[Date Index]
[Thread Index]
[Author Index]
Re: Re: problem writing debugging utility function
*To*: mathgroup at smc.vnet.net
*Subject*: [mg100463] Re: [mg100452] Re: problem writing debugging utility function
*From*: Leonid Shifrin <lshifr at gmail.com>
*Date*: Thu, 4 Jun 2009 06:33:49 -0400 (EDT)
*References*: <gvq09k$mqv$1@smc.vnet.net> <200905311037.GAA17048@smc.vnet.net>
Stonewall,
The Function command must obey the general rules of Mathematica evaluation.
When we indicate HoldAll as an explicit attribute, this tells Function how
to pass the arguments to its body - to evaluate them first or not. But the
HoldAll attribute implicit for Function is always there, and that just
assures that Function is at all able to do its work, such as variable
binding and name conflict resolution (Function is a lexical scoping
construct). Consider an example:
In[1] =
x = 10;
Function[x, x^2] /@ Range[5]
Out[1] = {1, 4, 9, 16, 25}
The <x> inside a function has nothing to do with a global <x>, exactly due
to the HoldAll attribute of Function: it allows Function to analyze its
arguments (I mean, the body - x and x^2 in this case) and do the name
collision resolution before using the arguments.
(there is a slight confusion in terminology here because Function is a
SubValues-based construct: Function[body][args], so when I mean arguments, I
mostly mean body :), because that's what is affected by the attributes of
Function). So, in a sense, the confusion arises because this is the case
when Function itself is a subject to the same logic.
Now, removing the HoldAll attribute from Function is equivalent to using
Evaluate on all its arguments:
In[2] = Function[Evaluate[x],Evaluate[x^2]]/@Range[5]
During evaluation of In[2]:= Function::flpar: Parameter specification 10 in
Function[10,100] should be a symbol or a list of symbols. >>
...
Out[2]=
{Function[10,100][1],Function[10,100][2],Function[10,100][3],Function[10,100][4],Function[10,100][5]}
The error messages are because the first argument of Function must be
variable name, or a list of variable names (for named variables), but <x>
now evaluates to its global value, and the action of Function[10,100] on any
argument is undefined and thus the expression is just returned (note by the
way that if we would know/be able to see the system (built-in) global
rules/definitions for Function, they would be SubValues, not DownValues). In
the following case:
In[3] =
Clear[y];
Function[Evaluate[y], Evaluate[x^2]] /@ Range[5]
Out[3] = {100, 100, 100, 100, 100}
It at least understands what to do since <y> has no global value and is a
symbol. In the latter case, formally the result would be the same if we make
a "normal" call:
In[4] = Function[y, x^2] /@ Range[5]
Out[4] = {100, 100, 100, 100, 100}
Tracing shows the difference in evaluation however:
In[5] = Function[Evaluate[y], Evaluate[x^2]][1] // Trace
Out[5] = {{{{x,10},10^2,100},Function[y,100]},Function[y,100][1],100}
In[6] = Function[y, x^2][1] // Trace
Out[6] = {Function[y,x^2][1],x^2,{x,10},10^2,100}
By the way, sometimes we may want to force the first (or both) of the
arguments of the Function (the variable name or list of names) to be
evaluated. This happens when we want to force Function perform the variable
binding with the exact variable names that we provide. One such case happens
when we have a list of variables (and possibly the rhs) separately:
In[7] =
Clear[x1,x2,x3]
vars = {x1,x2,x3};
expr = x1*x2*x3;
In[8] = {#, #[1, 2, 3]} &@Function[vars, expr]
Out[8] = {Function[vars, expr], x1 x2 x3}
In[9] = {#, #[1, 2, 3]} &@Function[Evaluate[vars], expr]
Out[9] = {Function[{x1, x2, x3}, expr], x1 x2 x3}
In[10] = {#, #[1, 2, 3]} &@Function[Evaluate[vars], Evaluate[expr]]
Out[10] = {Function[{x1, x2, x3}, x1 x2 x3], 6}
We see that in the latter case, we achieved the correct binding. I have to
add however that separating variables and body in such a manner can be error
prone and probably should be avoided in favor of safer techniques to achieve
the same goal. For example, if x1,x2,x3 would have global values, we are in
trouble:
In[11] =x1 = 1; x2 = 2; x3 = 3;
In[12]:= Function[Evaluate[vars],Evaluate[expr]]
During evaluation of In[100]:= Function::flpar: Parameter specification
{1,2,3} in Function[{1,2,3},6] should be a symbol or a list of symbols. >>
Out[12]= Function[{1,2,3},6]
One way to make this safer in this case is to wrap everything in Block:
In[13] =
x1 = 1; x2 = 2; x3 = 3;
Block[{x1, x2, x3}, {#, #[1, 2, 3]} &@
Function[Evaluate[vars], Evaluate[expr]]]
Out[13] = {Function[{x1, x2, x3}, x1 x2 x3], 6}
But this wouldn't save us if x1,x2,x3 would have global values at the moment
when we defined <expr> and <vars>. So it is best to avoid globals.
In[14] = Clear[x1,x2,x3];
Another class of situations where we may want to do this is when we want to
prevent variable renaming that normally happens during the name collision
resolution in nested scoping constructs. Here is a (rather contrived)
example from the top of my head:
In[15] = Module[{x}, Function[x, x^2]] // FullForm
Out[15] = Function[x,Power[x,2]]
In[16] = Module[{x}, Function[Evaluate[x], x^2]] // FullForm
Out[16] = Function[x$246,Power[x$246,2]]
We see that Function in the first case protects its variable which remains
just <x> (as a symbol name), while in the second it is given a name
generated by Module. When can this ever be useful? Well, if you use
introspection in your code (such as writing macros that analyze/transform
your code), then the second case can protect the code from what is called in
Lisp a "variable capture" - when several instances of <x> belonging to
different lexical scopes would mistakingly be considered by a macro to be
the same x, or similar problems.
Probably all these examples are appropriate to be categorized as advanced
techniques, so normally you don't want to play with Function in this manner.
But I think they clarify the role of internal (implicit) HoldAll that the
Function possesses.
To summarize: this internal HoldAll has nothing to do with the arguments
passed to the function Function[body][arguments]
(and, by the way, never could, because in expression f[x][y],
only the processing of <x> is affected by the attributes of <f>), but with
the <body> passed to the function <Function> itself, and is needed for the
correct operation of the Function itself. OTOH, correct processing of
<arguments> according to the attributes given explicitly in the <body> of
Function is a task of Function's implementation.
Hope this helps.
Regards,
Leonid
On Thu, Jun 4, 2009 at 12:34 AM, Stonewall Ballard <stoneyb at gmail.com>wrote:
> Leonid,
>
> This is a really good explanation of evaluation. I'm still struggling
> to internalize this, even after using Mathematica for years. I'm
> curious about one point you raised. In this example:
>
> > In[7] = Function[y, (Print["Just before calling f"]; f[y]),
> > HoldAll][Print["*"]]
> >
> > Just before calling f
> >
> > *
> >
> > Out[7]= {Hold[Null],Symbol}
>
> the result is different than when leaving off the explicit HoldAll:
>
> In[32]:= Function[y, (Print["Just before calling f"]; f[y])][
> Print["*"]]
>
> During evaluation of In[32]:= *
>
> During evaluation of In[32]:= Just before calling f
>
> Out[32]= f[Null]
>
> Yet the documentation for Function says:
> Function has attribute HoldAll. The function body is evaluated only
> after the formal parameters have been replaced by arguments.
>
> How is the explicit HoldAll attribute different from the inherent
> HoldAll? Why doesn't Function normally act as with the explicit
> HoldAll?
>
> Thanks.
>
>
Prev by Date:
**Re: what is my error?**
Next by Date:
**Re: Re: Re: RandomReal gets stuck**
Previous by thread:
**Re: problem writing debugging utility function**
Next by thread:
**Re: problem writing debugging utility function**
| |