9
$\begingroup$

For reusable code it's good practice to use Module[] to localize iteration variables used by Table[], as explained by this post.

Is it possible to use some Hold / ReleaseHold gymnastics to write a function ModuleTable[] which behaves like this?

ModuleTable[f[i], {i, 1, 10}]

gets automatically expanded into

Module[{i}, Table[f[i], {i, 1, 10}]]
$\endgroup$
4
  • 3
    $\begingroup$ In the simplest case of a single iteration variable, what you ask for is as simple as SetAttributes[ModuleTable, HoldAll]; ModuleTable[code_, iter : {var_, __}] := Module[{var}, Table[code, iter]]. Generalizing to several iteration variables is not hard either. $\endgroup$ Apr 21, 2021 at 21:54
  • $\begingroup$ Thanks for the answer. I figured out how to handle any number of iterations. SetAttributes[ModuleTable, HoldAll]; ModuleTable[code_, iters : ({_, __} ..)] := Module[Evaluate[{iters}[[All, 1]]], Table[code, iters]]; $\endgroup$
    – felix
    Apr 22, 2021 at 10:16
  • 2
    $\begingroup$ @felix not so simple though, try i = 5; ModuleTable[i, {i, 10}] $\endgroup$
    – Kuba
    Apr 22, 2021 at 10:34
  • $\begingroup$ @Kuba You're right. Do you have a quick solution? It's easy to deal with a fixed number of 2 iterations, 3 iterations etc., but I haven't figured out how to do it for an arbitrary number of iterations. $\endgroup$
    – felix
    Apr 22, 2021 at 10:46

1 Answer 1

10
$\begingroup$

Here is one way to do this for arbitrary number of iterators:

ClearAll[ModuleTable]
SetAttributes[ModuleTable, HoldAll];
ModuleTable[code_, iters__List] :=
  Replace[
    DeleteCases[Hold[iters][[All, 1]], Except[_Symbol]], 
    Hold[vars__] :> Module[{vars}, Table[code, iters]]
  ]

where DeleteCases was necessary since iterators may not include a symbol. The main device to control code evaluation, used here, is called injector pattern on this site (you can search for this term to see other examples of its use).

For example:

ClearAll[a, b]
a = 1;
b = 2;
ModuleTable[a + b, {a, 1, 3}, {2}, {b, 2, 5}]

(* {{{3, 4, 5, 6}, {3, 4, 5, 6}}, {{4, 5, 6, 7}, {4, 5, 6, 7}}, {{5, 6, 7, 8}, {5, 6, 7, 8}}} *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.