Services & Resources / Wolfram Forums
-----
 /
MathGroup Archive
2004
*January
*February
*March
*April
*May
*June
*July
*August
*September
*October
*November
*December
*Archive Index
*Ask about this page
*Print this page
*Give us feedback
*Sign up for the Wolfram Insider

MathGroup Archive 2004

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

Search the Archive

RE: Unexpected behaviour of HoldRest

  • To: mathgroup at smc.vnet.net
  • Subject: [mg45707] RE: [mg45678] Unexpected behaviour of HoldRest
  • From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
  • Date: Wed, 21 Jan 2004 04:54:52 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

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
>Sent: Monday, January 19, 2004 11:15 AM
>To: mathgroup at smc.vnet.net
>Subject: [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


  • Prev by Date: RE: Tail recursion and local functions
  • Next by Date: Suse Linux Action error
  • Previous by thread: Unexpected behaviour of HoldRest
  • Next by thread: Re: RE: Unexpected behaviour of HoldRest