MathGroup Archive 1990

[Date Index] [Thread Index] [Author Index]

Search the Archive

Parameter passing "feature" is correct!

David Jacobson writes:

> When a function has the HoldAll (or HoldFirst or HoldRest) attributes,
> there are possible name conflicts between symbols in actual parameters
> (arguments) and local variable declared in blocks...

Quite true.  Mathematica's evaluation strategy is (at least 80% of the
time) pure textual substitution and term-rewriting.  In the example below,
"foo[z]" causes the pattern variable "x" to match the "z" (which is not
rewritten because of the "HoldAll" attribute).  The MEANING of the ":="
is that whatever is matched by the pattern variables on the left-hand
side is substituted for those variables on the right-hand side.
Thus "foo[z]" is rewritten to "{Block[{z=3},z],z}".  After that rewriting
happens, "foo" (and its "HoldAll" attribute) are no longer part of the
expression, so further rewriting can now happen.  The first element of
the list has "z" inside a Block in which "z" has the value 3, so that
"z" rewrites to 3 (this rewriting is what it MEANS in Mathematica for
"z" to "have the value 3").  The second element is not inside a block,
so the "z" there gets rewritten according to the global rules, which
give "z" the value 1.

> I'm not sure this is a bug, ...

It's not.  I suppose you could claim that it's a "design misfeature",
but Mathematica IS DOING what it's documented to do.  This is why there
are "Contexts" in the language.  Compare the behavior of "foo" to
that of "bar" below.  Once again the "z" in "bar[z]" is not rewritten
immediately because of a "HoldAll" attribute.  But this time "bar[z]"
gets rewritten to "{Block[{Private`z=3},{z,Private`z}],{z,Private`z}}".
Now a "z" in the context "Private`" is NOT the same symbol as a
"z" in the (default) context "Global`", so the rule on "Private`z"
inside the Block does not affect the "z" that was passed in as the
argument to "bar".  The result is that of the two distinct "z"'s
inside the Block, the first one gets rewritten according to the
rules for "Global`z", so it becomes a 1, while the second gets
rewritten according to the rules for "Private`z", so it becomes a
3.  The two "z"'s in the second sublist are in the scope of the
global rules only, not inside a Block, so the first one ("Global`z")
gets rewritten to 1 as before, but the second one ("Private`z")
does not get rewritten at all, because the global rule base contains
no rules for the symbol "Private`z".

Of course, the usual way of putting symbols into a different context
than "Global`" is not to write the fully-qualified names with explicit
context prefixes, but to use "Begin[]" or "BeginPackage[]" to tell
the parser to use a different context as default until the corresponding
"End[]" or "EndPackage[]".  The parser interprets symbol names not explicitly
qualified by a context prefix as belonging to the context named by the
current value of "$Context", which is affected by "Begin[]", "BeginPackage[]",
"End[]", and "EndPackage[]".

In[1]:= SetAttributes[foo, HoldAll]

In[2]:= foo[x_] := { Block[{z=3},x], x }

In[3]:= foo[1]

Out[3]= {1, 1}

In[4]:= z=1; foo[z]

Out[4]= {3, 1}

In[5]:= SetAttributes[bar, HoldAll]

In[6]:= bar[x_] := { Block[{Private`z=3}, {x,Private`z} ], {x,Private`z} }

In[7]:= z

Out[7]= 1

In[8]:= bar[z]

Out[8]= {{1, 3}, {1, Private`z}}

In[9]:= bar[1]

Out[9]= {{1, 3}, {1, Private`z}}

I hope this explanation causes more understanding than confusion!

--Cameron Smith
  Mathematica programming consultant
  CAMERON at MIDD.BITNET  --or--  cameron at

  • Prev by Date: Mathematica Conference attendance
  • Next by Date: Mathematica Conference
  • Previous by thread: Mathematica Conference attendance
  • Next by thread: Mathematica Conference