Re: RE: Unexpected behaviour of HoldRest

*To*: mathgroup at smc.vnet.net*Subject*: [mg45734] Re: [mg45707] RE: [mg45678] Unexpected behaviour of HoldRest*From*: Andrzej Kozlowski <akoz at mimuw.edu.pl>*Date*: Thu, 22 Jan 2004 03:37:35 -0500 (EST)*References*: <200401210954.EAA07748@smc.vnet.net>*Sender*: owner-wri-mathgroup at wolfram.com

It may be of some interest to point out that one can often use Hold and ReleaseHold instead of Sequence, with similar effect (and sometimes with fewer problems). For example: ReleaseHold[{{0, 1, 2, 3, 2}, 3, 2} /. 2 -> Hold[]] {{0,1,3},3} Carl Woll's OrderedUnion can also be written using this approach: OrderedUnion[li_] := ReleaseHold[Block[{i}, i[n_] := (i[n] = Hold[]; n); i /@ li]] OrderedUnion[{1,4,3,17,3,5,5,17,11,4}] {1,4,3,17,5,11} (I have not tried comparing its performance with Carl's original version). Andrzej Kozlowski Chiba, Japan http://www.mimuw.edu.pl/~akoz/ On 21 Jan 2004, at 09:54, Wolf, Hartmut wrote: > John, > > you'r right, as Sequence[] should be used with care. Up to Version 4 > it was > an undocumented function and the only mention to it I found was from > Roman > Maeder (who is, or was an insider; and Carl Woll certainly had read his > books). > > Almost ever the use of Sequence can be avoided (although it might come > handy), and in this group its use has been popularized more than it > deserves. Even OrderedUnion -- which was a stroke of genius at its > time -- > nowadays with the modern versions of Mathematica (packed arrays, > improved > Split, Ordering) clearly no longer is the fastest way to do it! > > Sequence should be used with care and presupposes an exact knowledge > and > understanding of the Mathematica evaluation sequence. > > (Further comments interspersed) > > > >> -----Original Message----- >> From: John Tanner [mailto:john at janacek.demon.co.uk] To: mathgroup at smc.vnet.net > To: mathgroup at smc.vnet.net >> Sent: Monday, January 19, 2004 11:15 AM >> To: mathgroup at smc.vnet.net >> Subject: [mg45734] [mg45707] [mg45678] Unexpected behaviour of HoldRest >> >> >> Inspired by Carl Woll's OrderedUnion (for which many, many thanks!) I >> have found similar uses for Sequence[], such as using >> replacement rules: >> >> In[1]:= {{0,1,2,3,2},3,2} /. 2->Sequence[] >> >> Out[1]= {{0, 1, 3}, 3} >> > > The right way to do that: > > In[2]:= DeleteCases[{{0, 1, 2, 3, 2}, 3, 2}, 2, 2] > Out[2]= {{0, 1, 3}, 3} > > >> But I recently found an "unexpected" result: >> >> In[1]:= If[1 == 1, Sequence[], 2] >> >> Out[1]= 2 >> > > Well, it should be expected, Sequence will be "flattened out" when the > arguments are evaluated _before_ the expression If itself is being > evaluated > (unless it had the SequenceHold or HoldAllComplete attribute, but it > has > neither of them) > > In[4]:= Attributes[If] > Out[4]= {HoldRest, Protected} > > Such in a first step > > If[1 == 1, Sequence[], 2] > > is evaluated to > > If[True, Sequence[], 2] > > now Sequence objects will be flattened out irrespectively of HoldRest, > therefore the expression is transformed to > > If[True, 2] > > only then rules for If are applied, hence Out[1] > > >> Now when presented in this form it is "obvious", that Sequence[] is >> being "flattened out" of the arguments to If. The wanted behaviour of >> If in this case can be restored if SequenceHold is applied: >> >> In[3]:= Unprotect[If]; >> SetAttributes[If, SequenceHold]; >> Protect[If]; >> >> In[6]:= If[1 == 1, Sequence[], 2] >> >> Out[6]= Sequence[] >> > > Dont't do that! We cannot overview the consequences of such a global > intervention. Instead act locally: > > In[7]:= If[1 == 1, Unevaluated[Sequence[]], 2] > Out[7]= Sequence[] > > > This now allows to do other things, e.g. > > In[3]:= Map[If[# === 2, Unevaluated[Sequence[]], #] &, > {{0, 1, 2, 3, 2}, 3, 2}, 2] > Out[3]= {{0, 1, 3}, 3} > > > >> But If has (I now find) the Attribute HoldRest, and Hold does not >> flatten out Sequence[] so I don't understand why that does not apply >> here also. >> > > Hold has the attributes > > In[6]:= Attributes[Hold] > Out[6]= {HoldAll, Protected} > > hence it flattens out Sequence[..] > > In[5]:= Hold[Sequence[], If[1 == 1, Sequence[], 2]] > Out[5]= Hold[If[1 == 1, Sequence[], 2]] > > (Of course there will be no operation for and _within_ the held > expression.) > > >> In[7]:= xx[1+2,2+3,3+4] >> >> Out[7]= xx[3,5,7] >> >> In[8]:= SetAttributes[xx,HoldRest] >> >> In[9]:= xx[1+2,2+3,Sequence[],3+4] >> >> Out[9]= xx[3,2+3,3+4] >> > > You just showed that HoldRest has nothing to do with all that. > > >> Relatively few built-in functions have SequenceHold applied: >> >> {AbsoluteTiming, Rule, RuleDelayed, Set, SetDelayed, TagSet, >> TagSetDelayed, Timing, UpSet, UpSetDelayed} >> >> And also relatively few built-in functions have HoldRest applied: >> >> {Assuming, DumpSave, If, PatternTest, RuleDelayed, Save, Switch} >> > > Yes, the main reason is for so-called lazy evaluation. Would you > imagine > what happend when If lacked this attribute? Not only that many parts > of the > expression had to be evaluated in vain, and never used for the result, > also > side effects would become completely unpredictable (more than is > anyway). > > > >> I will therefore now be much more careful of the use of Sequence! At >> present I don't want to be more daring and apply these attributes >> wholesale without understanding why this is happening. There must be >> other cases where Sequence can have unexpected effects - I now >> understand some of the problems I had when trying to use [mg13201] to >> modify $Post - >> reallyBig needs to cope with Sequence[] and Sequence[__]. >> >> -- >> from- John Tanner email- john at janacek.demon.co.uk >> mantra- curse Microsoft, curse... web - >> http%##www.janacek.demon.co.uk/ >> I hate this 'orrible computer, I really ought to sell it: >> It never does what I want, but only what I tell it. >> > > > I agree, see also the Book about evaluation (e.g. §A.4.1) > > -- > Hartmut Wolf > > >

**References**:**RE: Unexpected behaviour of HoldRest***From:*"Wolf, Hartmut" <Hartmut.Wolf@t-systems.com>