7

I am using Mathematica 10 now.

I typed code below

{{1, 2}, {2, 4}, {3, 6}, {4, 8}}[[;; , 1]][[1]]

and this gives result

1

But code

{{1, 2}, {2, 4}, {3, 6}, {4, 8}}[[;; , 1, 1]]

gives error

Part::partd: Part specification {{1,2},{2,4},{3,6},{4,8}}[[1;;All,1,1]] is longer than depth of object. >>

But according to help doc

expr[[i,j,...]]] or Part[expr,i,j,...]] is equivalent to expr[[i]][[j]]...

What is wrong?!! I remember I always coded it like this in Mathematica 9, no error occurs. Is it a bug??

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
matheorem
  • 17,132
  • 8
  • 45
  • 115
  • Span threads over the defined elements, which then do not have sufficient depth for the last part specification. E.g. {{1, 2}, {2, 4}, {3, 6}, {4, 8}}[[1, 1, 1]] returns the same error (on probably any version). Note: I removed the bugs tag, which is for confirmed bugs only. – Yves Klett Sep 01 '14 at 12:31
  • 3
    Also from the docs: "Successive part extraction is not always equivalent to direct part extraction". Perhaps it is better to read the piece you quote from the docs with the implicit proviso: "If expr[[i,j,...]] is a valid expression, it is equivalent to ..."? – kglr Sep 01 '14 at 12:31
  • Oh, and 9.01 throws the same error. – Yves Klett Sep 01 '14 at 12:53
  • @kguler Oh, such a delicate definition. Probably you are right. – matheorem Sep 01 '14 at 13:07
  • @MichaelE2 hmm... I am still waiting for someone in the know to expose the innards of Part+Span evaluation. That might actually be quite useful! – Yves Klett Sep 01 '14 at 17:36
  • @YvesKlett OK, I've answered. I just thought from your comment that you could and I didn't want to poach. I've been tricked by this before, so I agree that answering is good. – Michael E2 Sep 01 '14 at 18:16
  • @MichaelE2 you are most welcome - thanks for your effort! – Yves Klett Sep 01 '14 at 18:35

2 Answers2

8

General explanation

First, in general, a valid expr[[i1, i2,..., in]]] requires expr to have at least n levels, and the result will have n fewer levels.

The OP's example list {{1, 2}, {2, 4}, {3, 6}, {4, 8}} has two. The code

{{1, 2}, {2, 4}, {3, 6}, {4, 8}}[[;; , 1, 1]]

needs at least three levels. Hence the error.

Next, in the sentence of the documentation for Part,

expr[[i,j,...]] or Part[expr,i,j,...]] is equivalent to expr[[i]][[j]]...

the i, j, ... are to be integers, or so I used to think. However, as @kguler said in a comment, the equivalence holds if expr[[i, j,...]] is valid.

If instead of an integer, a Span or a List (or All) is used, the result will be a (possibly nested) list. Each Span and List adds a level to the depth of the result one would have had if every part had been a simple integer. This allows for further extraction of parts as in the OP's first example.

OP's first example

We can break down the OP's example as follows. The expression

{{1, 2}, {2, 4}, {3, 6}, {4, 8}}[[;; , 1]][[1]]

is equivalent to the last result of

{{1, 2}, {2, 4}, {3, 6}, {4, 8}}[[;; , 1]]
%[[1]]
(*
  {1, 2, 3, 4}
  1
*)

The first expression has a Span and evaluates to a list of parts, the first part of each expression at level 2. Adding a [[1]] extracts the first part of this list.

It may be a little easier to see what's going on in an example that gives no errors:

foo = ArrayReshape[Range@8, {4, 2, 1}]
foo[[;; , 1, 1]]
foo[[;; , 1]][[1]]
(*
  {{{1}, {2}}, {{3}, {4}}, {{5}, {6}}, {{7}, {8}}}
  {1, 3, 5, 7}
  {1}
*)

The last output is a list because {1} is the first part of

foo[[;; , 1]]
(*
  {{1}, {3}, {5}, {7}}
*)
Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • To the down-voter: Is there an error or some other issue? – Michael E2 Sep 02 '14 at 20:09
  • I did not downvote your answer, I never downvote correct answers. I'm just trying to detect an individual who downvoted mine a few minutes ago. Threre are very few suspicious... – Artes Sep 03 '14 at 19:05
  • @Artes All in all, it's been a considerate community, whose criticism has been carried out in a reasonably honest way. Let's hope it stays that way. – Michael E2 Sep 03 '14 at 19:56
  • 2
    It could be an interesting question to write an application in Mathematica finding who downvoted an answer. Comparing reputation points in collective registry of users (it subtracts points when one downvotes) with individual profiles (where points from downvoting are not registered) we can find downvoters. By using my pedestrian approach I could find only 3 suspected, but improving it with another characteristics we could approach up to $90$% certainity on average:). – Artes Sep 03 '14 at 20:19
3

When using [[All, 1, 1]] you are attempting to extract the first element of the first element of all parts of the expression. Note what happens when you specify 0 instead of 1, which is a valid "part" of 1 etc.:

{{1, 2}, {2, 4}, {3, 6}, {4, 8}}[[All, 1, 0]]
{Integer, Integer, Integer, Integer}

Part 0 is the head of an expression. See: Is there a summary of answers Head[] can give?

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371