8
$\begingroup$

This question already has an answer here:

I hope this is not a duplicate. I do not understand how does the Part and Span functions work on this expression:

g = f[a, b, c];

Taking zeroth element we get head

g[[0]]
(* => f *)

First, second and third element would give a, b and c respectively

g[[1]]
(* => a *)
g[[2]]
(* => b *)
g[[3]]
(* => c *)

My aim was to take second and third elements of f's arguments as a list. But

g[[2;;3]]
(* => f[b, c] *)

and I'm confused (the same with g[[{2, 3}]]). As a reslut I would expect expression with List or Sequence head instead. Why do we get this reslut? Is it consistent with that g[[1]] doesn't give f[1]?

$\endgroup$

marked as duplicate by MarcoB, user9660, Leonid Shifrin, Sjoerd C. de Vries, dr.blochwave Nov 12 '15 at 7:39

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.

  • 3
    $\begingroup$ Part retains the head of an original expression, when given a list of positions to extract, rather than a single position. The same with Span, which is conceptually the same as a list of positions. $\endgroup$ – Leonid Shifrin Nov 11 '15 at 18:32
  • $\begingroup$ So my confusion comes from the fact that for expressions with List heads Part would give expression with the same head (=List). $\endgroup$ – mmal Nov 11 '15 at 18:39
  • 1
    $\begingroup$ g[[1]] === Part[g, 1] is a single element extraction, so the element itself is returned. g[[{1}]] === Part[g,{1}] is an extraction of a list of elements, which happen to be just one element. In that case, you effectively get Head[g][sequence-of-extracted-elements]. With Associations, this is similar (although not quite the same) - there you get back an Association with extracted key-value pairs, if you use assoc[[{parts}]]. $\endgroup$ – Leonid Shifrin Nov 11 '15 at 19:00
  • 3
    $\begingroup$ @mmal It makes sense. If you want to extract a sequence of parts, you want to group them into some container. Grouping them into original head rather than a List means that you create an "object" similar to the original one, but with fewer parts. This is much more useful behavior in a large number of cases, than if the parts would have been grouped always in a List. And if you want the latter behavior, it is always easy to get by Apply-ing List to the result. $\endgroup$ – Leonid Shifrin Nov 11 '15 at 19:48
  • 6
    $\begingroup$ similar: (2449), (95763). $\endgroup$ – WReach Nov 11 '15 at 22:39
9
$\begingroup$

General

Part retains the head of an original expression, when given a list of positions to extract, rather than a single position. The same with Span, which is conceptually the same as a list of positions.

Part[h[1, 2, 3, 4, 5], 1]
Part[h[1, 2, 3, 4, 5], {3, 4, 5}]
Part[h[1, 2, 3, 4, 5], 3 ;; 5]

(* 
   1

   h[3, 4, 5]

   h[3, 4, 5]
*)

It makes sense. If you want to extract a sequence of parts, you want to group them into some container. Grouping them into original head rather than a List means that you create an "object" similar to the original one, but with fewer parts. This is much more useful behavior in a large number of cases, than if the parts would have been grouped always in a List. And if you want the latter behavior, it is always easy to get by Apply - ing List to the result.

Example: evaluation control

Here is just one (a bit artificial) example, where this is rather useful:

Part[Hold[1^2, 2^2, 3^2], 2]

(* 4 *)

but

Part[Hold[1^2, 2^2, 3^2], {2}]

(* Hold[2^2] *)

so in this case, this semantics of Part allowed us to prevent evaluation leak, if we wanted to.

The case of Associations

One case which stands out is that of Associations. We can start by noting a curious fact that Associations are atomic, and yet we can extract parts from them. In any case, the principle that the head of the expression is retained when several parts are extracted in a List, holds here too. Together with the head, the keys are also retained:

<|1 -> 2, 3 -> 4, 5 -> 6|>[[2]]

(* 4 *)

but

<|1 -> 2, 3 -> 4, 5 -> 6|>[[{2}]]

(* <|3 -> 4|> *)

and

<|1 -> 2, 3 -> 4, 5 -> 6|>[[{2, 3}]]

(* <|3 -> 4, 5 -> 6|> *)

This is in fact a very useful behavior of Associations, in a number of situations.

$\endgroup$
  • $\begingroup$ Thank you, a very good and understandable explanation $\endgroup$ – eldo Nov 11 '15 at 22:30
  • $\begingroup$ @eldo Glad you found it helpful. $\endgroup$ – Leonid Shifrin Nov 11 '15 at 22:43

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