31
$\begingroup$

In most programming languages, container indices start at 0. This is not random or hardware-related; for example Dijkstra's article explains why zero-based indices make sense.

What are the reasons why Mathematica lists start with an index of 1?

$\endgroup$
  • 19
    $\begingroup$ Because the 0-th index is reserved for the head: lst = {1,2,3}; lst[[0]], which in this case is List. $\endgroup$ – Leonid Shifrin Jun 17 '15 at 21:54
  • 9
    $\begingroup$ Stephen was a FORTRAN and Macsyma programmer before he designed SMP and Mathematica and so it probably made much more sense to him to start at index 1. Also for physicists (like Stephen) it is natural to start numbering vectors and matrices with index 1 and since a list in Mathematica (what you call "container") is used to represent a vector (and a matrix, as a list of lists) it is completely natural ( or "nice", a funny non-scientific word Dijkstra uses) to start with index 1. $\endgroup$ – Rolf Mertig Jun 17 '15 at 22:12
  • 3
    $\begingroup$ EWD's comments are largely arbitrary aesthetic preferences. I think that other arbitrary aesthetic preferences (or at the least an equal preference for a and c) can easily be defended as well. $\endgroup$ – Oleksandr R. Jun 17 '15 at 22:15
  • 11
    $\begingroup$ The reason for zero indexing becomes perfectly obvious as soon as you find yourself doing index arithmetic.With mathematica we practically never need to resort to such arithmetic, so there is no reason to make the otherwise unnatural choice of counting from zero. $\endgroup$ – george2079 Jun 17 '15 at 22:21
  • 6
    $\begingroup$ I'm not in a position to put into question Dijkstra, but I'm quite confident that you can find just as many publications which argue that starting at 1 makes more sense. I think the real reason why many programming languages start to index at 0 is because C does that, but there it is more a consequence of array indexes being equivalent to pointer offsets and probably not so much a design decision. I have extensively used languages with both conventions and personally found the zero based indexing more error prone, 1<=i<=N seems to be a quite natural choice for ranges to me... $\endgroup$ – Albert Retey Jun 18 '15 at 6:16
43
$\begingroup$

I think Leonid's answer deserves to be expanded upon. Most other languages are not symbolic, and thus the "variable name" is not something one needs to keep track of --- ultimately the interpreted or compiled code is keeping track of pointers or something. In contrast, in Mathematica the Head of an expression is arbitrary. This is somewhat along the lines of LISP where the first symbol in a list is the procedure which should be applied to the rest of the list. So, in LISP one might write (+ 3 2) which evaluates to 5. Written this way, it's clear that the symbol + occupies the "natural" 0th position, 3 the first, and 2 the second. In Mathematica one would write the equivalent expression as Plus[3,2], so that the 3 is in the first position -- the same position that it would be in in LISP. The fact that some Heads (namely, List) work like vectors for many intents and purposes would break the uniformity of the mapping between a LISP-like language and Mathematica, and worse---break the internal uniformity of Mathematica indexing, if you demand that you should be able to extract the Head of an expression.

This is related to the fact that in some sense, it's the most symmetric thing to do in a symbolic language, if that language is going to support negative indexing and arbitrary Heads. For example if you have

f = F[1,2,3,4,5]

then f[[-1]] evaluates to 5. If you impose "periodic boundary conditions" you might imagine writing the expression f schematically as

     F
5          1

4          2
     3

so that moving one spot clockwise gives you the first element, one spot counterclockwise gives you the last element, and moving 0 spots gives you the Head.

$\endgroup$
  • 7
    $\begingroup$ Love the hexagonal diagram explaining positive and negative indexing. $\endgroup$ – Michael Jun 18 '15 at 7:03
  • 6
    $\begingroup$ This answer has been getting some upvotes lately, and I thought it might be nice to additionally point out that in many shell / scripting languages (like bash), \$0 is a variable which contains the command itself while the arguments start with \$1. $\endgroup$ – evanb Sep 15 '15 at 6:03
  • $\begingroup$ @evan, that convention carries over to Slot[]; #0 refers to the function itself (useful for recursive implementations). $\endgroup$ – J. M. will be back soon Dec 22 '16 at 3:46
  • $\begingroup$ @J.M., true! I think it's true for argc argv, also? I always have to look that up... $\endgroup$ – evanb Dec 22 '16 at 7:44
12
$\begingroup$

Some years ago, a friend of mine was in the supermarket with his son, small kid, who asked him to buy some candy. After some resistance, my friend agreed, but told him that should be just one. In the cashier, his son had two candy, and my friend said:

  • What is this? haven't we agreed One?

And the answer (very smart) was:

  • Yes! Here it is. Zero and One... (His son should be a C programmer)

Well... I believe starting to count lists of discrete items by 1 is much more natural. I don't understand why other languages do it starting by Zero, if it's not a continuum interval.

Mathematica, Matlab and R are the ones I know that follows this convention.

$\endgroup$
  • 4
    $\begingroup$ At least, for coefficients of polynomials and Fourier series, it is certainly sensible to index from zero. But I am definitely part of the group that is fine with Mathematica indexing from 1, leaving 0 for the head and negative indices counting from the end. $\endgroup$ – J. M. will be back soon Jun 18 '15 at 2:44
  • 5
    $\begingroup$ His son counted from zero like a C programmer, but he didn't exclude the end number like one. :-) $\endgroup$ – Michael Jun 18 '15 at 4:05
  • 1
    $\begingroup$ In lower level languages like C indexing arrays from 0 is more natural because there the indices work as offsets, i.e. if you have a pointer p, then p[0] is the same as *(p+0) and the same as *p and the same as 0[p]. $\endgroup$ – Ruslan Jun 18 '15 at 6:31
  • 4
    $\begingroup$ @Ruslan: the rationale for 0-indexing is not limited to lower level pointer arithmetic. The mentioned in the original question Dijkstra's article outlines some of it, namely the convenience of using semi-open intervals [begin, end), implying not including the upper bound in the loop, thus implying starting with 0. Also compare the complexity of arithmetic between base 0 and 1 for using single index for indexing into a 2D or 3D arrays. The case for 0-base is very strong; I am content though with evanb's answer. $\endgroup$ – Michael Jun 18 '15 at 7:01
  • 2
    $\begingroup$ To add to Michael's comment, note that our entire decimal number system is based on 0-indexing. When you start counting, every digit except for the very last one is 0. This is especially true in computing, where all digits are "always present" due to fixed storage width. 1-indexing, and its strong manifestation in language ("first", "second", "third", "fourth") is a remnant from the roman times, where there was no such thing as a zero, and consequently mathematics was a whole lot harder. Note how the year 2000 was in the second millenium, but 2001 in the third. $\endgroup$ – mic_e Jun 18 '15 at 15:08

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