Re: What does & mean?
- To: mathgroup at smc.vnet.net
- Subject: [mg107237] Re: What does & mean?
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Sat, 6 Feb 2010 03:24:59 -0500 (EST)
- References: <201002041126.GAA29847@smc.vnet.net> <hkgks4$6p9$1@smc.vnet.net>
Richard, > > Leonid's confusion relates to the pseudo-definition of a "function" by > pattern matching using > > fn[arg_]:= ....... > > and the definition of a true function by > > fn= Function[{arg}], ......] or the brief but obscure ...#..& notation... > fn = ....#.... & > > There is a widely held but technically bogus equivalence in the minds > of Mathematica users, so Leonid's not alone.. > > In particular, there is no pattern matching going on in the fn= ... case, > and the SetAttribute[fn, HoldAll] has no effect whatsoever. > Can it be that you are not aware of the syntax of pure functions in Mathematica which allows to set Hold-attributes (Function[vars,body, HoldAll] for instance)? But more to the point. I think it is you who is being confused this time, at least regarding the main point and purpose of my post. I did not give any "explanation", but stated the behavior and demonstrated it. In my post, I did not attempt to compare pattern-defined and pure functions, I just stated one particular peculiarity of the interplay between evaluation and *pure* functions in Mathematica. If you'd care to look at the relevant sections of my book you'd see that I clearly state that pure and pattern-defined functions are very different and used for different purposes (In fact, I had a couple of examples similar to yours to illustrate this). Now, let me explain in more detail the point of my previous post to you and anyone else interested. First, I repeat my previous code to make it self-contained: In[2]:= ClearAll[fn]; SetAttributes[fn, HoldAll]; fn[arg_] := Switch[Head[Unevaluated[arg]], Print, "You want to print", Times, "You want to multiply", _, "I have no idea what you want to do"]; In[5]:= fn[Print["*"]] Out[5]= "You want to print" In[6]:= fn[#] &@Print["*"] During evaluation of In[6]:= * Out[6]= "I have no idea what you want to do" Now, please have a look at the FullForm: In[7]:= FullForm[fn[#]&] Out[7]//FullForm= Function[fn[Slot[1]]] What we see is that <fn> gets wrapped in a pure function. When parameters are passed to fn[#]&, there are two stages then. First, they are passed to an outer pure function Function, which in turn evaluates (or not, depending on its attributes) them and then calls <fn> as a (possibly part of) evaluation of its body, with these parameters. Second, parameters are then handed to <fn> (in evaluated form or not - this depends on the attributes of our external pure function), and their further evaluation is then governed by the attributes of <fn>. My point was that if we want parameters held, we must ensure this during both stages, while #-& based pure functions do not do that, since body[#]& is a short-hand for Function[body[Slot[1]], and this form of pure function does not imply Hold-attributes. We'd need Function[Null, body[Slot[1]],HoldAll] or Function[{par},body[par],HoldAll] (or other Hold-attribute) instead. Therefore, for pure functions expressed with #-& notation, parameters always get evaluated inside Function (stage 1) before they are used in evaluation of its body, regardless of the properties of the body (attributes of <fn> here). >From the end-user viewpoint, the pitfall is that if the user counts on <fn> holding its arguments and adds a seemingly innocent syntax fn[#]&, she is in for a big surprise. This is why I cited the relevant part of the documentation which states the equivalence of fn and fn[#]& and ignores this subtle point, potentially confusing the users who are unaware of this. Now, here is what is needed to avoid it: In[8]:= Function[Null, fn[#], HoldAll][Print["*"]] Out[8]= "You want to print" In this case, the presence of HoldAll in a pure function prevented evaluation of the passed parameter, and it safely "arrived" at <fn> in unevaluated form. But then again, this form of pure function requires Function and can not be expressed with #-&. In fact, there can be cases when this behavior is desirable, and this construct may be used intentionally. In the following toy situation, In[9]:= f[x_, y_] := (x - y)^2; In[10]:= Block[{f}, Hold[Evaluate[f[1 + 2 + 3, 4 + 5 + 6]]]] Out[10]= Hold[f[6, 15]] we used Block to get the result as above (partially evaluated), and Hold[Evaluate[]] construct to evaluate the body of Hold while <f> is blocked. The same can be achieved with #-& In[11]:= Block[{f}, Hold[#] &@f[1 + 2 + 3, 4 + 5 + 6]] Out[11]= Hold[f[6, 15]] This example is of course artificial, but there are more interesting cases where this trick is useful. Once again, the whole discussion is about peculiarities of *pure* function syntax and evaluation in Mathematica, and this has nothing to do with pattern-defined functions, which I just used in supporting code for convenience. Here is a version which does not use pattern-defined functions at all, but otherwise behaves in exactly the same way for the purposes of my discussion, and suits me just as well: In[12]:= fn1 = Function[{arg}, Switch[Head[Unevaluated[arg]], Print, "You want to print", Times, "You want to multiply", _, "I have no idea what you want to do"], HoldAll]; In[14]:= fn1[#] &@Print["*"] During evaluation of In[14]:= * Out[14]= "I have no idea what you want to do" In[15]:= Function[Null, fn1[#], HoldAll][Print["*"]] Out[15]= "You want to print" To my mind, this explanation should have left no room for further ambiguities, both in terms of what happens and what I meant. By the way, I encountered this kind of effects all too many times in practice, so this is not something I am just theorizing about. Finally, I have a stylistic suggestion that before you publicly post other messages dismissing some other poster's comments in such a definitive tone, you first care to study the case under discussion and those posts more thoroughly than you did it this time. I highly respect you for being one of the Lisp / CS experts, and I'd prefer to keep it that way. Regards, Leonid > > (aside: Programming with "pure functions" in Mathematica follows from its > heritage in Lisp, where Function[{x,y},x+y] or #1+#2& more briefly, would > be written as (lambda(x y)(+ x y)). Further use of pure functions can be > viewed in the literature on Lisp. ) > > To see that the two forms are different most simply, try > > f[x_]:=Hello[x] > g=Hello[#]& > > f[1] is the same as g[1], namely Hello[1] but > > f[1,2,3] returns Hello[1] > g[1,2,3] returns g[1,2,3] > >
- Follow-Ups:
- Re: Re: What does & mean?
- From: Canopus56 <canopus56@yahoo.com>
- Re: Re: What does & mean?
- References:
- Re: What does & mean?
- From: Bill Rowe <readnews@sbcglobal.net>
- Re: What does & mean?