Re: Help with HoldAll needed
- To: mathgroup at smc.vnet.net
- Subject: [mg100908] Re: [mg100891] Help with HoldAll needed
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Thu, 18 Jun 2009 04:51:17 -0400 (EDT)
- References: <200906170845.EAA08859@smc.vnet.net>
Hi Erich, Short answer: use Hold instead of Unevaluated: In[1] = ClearAll[MyFun]; SetAttributes[MyFun, HoldAll]; MyFun[x_] := Hold[x]; (in this example this means that you could bypass MyFun step and start with Hold[2=3] from the beginning), and rules to deconstruct expressions: In[2] = MyFun[2 = 3] /. HoldPattern[a_ = b_] :> a Out[2] = Hold[2] It is actually safer and easier to keep your expression wrapped in Hold and use rules rather than play with attributes and evaluation. A more interesting example: In[3] = code = Hold[Module[{a = 1, b, c = 2, d}, Print[a, b, c, d]]] In[4] = moduleVars = Cases[code, HoldPattern[ Module[x_List, body_]] :> (Hold[x] /. HoldPattern[Set[y_Symbol, rhs_]] :> y), Infinity] Out[4] = {Hold[{a, b, c, d}]} Here we used this technique to introspect Module and extract variables declared in it, in held form. Now, a few remarks on your attempt: 1. If you really want to play games with evaluation, do yourself a favor and read some detailed account on Mathematica evaluator, such as "Mathematica Internals" by David Withoff (WRI technical report, available online at Wolfram Library Archive), or a book by David Wagner (unfortunately, out of print) - this will save you hours of frustration. 2. Try to always set Attributes before making definitions for the function - this is a generally correct way to do it, and there are (rather pathological, but still) cases when this matters - see Guidebook for Programming by Michael Trott for some examples. Here is one: In[5] = ClearAll[r, t, h]; r[x_ + y_] := x - y; h[t[r[f_[x_] + g_[y_]]]] := f[x] - g[y]; SetAttributes[h, HoldAll]; In[6]= ?h Out[6] = Global`h Attributes[h]={HoldAll} h[t[f_[x_]-g_[y_]]]:=f[x]-g[y] You see, the definition for <r> evaluated inside the l.h.s (declaration) for <h> before the defining assignment for h evaluated. Now: In[7] = ClearAll[h]; SetAttributes[h, HoldAll]; h[t[r[f_[x_] + g_[y_]]]] := f[x] - g[y] In[8] = ?h Out[8] = Global`h Attributes[h]={HoldAll} h[t[r[f_[x_]+g_[y_]]]]:=f[x]-g[y] The reason for this behavior is that Set and SetDelayed only hold their direct argument, not arguments of that argument. For example, in this case: In[9] = ClearAll[f, a]; a = 1; f[a] = 5; In[10] = ?f Out[10] = Global`f f[1]=5 we might have naively expected the rule f[a] = 5 being added to the rule base. But <a> evaluated to 1, because evaluation of <a> is governed already by attributes of <f>, not Set. Now, the above example with <h> is indeed a pathological one, but there are other less contrived situations where this is important as well. The worst part here is that the trouble happens at the level of the function's definition, and this is usully the last thing to suspect. 3. You don't need HoldAllComplete attribute. It is used typically to prevent evaluator from taking any action on an expression, such as UpValue lookup (which still happens with HoldAll). For most "standard" holding purposes HoldAll will suffice. 4. The reason that Unevaluated does not work for you is that you use it in an inappropriate setting - you should have used Hold instead. Have a look at the recent thread http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/bfd67e9122b1fdec?hl=en# where there is a detailed discussion on the difference between Hold and Unevaluated. To put it short, use Unevaluated only if you want some argument to be passed to some function in unevaluated form locally, just once. Unevaluated wrappers are stripped at the end of the given evaluation, and then the new evaluation with a resulting expression starts. Therefore, at the end of evaluation of <MyFun> you have just expression 2 = 3 (Unevaluated stripped), and evaluator tries to evaluate this and gives you an error message. Here is the way to get what you want with Unevaluated, just for the record: In[11] = ClearAll[MyFun]; SetAttributes[MyFun, HoldAll]; MyFun[x_] := Unevaluated[Unevaluated[x]]; Clear[f]; f[x_]:=First[x]; In[12] = f[MyFun[2 = 3]] // Trace Out[12] = {{MyFun[2=3],Unevaluated[2=3]},f[Unevaluated[2=3]], First[Unevaluated[2=3]],First[2=3],2} But this is error-prone: you have to explicitly count how many levels of Unevaluated wrapper you need, so that when they are stripped you get the desired outcome. As I mentioned at the top of this post, when you wnat to preserve the result in held (unevaluated) form in between two separate evaluations (which is what you need here), use Hold instead. Finally, there is another way to "freeze" code - use the Block trick. For example, in this case: In[13] = Block[{Set}, First[2 = 3]] Out[13] = 2 This method has limitations: you can not Block symbols possessing Locked attributes. Hope this helps. Regards, Leonid On Wed, Jun 17, 2009 at 1:45 AM, Erich Neuwirth <erich.neuwirth at univie.ac.at > wrote: > I define > > MyFun[x_]:=Unevaluated[x] > SetAttributes[MyFun,HoldAllComplete] > > > MyFun[2 = 3] > still evaluated the argument and of course produces an error > I would like to get the unevaluated expression to be able > to separate the first argument. > > In fact, I would like MyFun to be a macro which allows me > to play list processing games with the arguments. > > How can this be accomplished? > > --0016e6dbe2ae0651cb046c8be960 Content-Type: text/html; charset="ISO-8859-1" Content-Transfer-Encoding: quoted-printable X-Sun-Content-Length: 6574 Hi Erich,<br><br>Short answer: use Hold instead of Unevaluated:<br><br>In[1= ] = <br><br>ClearAll[MyFun];<br>SetAttributes[MyFun, HoldAll];<br>MyFun[x= _] := Hold[x];<br><br>(in this example this means that you could bypass M= yFun step and start<br> with Hold[2=3] from the beginning), and rules to deconstruct expressions:= <br><br>In[2] = <br>MyFun[2 = 3] /. HoldPattern[a_ = b_] :> a<br><= br>Out[2] = Hold[2]<br><br>It is actually safer and easier to keep you= r expression wrapped in Hold and use rules rather than play with attributes= and evaluation. A more interesting example:<br> <br>In[3] = <br>code = Hold[Module[{a = 1, b, c = 2, d}, Print[a, b= , c, d]]]<br><br>In[4] = <br>moduleVars = <br> Cases[code, <br> Ho= ldPattern[<br> Module[x_List, body_]] :> (Hold[x] /. <br> = HoldPattern[Set[y_Symbol, rhs_]] :> y), Infinity]<br> <br>Out[4] = {Hold[{a, b, c, d}]}<br><br>Here we used this technique to i= ntrospect Module and extract variables<br>declared in it, in held form.<br>= <br><br>Now, a few remarks on your attempt:<br><br>1. If you really want to= play games with evaluation, do yourself a favor and read some detailed acc= ount on Mathematica evaluator, such as "Mathematica Internals" by= David Withoff (WRI technical report, available online at Wolfram Library A= rchive), or a book by David Wagner (unfortunately, out of print) - <br> this will save you hours of frustration.<br><br>2. Try to always set Attrib= utes before making definitions for the function - this is a generally corre= ct way to do it, and there are (rather pathological, but still) cases when = this matters - see Guidebook for Programming by Michael Trott for some exam= ples. Here is one:<br> <br><br>In[5] = <br><br>ClearAll[r, t, h];<br>r[x_ + y_] := x - y;<br>h= [t[r[f_[x_] + g_[y_]]]] := f[x] - g[y];<br>SetAttributes[h, HoldAll];<br>= <br>In[6]= ?h<br><br>Out[6] = <br><br>Global`h<br>Attributes[h]={Hold= All}<br> <br>h[t[f_[x_]-g_[y_]]]:=f[x]-g[y]<br><br>You see, the definition for = <r> evaluated inside the l.h.s (declaration) for <h> before the= defining assignment for h evaluated. Now:<br><br>In[7] = <br><br>ClearAl= l[h];<br> SetAttributes[h, HoldAll];<br>h[t[r[f_[x_] + g_[y_]]]] := f[x] - g[y]<br>= <br>In[8] = ?h<br><br>Out[8] = <br>Global`h<br>Attributes[h]={HoldAll= }<br> <br>h[t[r[f_[x_]+g_[y_]]]]:=f[x]-g[y]<br><br>The reason for this = behavior is that Set and SetDelayed only hold their direct argument, not ar= guments of that argument. For example, in this case:<br> <br>In[9] = <br>ClearAll[f, a];<br>a = 1;<br>f[a] = 5;<br><br>In[10] = = ?f<br><br>Out[10] = <br>Global`f<br>f[1]=5<br><br>we might have nai= vely expected the rule f[a] = 5 being added to the rule base.<br>But <= a> evaluated to 1, because evaluation of <a> is governed already b= y attributes of <f>, not Set.<br> <br>Now, the above example with <h> is indeed a pathological one, but= there are other less contrived situations where this is important as well.= The worst part here is that the trouble happens at the level of the functi= on's definition, and this is usully the last thing to suspect.<br> <br><br>3. You don't need HoldAllComplete attribute. It is used typical= ly to prevent <br>evaluator from taking any action on an expression, such a= s UpValue lookup (which still happens with HoldAll). For most "standar= d" holding purposes HoldAll will suffice.<br> <br>4. The reason that Unevaluated does not work for you is that you use it= <br>in an inappropriate setting - you should have used Hold instead. Ha= ve a <br>look at the recent thread <br><br><a href="http://groups.google.= com/group/comp.soft-sys.math.mathematica/browse_thread/thread/bfd67e9122b1f= dec?hl=en#">http://groups.google.com/group/comp.soft-sys.math.mathematica= /browse_thread/thread/bfd67e9122b1fdec?hl=en#</a><br> <br>where there is a detailed discussion on the difference between Hold and= Unevaluated. To put it short, use Unevaluated only if you want some argume= nt to be passed to some function in unevaluated form locally, just once. Un= evaluated wrappers are stripped at the end of the given <br> evaluation, and then the new evaluation with a resulting expression <br>sta= rts. Therefore, at the end of evaluation of <MyFun> you have just exp= ression 2 = 3 (Unevaluated stripped), and evaluator tries to evaluate thi= s and gives you an error message. <br> <br>Here is the way to get what you want with Unevaluated, just for the rec= ord:<br><br>In[11] = <br><br>ClearAll[MyFun];<br>SetAttributes[MyFun, Hol= dAll];<br>MyFun[x_] := Unevaluated[Unevaluated[x]];<br><br>Clear[f];<br>f= [x_]:=First[x];<br> <br>In[12] = f[MyFun[2 = 3]] // Trace<br><br>Out[12] = {{MyFun[2=3]= ,Unevaluated[2=3]},f[Unevaluated[2=3]],<br>First[Unevaluated[2=3]],Fi= rst[2=3],2}<br><br>But this is error-prone: you have to explicitly count = how many levels of<br> Unevaluated wrapper you need, so that when they are stripped you get the de= sired outcome.<br><br>As I mentioned at the top of this post, when you wnat= to preserve the result in held (unevaluated) form in between two separate = evaluations (which is what you need here), use Hold instead.<br> <br>Finally, there is another way to "freeze" code - use the B= lock trick. For <br>example, in this case:<br><br>In[13] = Block[{Set}, F= irst[2 = 3]]<br><br>Out[13] = 2<br><br>This method has limitations: you= can not Block symbols possessing Locked attributes.<br> <br>Hope this helps.<br><br>Regards,<br>Leonid<br><br><br><br><br><br><br><= br><br><br><br><br><br><br><br><br><br><div class="gmail_quote">On Wed, J= un 17, 2009 at 1:45 AM, Erich Neuwirth <span dir="ltr"><<a href="mai= lto:erich.neuwirth at univie.ac.at">erich.neuwirth at univie.ac.at</a>></span>= wrote:<br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, = 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">I define<br> <br> MyFun[x_]:=Unevaluated[x]<br> SetAttributes[MyFun,HoldAllComplete]<br> <br> <br> MyFun[2 = 3]<br> still evaluated the argument and of course produces an error<br> I would like to get the unevaluated expression to be able<br> to separate the first argument.<br> <br> In fact, I would like MyFun to be a macro which allows me<br> to play list processing games with the arguments.<br> <br> How can this be accomplished?<br> <br> </blockquote></div><br> --0016e6dbe2ae0651cb046c8be960--
- References:
- Help with HoldAll needed
- From: Erich Neuwirth <erich.neuwirth@univie.ac.at>
- Help with HoldAll needed