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. > >