# Sequence evaluation in an If statement [duplicate]

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}]).

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

• {a, b, If[1 == 0, x, Evaluate[Sequence @@ {}]], c} returns {a, b, Null, c}. I think it is caused by the order of evaluation. – happy fish Apr 19 '15 at 12:34
• 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]. – Mr.Wizard Apr 19 '15 at 16:55
• @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. – Mario Carneiro Apr 20 '15 at 5:10
• 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. – Mr.Wizard Apr 20 '15 at 15:27

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[]]


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.

• 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 {...}. – Szabolcs Apr 19 '15 at 12:54
• @Szabolcs. +1. I have corrected my answer accordingly. – m_goldberg Apr 19 '15 at 13:44