Re: Re: problem writing debugging utility function
- To: mathgroup at smc.vnet.net
- Subject: [mg100839] Re: [mg100732] Re: problem writing debugging utility function
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Tue, 16 Jun 2009 21:49:08 -0400 (EDT)
- References: <gvq09k$mqv$1@smc.vnet.net> <200905311037.GAA17048@smc.vnet.net>
Hi Stoney, The key here that I didn't understand before is that the implicit > HoldAll attribute of Function applies to the arguments of Function, > not the resultant function. It's probably wrong of me to think that > Function[args, body] creates an object which is then applied to args. > Very lispy thinking. This is correct - Function[args,body] is just some symbolic expression which Mathematica does not know what to do with, so it is kept unevaluated (in the sense that there are no built-in DownValues defined for Function, or at least so it appears) > > > The attributes argument to Function is needed, then, because there's > no other way to set attributes for subvalues. This is not quite what I meant (if I understood your statement correctly). Attributes are always set for a given symbol, rather than for a given global rule, and affect only the evaluation of sub-expressions for which this symbol is a head in a given expression. If you give a HoldAll attribute to a symbol <f>, all we know is that in an expression f[x] <x> will be kept unevaluated (unless <x> has a head Evaluate), but we don't know whether f[x] will be used as an element of some other expression, like say f[x]+f[y] (which is more common, and then it will be rewritten if f has a DownValues definition matching unevaluated form of <x>), or as a composite head f[x][el1,el2,...], in which case f should have a SubValues - based definition for this to be rewritten into something else. What I mean is that the attributes of <f> govern the treatment of <x> in f[x], regardless of which of these two scenarios is realized. This is because the evaluation of expressions like f[g][h][x,y] is recursive, with all "higher" heads being completely evaluated before elements of the corresponding expression start to be evaluated, so f[g] evaluates completely, then f[g][h] evaluates completely, and then f[g][h][x,y] evaluates (this is a different recursion from that involved just in evaluation of general mathematica expressions, with the latter containing the former as a part of each of its recursive steps - we may call it "head recursion", and I agree that it adds to the complexity of Mathematica evaluator. I think though that the possibilities it opens have not been fully explored yet. In fact, I find it remarkable enough that you may in principle use these possibilities to implement pure functions (Function construct) themselves, from the more fundamental language constructs such as rewrite rules. In a sense, this is the answer to the question: Function itself is not a fundamental language feature, but something (that can be) implemented on top of the core language, and the internal HoldAll attribute is a part of that implementation). Here is, for the sake of example, a possible implementation of the simplest Function functionality (no attributes for arguments, no name conflict resolution with other scoping constructs, no anonimous arguments (slots), single argument syntax not supported, no diagnostic/error messages): Clear[myFunction]; SetAttributes[myFunction, HoldAll]; myFunction[argnames_List, body_][arguments__] /; Length[{arguments}] >= Length[Unevaluated[argnames]] := First[Hold[body] /. First[RuleDelayed @@@ Thread[Hold[ Evaluate[HoldPattern /@ Hold @@ Unevaluated[argnames]], Evaluate[ Take[Hold[arguments], Length[Unevaluated[argnames]]]]], Hold] /. Hold[x__RuleDelayed] :> Hold[{x}]]] This is perhaps too long and ugly, and can be done much better and shorter, but it suffices to illustrate the point. For example: In[1] = x=1;y=2; In[2] = myFunction[{x, y}, x + y][a, b, c] Out[2] = a+b You may change HoldAll for myFunction to HoldFirst or HoldRest, or remove it alltogether, and see what happens. Now, it is another implementation question how to make myFunction hold arguments <arguments> when we use a form myFunction[argnames,body,HoldAll][arguments] or other Hold attributes. The internal HoldAll present in myFunction will not by itself do it. So, coming back to the main discussion, should HoldAll attribute in Function be absent, and <argument names>, <body> inside Function would evaluate so that we have Function[<evaluated argument names>, <evaluated body>] even before we supply any actual arguments. Premature evaluation of argument names is bad since it will prevent the correct variable binding, while premature evaluation of <body> is equally bad since the body is not meant to be evaluated until variable binding is performed and actual arguments are passed as Function[arg names,body][arguments]. So, you may say that the internal HoldAll is needed since Function[arg names,body] is subject to the general procedure of Mathematica evaluation, while we want to prevent the evaluation of <arg names>, <body>. This has nothing to do with the actual parameters being passed to the pure function at a later point, and governs the steps happening "before" it in the evaluation procedure. Sorry if this is also what you meant and I just restated the obvious. Regards, Leonid > This is just another > part of the complexity cascade in Mathematica. For example: > > In[1]:= Clear[foo, bar] > > In[2]:= b = 5 > > Out[2]= 5 > > In[3]:= SetAttributes[foo, HoldAll] > > In[4]:= foo[b] > > Out[4]= foo[b] > > In[5]:= bar[b] > > Out[5]= bar[5] > > In[6]:= foo[b][b] > > Out[6]= foo[b][5] > > > ... > > 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 > wit= > h > > the <body> passed to the function <Function> itself, and is needed for > th= > e > > 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. > > Yes, indeed. Thanks. > > - Stoney >