25

From my experience with modern programming and scripting languages, I believe most programmers are generally accustomed to referring to the first element of an array by 0 as index.
Are there any substantial advantages in using 1?

I'm sure I've heard of more languages other than Zsh behaving similarly with arrays; it's fine by me, as it is equally convenient.
However, as previously released and widely used shell scripting languages such as ksh and bash all use 0, why would someone choose to alter this common "standard"?

My immediate answer to my question would be "of course not";
then, the only explanation I can think of regarding this somewhat "exclusive feature" to shells would be "they just did this to show off a bit more their cool shell".

I don't know much of either Zsh or its history though, and there is a high chance my trivial theory about this does not make any sense.

Is there an explanation for this? Or is it just out of personal taste?

  • 5
    Some historical research (or rantish ruminations?) on the topic of 0 versus 1: exple.tive.org/blarg/2013/10/22/citation-needed – thrig Dec 30 '15 at 18:32
  • For historical reason, that's probably came from csh, which also used one-based array indexing. – cuonglm Dec 30 '15 at 18:45
  • 3
    nowadays, sh is a standard language (not an implementation) that has different possible interpreters. Some of those interpreters for the sh language like bash, ksh and yash support arrays as extension, but they are not part of the language just like gcc, a compiler for the standard C language supports extensions over the standard C language. And just like for C, there is no "official" implementation of a "sh" interpreter. – Stéphane Chazelas Dec 30 '15 at 21:34
  • 1
    Related - comments in this PPCG answer – Digital Trauma Dec 31 '15 at 0:39
  • 4
    Maybe a bit off topic, but relevant. The Romans used inclusive counting, staring from one instead of zero.The day after tomorrow, to us "two days ahead", was to them "three days ahead." They counted today as one, not zero. As a consequence when their Egyptian astronomers recommended a leap day every fourth year, the Romans actually introduced it every third year, starting in 45 BCE. It took until 12 BCE for the error to be corrected. – Harry Weston Jan 1 '16 at 12:11
31
  • Virtually all shell arrays (Bourne, csh, tcsh, fish, rc, es, yash) start at 1. ksh is the only exception that I know (bash just copied ksh).
  • Most interpreted languages at the time (early 90s): awk, tcl at least, and tools typically used from the shell (cut -f1-3, head -n 3, sort -k1,3, cal 1 2015, comm -1) start at 1. sed, ed, vi number their lines from 1...
  • zsh takes the best of the Bourne shell and csh. The Bourne shell array $@ start at 1. zsh is consistent with its handling of $@ (like in Bourne) or $argv (like in csh). See how confusing it is in ksh where ${@:0:1} does not give you the first positional parameter for instance.
  • A shell is a user tool before being a programming language. It makes sense for most users to have the first element in $a[1]. It also means that the number of elements is the same as the last indice (in zsh like in most other shells except ksh, arrays are not sparse).
  • a[1] for the first element is consistent with a[-1] for the last.

So IMO the question should rather be: what got into David Korn's head to make its arrays start at 0?

  • 1
    and lua, i think. – mikeserv Dec 30 '15 at 21:23
  • 7
    It's a bug in human languages that numbering is one-based, and remarkable serendipity that most programming languages managed to keep that legacy out of their design. All the sadder that, after zero-based indexing was virtually established as the standard, so many “user-oriented” languages got it backwards, trying to be “simpler” by using the wrong, one-based indexing again. — That said: the best way to avoid indexing confusion is of course to avoid numerical indices entirely. – leftaroundabout Dec 31 '15 at 10:46
  • 1
    You can either justify that 0 was added AFTER to the human knowledge, and it somehow messed up things that time. theguardian.com/notesandqueries/query/0,5753,-1358,00.html - Again, just a matter of point of view :) – user34720 Dec 31 '15 at 11:04
  • 3
    Bourne shell array $@ starts at 0 (not 1) $0 is the name of program you are running. you should correct your third point – Edward Torvalds Jan 7 '16 at 9:54
  • 2
    @edwardtorvalds, No, $0 is not a positional parameters. It is not part of $@. "$@" is "$1" "$2" .... When it comes to functions, in many shells, you see that "$@" are the arguments to the function, while $0 stays the script path (or shell argv[0] when not running a script) – Stéphane Chazelas Feb 22 '16 at 15:42
7

I think the most plausible answer to this is the reverse array built-in from zsh

If you have an array with 4 elements, lets say myvar=(1 2 3 4) and you want to access the 4th element it will be print $myvar[4], right?

However, if you want to create a loop that will list the elements inside this array backwards, it's just a matter of using negative indexes:

print $myvar[-1]   # will print 4
print $myvar[-2]   # will print 3
print $myvar[-3]   # will print 2
print $myvar[-4]   # will print 1

This should explain since starting from zero, you will not reach one of those elements as there is no -0.

The second reason behind this is probably the C code related to variables on zsh is using int or double int to define array indexes, and since it uses Two's Complement to represent negative numbers there is no way to represent -0(Signed zero), like you can do on float point variables.

If you are really used to indexes starting at 0, i suggest you to use the KSH_ARRAYS option to fix this.

And taking the hook of @cuonglm comment, the csh features implemented on zsh are explained here. It seems not to be a historical reason but a way to provide a confortable work environment for those who are used with csh

  • 3
    Then, this should make you access the first and last array items at the same time, breaking all the logic of scanning an array ;) Could even create a blackhole. LOL – user34720 Dec 30 '15 at 18:13
  • 2
    for 0-indexed arrays replace the - with ~. – mikeserv Dec 30 '15 at 21:16
  • 1
    @mfxx - i was talking about bash. i think it handles negative indices for set elements as syntax sugar, but then doesn't do so otherwise. can't remember. from my perspective, people should just create a directory and use files for whatever they're stuffing into all that shell state. you can index those elements any which way you like. – mikeserv Dec 30 '15 at 22:00
  • 1
    ~ is binary inversion. ~0 is -1. (all bits flipped, relies on how negative numbers are usually represented bit-wise). On an unset array or an array with only one element of indice 0, a[0], a[-0], a[-1] and a[~0] will give you the same thing in a ksh-like array. – Stéphane Chazelas Dec 30 '15 at 22:02
  • 1
    @StéphaneChazelas - yeah, i think i remember handling this with ~ when -index didn't work. I guess probably all i did was ~-index. yeah. that sounds right. yes! and of course that works for unset elements as well. so i guess the comment above should be - for 0-indexed arrays add ~. i guess it just handled the -1 part easier maybe. i dunno. its not jumping to the forefront of my memory at the moment... – mikeserv Dec 30 '15 at 23:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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