4
$\begingroup$
In[1] := {a, b, Sequence @@ {}, c}
Out[1] := {a, b, c}

In[2] := {a, b, Sequence[], c}
Out[2] := {a, b, c}

In[3] := {a, b, If[1 == 0, x, Sequence @@ {}], c}
Out[3] := {a, b, c}

In[4] := {a, b, If[1 == 0, x, Sequence[]], c} 
Out[4] := {a, b, Null, c}

How do you explain this peculiar sequence of commands? In the last example, my guess is that the sequence is evaluated on the if statement itself, shrinking it to If[1 == 0, x] so that the false evaluation gives Null instead. Doesn't If have a HoldForm or something on the arguments to ensure that this doesn't happen? And why does example 3 work in that case? My application is a long list of the form {a,b,x,c} or {a,b,c} and I want to make the x appear in the list under a condition, without writing a,b,c twice (it would be equivalent to If[cond,{a,b,x,c},{a,b,c}]).

$\endgroup$

marked as duplicate by Mr.Wizard Apr 20 '15 at 15:27

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ {a, b, If[1 == 0, x, Evaluate[Sequence @@ {}]], c} returns {a, b, Null, c}. I think it is caused by the order of evaluation. $\endgroup$ – happy fish Apr 19 '15 at 12:34
  • $\begingroup$ I propose closing this as a duplicate of (3700). In my answer there I refer to SequenceHold as the explanation for "shrinking" to If[1 == 0, x]. $\endgroup$ – Mr.Wizard Apr 19 '15 at 16:55
  • $\begingroup$ @Mr.Wizard I agree, although the answers here and there both add helpful information on this phenomenon, so linking them is probably sufficient. I didn't know the stuff about Unevaluated[] and ##&[] that you mention in the other answer either. $\endgroup$ – Mario Carneiro Apr 20 '15 at 5:10
  • $\begingroup$ Okay, I shall close. I don't know if it's the same on Mathematics but here duplicates are rarely deleted, so yes, this post and its answers will remain linked from 3700. $\endgroup$ – Mr.Wizard Apr 20 '15 at 15:27
6
$\begingroup$

Sequence is treated a bit specially. It does not get "evaluated to a result", but instead as the documentation explains:

Sequence objects will automatically be flattened out in all functions except those with attribute SequenceHold or HoldAllComplete.

This means that even though If has attribute HoldRest, the expression If[1 == 0, x, Sequence[]] will be changed to If[1==0, x] before the If itself gets evaluated. The result of If[1==0, x] is Null, so that's where the Null comes from.

The alternative If[1 == 0, x, Sequence @@ {}] does not contain Sequence[], only Sequence. The If gets evaluated first, resulting in Sequence @@ {}, which is evaluated to Sequence[] and finally flattened out.


This is a typical problem with using Sequence[] and If together and the simple solution is

If[1 == 0, x, Unevaluated@Sequence[]]
$\endgroup$
3
$\begingroup$

Sequence has non-standard evaluation rules. You can work around them like so.

seq := Sequence

{a, b, If[False, x, seq[]], c}
{a, b, c}
{a, b, If[True, x, seq[]], c}
{a, b, x, c}

Updated to conform with the observation made by Szabolcs in his comment below.

$\endgroup$
  • 1
    $\begingroup$ The SequenceHold attribute needs to be assigned to the head that contains the Sequence[]. Here SetAttributes[seq, SequenceHold]; is not needed. Your example will work the same without it, seq = Sequence is sufficient. The evaluator will only flatten out a literal Sequence[] in If before evaluating the If. seq[] is not Sequence[] so it won't be flattened out before If is evaluated. Once If is evaluated, it yields seq[], which then is evaluated to Sequence[] which is then flattened out inside the {...}. $\endgroup$ – Szabolcs Apr 19 '15 at 12:54
  • $\begingroup$ @Szabolcs. +1. I have corrected my answer accordingly. $\endgroup$ – m_goldberg Apr 19 '15 at 13:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.