I'm skeptical of the built-in debugger because it seems to crash the
kernel often, so I do most of my debugging by inserting print
statements like
Print["variableOne = ",variableOne].
Being extraordinarily lazy I soon thought it might be nice to have a
little function, say dbgv, which takes a variable or name of a
variable as an argument, and produces the same result as the print
statement above.
At first I assumed this would be easy, since almost every programming
problem turns out to be pretty easy with Mathematica. But after an hour
or so I began to wonder whether it would be possible at all. I did
eventually find a solution, a function dbgv such that dbgv[variableOne]
produces exactly the effect of the print statement, but it's really ugly.
I'll post it later.
Granted this is not an important problem since it's not too much
trouble to just type in the whole print statement. But it's worth
noting that this would trivial to solve with a Lisp macro, and despite
the fantastic expressibility of Mathematica it doesn't seem to have a
good replacement for macros. The closest equivalents are $Pre(Read),
which I used in my solution, but they're not nearly as nice to work with.
Can anyone think of an elegant solution?
the way to do it is to use non-standard evaluation. Here is the function
that probably does what you want
In[1] =
SetAttributes[ShowIt, HoldAll];
ShowIt[code_] :=
Module[{y},
Print[ToString[Unevaluated[code]], " = ", y = code];
y];
This will print the variable name, its value, and then return the variable
value itself so that you can use it in your code, just as before - you just
need to "stick" ShowIt in the place where you need to print the info. The
parameter of the function does not necessarily have to be a variable - you
can wrap it around any piece of code (there could be a few subtleties if
your code also uses non-standard evaluation, but this is rarely the case).
Note that we take care that the code (<code>) is executed only once, so the
case of side effects (like i++ etc) is handled correctly. Example:
In[2] =
Block[{i, res = Table[0, {5}]},
For[i = 1, i <= 5, i++,
res[[i]] = ShowIt[i]];
res]
i = 1
i = 2
i = 3
i = 4
i = 5
Out[2] = {1,2,3,4,5}
>But it's worth
>noting that this would trivial to solve with a Lisp macro, and despite
>the fantastic expressibility of Mathematica it doesn't seem to have a
>good replacement for macros.
This is just not true. The ShowIt function above *is* a macro, since, due to
the HoldAll attribute, it expands the code before it is run. As another very
simple macro example, consider this:
ClearAll[withCodeAfter];
SetAttributes[withCodeAfter,HoldRest];
withCodeAfter[before_,after_]:=(after;before);
This macro can be used to avoid an introduciton of auxilliary variable in
case
when the result is computed somewhere in the middle of the code (by the
<before> piece), but when some other code must be executed (<after> piece),
before the result is returned. Example:
In[3] =
Clear[i];
i = 0;
withCodeAfter[Print[i], i++]
0
In[4] = i
Out[4] = 1
The availability of macros in Mathematica is apparent from the fact that all
the code we write is data as well (as can be seen by the FullForm command),
and the availability of non-standard evaluation. This fact is obscured by
the built-in pretty-printer/preprocessor which allows us to use shortcut and
infix notation.
However indeed there are a few reasons that make macros harder to write in
Mathematica:
a) Evaluator is more complex, than in Lisp. There are several kinds of
global rules, there are attributes, there are several ways to make
evaluation non-standard, there are built-in rules for system functions that
the user may not be aware of, there is dynamic scoping with Block that is
very powerful but can be easily abused, there are several lexical scoping
constructs (Module, With, Function, SetDelayed, etc) and associated with
them rules for variable collision resolution, etc, etc. It is harder to
"compute" the consequences of the macro expansion, or to get it right in all
cases of intended use.
b) Pattern-matching gets in the way when some portion of the code is
rule-based, since evaluation depends on whether or not some patterns match.
c) This is a consequence of b): when we define a function with restricted
patterns such as f[x_Integer]:=... etc, we effectively introduce a (weak)
typing,
which also gets in the way.
d) It requires conscious effort not to use (at all) short-hand and/or infix
notation, which is handy but often hides that the code may expressed as an
expansion of some macro.
I think it will generally be very nice if macros would find their way into
the mainstream Mathematica programming, but this will probably start to
really pay off for those who intend to use Mathematica to build rather
large/complex systems (or their prototypes).
Best regards,
Leonid
On Fri, May 29, 2009 at 5:57 PM, dabr...@indiana.edu
<dabr...@indiana.edu>wrote:
For a function that works like the Print expression above, one could use
one of the following:
Non-string version:
SetAttributes[dbg, HoldAll]
dbg[var_] := Print[ToString[Unevaluated[var]], " = ", var]
String version:
dbg2[name_String] :=
ToExpression[name, InputForm, Print[name, " = ", #] &]
Though I am not sure I understand your question because I don't see what
relation $Pre or Read have with this.
For debugging, take a look at Trace, On[] and Off[], and Monitor as well.
SetAttributes[printVariable,HoldAll]
printVariable[var_]:=Print[ToString[Unevaluated[var]]," = ",var]
?
Regards
Jens
ape = 1;
printVariable[ape]
Out: ape = 1
Cheers -- Sjoerd
On May 30, 2:57 am, "dabro...@indiana.edu" <dabro...@indiana.edu>
wrote:
> This matter is pretty unimportant, but perhaps of interest in laying
> out a persistent source confusion for me with Mathematica: evaluation
> control.
>
> I'm skeptical of the built-in debugger because it seems to crash the
> kernel often, so I do most of my debugging by inserting print
> statements like
>
> Print["variableOne = ",variableOne].
>
> Being extraordinarily lazy I soon thought it might be nice to have a
> little function, say dbgv, which takes a variable or name of a
> variable as an argument, and produces the same result as the print
> statement above.
>
> At first I assumed this would be easy, since almost every programming
> problem turns out to be pretty easy with Mathematica. But after an hou=
Ken Levasseur
http://homepage.mac.com/klevasseur/
On May 29, 2009, at 8:57 PM, dabr...@indiana.edu wrote:
> This matter is pretty unimportant, but perhaps of interest in laying
> out a persistent source confusion for me with Mathematica: evaluation
> control.
>
> I'm skeptical of the built-in debugger because it seems to crash the
> kernel often, so I do most of my debugging by inserting print
> statements like
>
> Print["variableOne = ",variableOne].
>
> Being extraordinarily lazy I soon thought it might be nice to have a
> little function, say dbgv, which takes a variable or name of a
> variable as an argument, and produces the same result as the print
> statement above.
>
> At first I assumed this would be easy, since almost every programming
> problem turns out to be pretty easy with Mathematica. But after an
> hour
SetAttributes[ShowIt, HoldAll];
ShowIt[code_] :=
Module[{y},
Print[ToString[Unevaluated[code]], " = ", y = code];
y];
My own solution was the hideous
$PreRead=ReplaceAll[#,{{"dbgv","[",var_,"]"}:>{"Print","[",RowBox
[{"\""<>var<>" = "<>"\"",",",var}],"]"}}]&;
which makes dbgv work like a macro. The grotesqueness is because what
$PreRead sees is a very raw input form, with expressions broken down
into RowBox's. In a sense this is the most direct analog to Lisp's
macros, but ... yechh.
The Unevaluated[] function had slipped off my radar, probably because
I never fully grokked the distinction between it and Hold[]. In fact
I'm still a bit confused about it. At first I thought it might like
the evaluation inhibitor ` in Lisp, but some examples disabused me of
that.
In[2]:= f@Unevaluated[5 + 6 + 7 + 8]
Out[2]= f[Unevaluated[5 + 6 + 7 + 8]]
In[11]:= ToString@Unevaluated[5 + 6 + 7 + 8]
Out[11]= "5 + 6 + 7 + 8"
I might have expected Out[11]= "Unevaluated[5 + 6 + 7 + 8]"
In[13]:= sqr[x_] := x^2
In[14]:= sqr@Unevaluated[5 + 6 + 7 + 8]
Out[14]= 676
I might have expected Out[14]= sqr[5 + 6 + 7 + 8] since sqr does not
know what to do with the pattern _+_+_+_ or _+_ for that matter.
Could anyone elucidate this for me?
Unevaluated[] is treated in a special way during evaluation. There's
a good explanation of what it does in the docs, under 'More
information':
"f[Unevaluated[expr]] effectively works by temporarily setting
attributes so that f holds its argument unevaluated, then evaluating f
[expr]."
http://reference.wolfram.com/mathematica/ref/Unevaluated.html
There's also a very detailed explanation somewhere in the docs of how
exactly expressions are evaluated by the kernel. You can look that up
if you're interested.
It's no wonder if you're confused about Unevaluated/Hold/etc. and
evaluation order. They can be confusing. People are usually pointed
to the paper titled 'Working with Unevaluated Expressions' by Robby
Villegas. There's a link to it here:
echo[x_] := Print[ToString@HoldForm@x, " = ", x]
Bobby
On Fri, 29 May 2009 19:57:49 -0500, dabr...@indiana.edu
<dabr...@indiana.edu> wrote:
Just to add some more to the reply of Szabolcs:
The evaluation process in Mathematica is recursive, going first "down" to
leaves, then evaluating it "up", starting from leaves and going to larger
sub-expressions, checking for the global rules to match. Unevaluated is
treated in a special way in that it suppresses the evaluation of expression
"on the way down", allowing the rules attached to the head (say <g>)
surrounding it to apply "on the way up" on the original expression. The
original expression may or may not evaluate later, depending on what <g>
does with its argument. In the following example:
In[1] =
g[x_ + y_] := x*y;
g[Unevaluated[5 + 5]]
Out[1] = 25,
the rule attached to <g> did apply since the expression 5+5 was preserved in
its unevaluated form. In this case, the original expression (Plus operator)
never evaluated, but in some other cases it may evaluate - it all depends
on <g> now. But without Unevaluated, <g> would never have a chance to see
the original expression, since by the time evaluation goes "up" to g, 5+5
would have evaluated to 10 already. This situation indeed is precisely as if
we would give <g> Hold attribute "on the way down" and remove it "on the way
up".
There are several differences between Hold and Unevaluated. Technically,
Hold is just a wrapper with a HoldAll attribute which is not particularly
different from any user-defined HoldAll wrapper, and is special just because
it is the "official" holding wrapper and there are commands such as
ReleaseHold that work with it together. Most of the functionality of Hold
can pretty much be duplicated/reproduced by any HoldAll wrapper. OTOH,
Unevaluated is one of the "magic symbols", along with Evaluate and Sequence.
It is more deeply "wired in", into the main evaluation loop algorithm, and
its functionality can not be removed, blocked or duplicated. In particular,
we may block Hold with a Block trick Block[{Hold},...], but we can not block
Unevaluated in the same way.
Another difference is that (one level of wrapping with) Unevaluated does not
by itself represent extra level of wrapping - it is automatically stripped
off when the evaluator comes to apply the rules to expression inside it. Not
so with Hold - it is a normal wrapper.
>From the viewpoint of the user, the uses of Hold and Unevaluated are also
different. Hold is often used to preserve the internal expression
unevaluated for more than one successive evaluation (or in between such
evaluations). For example, if one function (say <f>) produces the result as
an expression which wil normally evaluate but whose evaluation we want to
prevent, and another function (say <h>) needs to consume this result in this
unevaluated form, but the result is not passed directly from <f> to <h>,
then <f> may wrap the result in Hold and <h> will then have to unwrap it.
Unevaluated would not help us here since it is normally used in a single
evaluation. Here is a simple example:
In[2] =
Clear[f,h];
f[x_] := Module[{y}, y = Hold[x^2]];
h[x_Hold] := x /. Hold[a_^b_] :> {a, b}
In[3] = odd = Select[f /@ Range[10], Not[FreeQ[#, _?OddQ]] &]
Out[3] = {Hold[1^2], Hold[3^2], Hold[5^2], Hold[7^2], Hold[9^2]}
In[4] = h /@ odd
Out[4] = {{1, 2}, {3, 2}, {5, 2}, {7, 2}, {9, 2}}
What happens here is that <f> constructs some power (square) while <h>
deconstructs it to base-power pair. But <h> is not called directly on the
result of <f>, so we need to prevent expressions from evaluation in between
evaluations involving <f> and <h>. Unevaluated would not be helpful here.
Another thing worth mentioning (and more directly relevant to your example)
is the mechanics of argument - passing. Consider this function:
In[5] =
Clear[f];
f[x_] := {Hold[x],Head[x]};
It is supposed to return the held input together with its head . Let us try
In[6] = (Print["Just before calling f"]; f[#]) &[Print["*"]]
*
Just before calling f
Out[6]= {Hold[Null],Symbol}
If we attempt to force it to not evaluate the argument (Printing), in this
way:
In[7] = Function[y, (Print["Just before calling f"]; f[y]),
HoldAll][Print["*"]]
Just before calling f
*
Out[7]= {Hold[Null],Symbol}
We see that the result was indeed not evaluated before having been passed to
<f>, but it was evaluated in <f>, and the r.h.s of <f> uses an already
evaluated result. Now, it is to prevent also this evaluation of the
argument that we need Unevaluated:
In[8] =
Function[y, (Print["Just before calling f"]; f[Unevaluated[y]]),
HoldAll][Print["*"]]
Just before calling f
*
Out[8] = {Hold[Print["*"]], Symbol}
We see that the printing still takes place, and while the held part is ok,
the head part still computes the Head of the evaluated argument (that's
where the printing happens). This is because this time, Head needs
Unevaluated - we redefine <f>:
In[9] =
Clear[f];
f[x_] := {Hold[x],Head[Unevaluated[x]]};
In[10] =
Function[y, (Print["Just before calling f"]; f[Unevaluated[y]]),
HoldAll][Print["*"]]
Just before calling f
Out[10]= {Hold[Print[*]],Print}
Now we get what we want. Hopefully by this moment the pattern started to
emerge. Note that Unevaluated is unnecessary if the function itself holds
its argument, possessing one of the hold attributes:
In[11]=
ClearAll[f];
Attributes[f] = {HoldAll};
f[x_] := {Hold[x], Head[Unevaluated[x]]};
In[12] =
Function[y, (Print["Just before calling f"]; f[y]), HoldAll][Print["*"]]
Just before calling f
Out[12]= {Hold[Print[*]],Print}
It is slightly off the main line of the argument, but another common
pitfall associated with this sort of things is something like this:
In[13] = {Hold[#] &[5^2],Hold[5^2]}
Out[13] = {Hold[25],Hold[5^2]}
The #-& notation is so routinely used that one often forgets that it does
introduce an additional parameter-passing stage. This is what one should use
to avoid evaluation during that stage:
In[14] = {Function[Null, Hold[#], HoldAll][5^2], Hold[5^2]}
Out[14] = {Hold[5^2], Hold[5^2]}
Sometimes the opposite is needed however:
In[15]:=
i = 0;
Function[x, {x, x, x}, HoldAll][i++]
Out[15]= {0, 1, 2}
In[16] = i
Out[16] = 3
In[17]:=
i = 0;
Function[x, {x, x, x][i++]
Out[17]= {0, 0, 0}
In[18] = i
Out[18] = 1
In this case, chances are that the first behavior is not what was intended.
So, to summarize: Hold is mostly useful to prevent evaluation of some
results, in between some other evaluations. Unevaluated in useful to force
some function use - just once, in this particular evaluation (for its
r.h.s.) - its original (unevaluated) argument if that function does not
have a corresponding hold attribute. Hold attributes are useful for the same
thing, but 1) They are permanent, not just one-time use 2) Unevaluated
wrappers are stripped off when evaluator meets them "on the way up", so
subsequent evaluation uses already normal version of the argument - not so
with attributes 3) You may need to work with functions written by others (or
system functions), for which changing attributes even temporarily may have
undesired/unpredictable consequences - in this case Unevaluated is more
appropriate, to make up for the lacking hold attribute just once. Perhaps,
another way to put is is that attributes belong to the function, while
Unevaluated "belongs" to a particular argument (though affecting the
execution of the function on that argument as if that function had a hold
attribute).
This is probably a very long-winded way to explain these things, but I hope
it will still clarify some issues.
Best regards,
Leonid
On Sun, May 31, 2009 at 3:37 AM, dabr...@indiana.edu
<dabr...@indiana.edu>wrote:
> Thanks a lot to Leonid, Szabolcs, and Ken for their solutions. I
> liked Leonid's the best, being both much simpler and more general than
> mine.
>
> SetAttributes[ShowIt, HoldAll];
> ShowIt[code_] :=
> Module[{y},
> Print[ToString[Unevaluated[code]], " = ", y = code];
> y];
>
> My own solution was the hideous
>
> $PreRead=ReplaceAll[#,{{"dbgv","[",var_,"]"}:>{"Print","[",RowBox
> [{"\""<>var<>" = "<>"\"",",",var}],"]"}}]&;
>
> which makes dbgv work like a macro. The grotesqueness is because what
> $PreRead sees is a very raw input form, with expressions broken down
> into RowBox's. In a sense this is the most direct analog to Lisp's
> macros, but ... yechh.
>
-- David
P.S. Now please write a description of the entire Mathematica REPL with the
same clarity and level of detail! Self-publish it on Amazon or Lulu - I'll
buy a copy and I bet most of the mathgroup list would too!
On Tue, Jun 2, 2009 at 3:42 AM, Leonid Shifrin <lsh...@gmail.com> wrote:
> Hi,
>
> Just to add some more to the reply of Szabolcs:
>
<... lots of GOOD STUFF omitted ...>
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.
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
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.
The attributes argument to Function is needed, then, because there's
no other way to set attributes for subvalues. 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
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