I have been working on picking expressions apart using Head and Part and encountered a little mystery. Consider the canonical example

a + b + c


which has FullForm

Plus[a, b, c]


We expect, then, (a+b+c)[[0]] === Plus === Head[a+b+c] to be True, and it is. But then, we would expect (a+b+c)[[1;;3]] would be {a, b, c}, wouldn't we? But it isn't. The following is true:

(a + b + c)[[1;;3]] === (a + b + c)


Somehow, [[1;;3]], which is supposed to pick off elements 1 through 3 of its argument and put them in a List, doesn't get rid of the Head, which is element 0!

The questions are, then (and I will be grateful for hints and answers!)

1. Why doesn't (a + b + c)[[1;;3]] get rid of (a + b + c)[[0]], the Head?

2. What is the right way to get rid of the Head?

3. (a + b + c)[[0;;3]] produces 0. I would expect it to produce {Plus, a, b, c}. Instead, it produces 0. This just deepens the mystery for me! Why?

Point #1

Part always wraps element sequences with the original head of the expression.

expr = Hold[1 + 1, 2 + 2, 3 + 3, 4 + 4, 5 + 5];

expr[[{2, 3}]]

Hold[2 + 2, 3 + 3]


For this purpose a single part e.g. 1 is not a sequence but {1} and 1 ;; 1 are:

expr[[1]]

expr[[{1}]]

expr[[1 ;; 1]]

2

Hold[1 + 1]

Hold[1 + 1]


This applies at every level of the extraction:

exp2 = g[h[1, 2], i[3, 4]];

exp2[[  2 , 1  ]]
exp2[[ {2}, 1  ]]
exp2[[  2 ,{1} ]]
exp2[[ {2},{1} ]]

3

g[3]

i[3]

g[i[3]]


I used this nontrivially for Elegant manipulation of the variables list.

Point #2

Consider instead using Extract which wraps sequences in List:

Extract[expr, {{2}, {3}}]

{4, 6}


The third argument of Extract can be used to specify a function to apply to individual elements before they are evaluated:

Extract[expr, {{2}, {3}}, HoldForm]

{2 + 2, 3 + 3}


If you want all parts you can also use Level:

Level[(a + b + c), {1}, Heads -> True]

{Plus, a, b, c}


Or Cases:

Cases[(a + b + c), _, Heads -> True]

{Plus, a, b, c}


Or Replace/ReplaceAll:

(a + b + c) /. head_[body___] :> {head, body}

{Plus, a, b, c}


Point #3

The last point is more tricky and I had to check it myself. There is a behavior that I also did not expect:

Range[5][[0 ;; 5]]

{}


What I expected was an error as seen here:

Range[5][[0 ;; 4]]


and here:

Range[5][[0 ;; 6]]


When Span is used in Part[x, 0 ;; n] where n is the length of x, Part returns the head of the expression. Therefore (a + b + c)[[0;;3]] returns Plus[] and Plus[] evaluates to 0.

I believe Span behaves this way because of how it handles non-positive values, and zero-length spans. Consider:

Range[10][[-2 ;; 10]]

{9, 10}


You can see that it wraps around. Now consider:

Range[10][[5 ;; 4]]

{}


An empty span returns the head of the expression with no arguments.

Using 0 ;; n where n is the last element in the list, or 0 ;; -1, is also an empty span wrapping around the open end of the list.

Range[10][[0 ;; -1]]

{}

• Ah, I see that you can answer #1 as well, not just Leonid :) – Verbeia Feb 29 '12 at 6:26
• Regarding point #3, you might find this discussion relevant (if not too enlightening). – Szabolcs Feb 29 '12 at 11:47
• @Szabolcs That's important information. I cannot recall a situation where it would affect me, but it would be bloody annoying to track it down if it did. – Mr.Wizard Feb 29 '12 at 16:36
• And another place for the all-powerful Cases: Cases[{a + b + c}, head_[args___] -> {head, args}] produces {{Plus, a, b, c}} – Reb.Cabin Mar 8 '12 at 23:04
• @Reb doing that route you don't even need Cases: a + b + c /. head_[args___] :> {head, args} – Mr.Wizard Mar 9 '12 at 0:06

Perhaps only the developers (or Leonid) can answer #1 and #3 and "why".

The quick answer to #2 is Apply, remembering that List is a Head like any other:

List @@ (a + b + c)


{a, b, c}

On #3, I can't explain why ;; syntax gives 0 when

(a + b + c)[[Range[0, 3]]]


gives

a + b + c + Plus

So you could try

List @@ ((a + b + c)[[Range[0, 3]]])


{a, b, c, Plus}

• There is something broken in the way the site previews answers. I have been amending my answer for the last twenty minutes and only now do I see that you also posted an answer. – Mr.Wizard Feb 29 '12 at 6:48
• @Mr.Wizard You don't get notified of a new answer when editing your already existing answer... – rm -rf Feb 29 '12 at 8:15
• The List @@ answer has a deep, hackish charm, coming closest to answering "... and everything but Head.". The Extract and Level answers have more versatility and clearly enable complete analysis and compilation of expressions. A metacircular evaluator for MMA would not seem too remote a possibility. – Reb.Cabin Feb 29 '12 at 8:17
• In some sense, Sequence@@(a+b+c) comes closer to "everything but Head" than List@@(a+b+c): While List is just another head (with a special input/display syntax associated with it), Sequence is the closest Mathematica has to a headless expressions: If you insert it anywhere (except functions with attribute HoldAllComplete) it just gets interpolated. – celtschk May 21 '12 at 19:35
• @celtschk For completeness the attribute SequenceHold also prevents the flattening of Sequence expressions, just as HoldAllComplete does, while allowing other evaluation. – Mr.Wizard Aug 14 '17 at 6:13