Message Boards Message Boards

Why are globals interfering with local variables in Module?

GROUPS:

I want to have a list of expressions that are to be evaluated in a module. So as not to have the variables in the input expressions take on global values, the plan is to input the expressions as strings. Here is a simplified program of the problem:

 In[902]:= a = 5

test1[vars_List] := Module[{a, b, c, d, f},
  Print["a = " a, "   b = ", b];
  ToExpression@vars
  ]

In[904]:= test1[{"a+b+c ", "d+a+f"}]

During evaluation of In[904]:= a =  a$309722   b = b$309722

Out[904]= {5 + b + c, 5 + d + f}

Why is the local 'a' in the Module taking on the global value?

POSTED BY: Eric Johnstone
Answer
6 months ago

A simplified example might be

In[1]:= a = 1; 
        Module[{a = 2}, ToExpression["a"]]

Out[2]= 1

According to the documenation, "Before evaluating expr, Module substitutes new symbols for each of the local variables that appear anywhere in expr ..."

In this case, the variable a does not appear anywhere in the body of the Module (the string "a" does) and therefore nothing gets substituted.

In other words, Module returns ToExpression["a"] which evaluates to a which evaluates to 1 -- outside the Module.

POSTED BY: Ilian Gachevski
Answer
6 months ago

Thanks, Ilian.

Yes, I see that now in the details of Module, although it took a few readings to understand it. So 'a' has to exist in the expression already in order for the local variables to apply.

Do you have any idea just how you would input an expression into Module?

Eric

POSTED BY: Eric Johnstone
Answer
6 months ago

Do you have any idea just how you would input an expression into Module?

That would depend on why you want to do this. In some cases, you can use Block, which uses dynamic scoping. Basically, Block temporarily removes any definitions associated with the localized symbols. However, the symbols are still the very same ones both inside and outside Block—they just don't have their definition until the Block exits.

POSTED BY: Szabolcs Horvát
Answer
6 months ago

I feel that there must be a story behind your question, and the best solution really depends on what bigger problem you are trying to solve.

Suppose that you are taking some input from a user, which should be a mathematical expression with arbitrary symbols in it. You need to prevent any symbols in this expression from conflicting with any other symbols currently present in your Mathematica session. One possible solution is to isolate them into their own special context:

In[11]:= Block[{$ContextPath = {}, $Context = "myCont`"},
 ToExpression["a+b"]
 ]

Out[11]= myCont`a + myCont`b

In[12]:= Block[{$ContextPath = {}, $Context = "myCont`"},
 ToExpression["a+Plus"]
 ]

Out[12]= myCont`a + myCont`Plus
POSTED BY: Szabolcs Horvát
Answer
6 months ago

Thanks, Szabolcs.

Well, the story behind my question is that I'm developing an environment for working with Boolean algebra in an engineering context. I've been fascinated by Boolean algebra since I read Boole's Laws of Thought when I was sixteen. I'm seventy now and I've used Boolean algebra (working by hand) to design circuits all my working life. This is a retirement project, so it's just for fun.

At the moment, I'm working on getting the sequential equations to step through their states. Here is what is working now:

In[105]:= a = 5

Out[105]= 5

In[106]:= SetAttributes[test1, HoldAll]

In[107]:= 
test1[expr_] := 
 Block[{output, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o},
  b = 23;
  c = expr /. {Plus -> Times, Times -> Plus};
  output = Print[c];
  c
  ]

In[108]:= test1[a + a (b + a + (k + 7) z^3)] 

During evaluation of In[108]:= a (a+23 a (7 k+z^3))

Out[108]= 5 (5 + 115 (7 k + z^3))

In[109]:= b

Out[109]= b

My variables are any of the lower-case letters plus their inverted forms (with an overbar). I found that I could declare them in the block and input expressions as I want. If I don't decare them first, this happens:

In[116]:= a = 5

Out[116]= 5

In[117]:= SetAttributes[test1, HoldAll]

In[118]:= test1[expr_] := Block[{output},
  b = 23;
  c = expr /. {Plus -> Times, Times -> Plus};
  output = Print[c];
  c
  ]

In[119]:= test1[a + a (b + a + (k + 7) z^3)] 

During evaluation of In[119]:= 5 (5+28 (7 k+z^3))

Out[119]= 5 (5 + 28 (7 k + z^3))

In[120]:= b

Out[120]= 23

So the global value of a is used and the global value of b is set.

I'll investigate the context solution.

Eric

POSTED BY: Eric Johnstone
Answer
6 months ago

Group Abstract Group Abstract