MathGroup Archive 2009

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

Search the Archive

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
>


  • Prev by Date: Re: What should be a simple task....
  • Next by Date: Huge wide plot placing into a pane
  • Previous by thread: Re: problem writing debugging utility function
  • Next by thread: Re: can SendMail use HTML and embedded images