Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a massive amount of code with lots of Table and Sum inside a Module. Each with their own iterators, and I have completely lost track of all of them. But if the user calls the function with an argument matching the name of the iterator, the code no long works as intended.

An example is this function that is supposed to return a list of three repeated symbols:

function[x_] := 
Module[{},
  answer = Table[x, {i, 1, 3}];
  Return[answer];
]

For example:

function[a]
(*{a,a,a}*)

But this can be broken by

function[i]
(*{1,2,3}*)

Obviously, Table is confusing the input x=i with its own iterator i. What is the fool-proof fix for this? Is there a solution without:

  1. Finding the names of all the iterators and listing them all as private variables inside Module?

  2. Finding all the iterators and renaming them longAndComplicated1, longAndComplicated2, etc.?

share|improve this question
    
Maybe \[FormalI] ? –  b.gatessucks Aug 23 at 21:16
    
@b.gatessucks If you are proposing using Formal Symbols for the Table iterators I think that would actually make the situation worse. In most evaluation it can be assumed that Formal Symbols will not have assigned values, but Table will not respect the Protected attribute therefore it will (temporarily) gives value to Formal Symbols. In my opinion that is even more confounding. –  Mr.Wizard Aug 24 at 2:31
    
@Mr.Wizard Thanks for the explanation, I didn't know about the Protected issue. –  b.gatessucks Aug 24 at 8:21

3 Answers 3

up vote 5 down vote accepted

Make use of Module's capability to localize variables.

f[x_] := Module[{i}, Table[x, {i, 1, 3}]]
f[i]
{i, i, i}

Also, with i localized, you don't need to use distinct iterator names in different iteration constructs.

g[x_] :=
  Module[{i, a, b},
    a = Table[x, {i, 3}];
    b = Table[x^3, {i, 2}];
    {a, b}]
{g[i], g[a], g[b]}
{{{i, i, i}, {i^3, i^3}}, 
 {{a, a, a}, {a^3, a^3}}, 
 {{b, b, b}, {b^3, b^3}}

Further, note that you don't need to use Return if you use the semicolon ( ; ) operator properly. (Yes, semicolon is an operator in Mathematica, not a terminator.) See this answer for more information on the semicolon operator. Actually, it likely you will benefit from all answers given on the page I have linked to.

share|improve this answer
    
Thanks! Where can I find more information on when I must use the 'Return' function? –  QuantumDot Aug 24 at 9:48
    
@QuantumDot. That is a very good question. I think it deserves own posting, so I have done so and given my answer which is way too long for a comment anyway. –  m_goldberg Aug 24 at 14:20

Table and Sum scope their variables in the manner of Block. Effectively your code is like this:

f[x_] := Block[{i = 5}, x]

f /@ {a, i}
{a, 5}

This is actually a very useful aspect of Table but in this case it is also the source of your problems.

Since you must localize the iterators one of the best solutions is the one you reject out of hand which is to put all iterator variables in the Module specification. Perhaps some meta-programming with satisfy you:

SetAttributes[localize, HoldAll]

localize[(s : Set | SetDelayed)[LHS_, RHS_]] :=
  Union @@ Cases[Unevaluated@RHS, (Table | Sum)[_, x__] :> Hold[x][[All, 1]], {0, -1}] //
    Pick[#, #, _Symbol] /. _[x__] :> s[LHS, Module[{x}, RHS]] &

To use it wrap your definition in localize:

localize[
  ff[x_] := {Sum[x, {i, 4}], Table[x, {i, 3}, {j, 2}]}
]

Test:

ff[i]
{4 i, {{i, i}, {i, i}, {i, i}}}

The definition we created:

Definition[ff]

enter image description here

share|improve this answer

If I understand correctly, your problem is that you do not want to have to comb through this block of code manually to find which variables are being used as iterators. Fortunately, you can do this with pattern matching.

Say we have this definition:

ClearAll@"Global`*";

function[x_] :=
 Module[{},
  notanswer = Sum[j^2, {j, 10}];
  answer = Table[x, {i, 1, 3}];
  answer];

You can work with the definition programmatically using DownValues.

Evaluate@DownValues@function // Inactivate;

I have used Inactivate to avoid any undesired evaluation. Now, you can search this expression for structures that include iterators:

Cases[%,
  iter : IgnoringInactive[_Table | _Sum] :> iter[[2, 1]], 
  Infinity] // Union

{i, j}

Then you can just plop that into the first argument of Module.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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