Gibt es einen Grund, warum das erste Element eines Zsh-Arrays durch 1 anstelle von 0 indiziert wird?

27

Aufgrund meiner Erfahrung mit modernen Programmier- und Skriptsprachen sind die meisten Programmierer daran gewöhnt, das erste Element eines Arrays mit 0 als Index zu bezeichnen.
Gibt es wesentliche Vorteile bei der Verwendung von 1 ?

Ich bin sicher, ich habe von mehr Sprachen als Zsh gehört, die sich mit Arrays ähnlich verhalten. Es ist in Ordnung für mich, da es genauso bequem ist.
Da jedoch zuvor veröffentlichte und weit verbreitete Shell-Skriptsprachen wie ksh und bash alle 0 verwenden, warum sollte sich jemand dafür entscheiden, diesen gemeinsamen "Standard" zu ändern?

Meine sofortige Antwort auf meine Frage wäre "natürlich nicht";
Die einzige Erklärung, die ich in Bezug auf dieses etwas "exklusive" Feature für Shells finden kann, wäre " sie haben dies nur getan, um ihre coole Shell ein bisschen besser zur Geltung zu bringen ".

Ich weiß jedoch nicht viel über Zsh oder seine Geschichte, und es ist sehr wahrscheinlich, dass meine triviale Theorie dazu keinen Sinn ergibt.

Gibt es eine Erklärung dafür? Oder ist es nur aus persönlichem Geschmack?

deekin
quelle
5
Einige historische Forschungen (oder rantish ruminations?) Zum Thema 0 versus 1: exple.tive.org/blarg/2013/10/22/citation-needed
thrig
Aus historischen Gründen ist dies wahrscheinlich der Fall csh, bei dem auch eine einbasierte Array-Indizierung verwendet wurde.
Donnerstag,
3
Heutzutage ist sh eine Standardsprache (keine Implementierung) mit verschiedenen möglichen Interpreten. Einige dieser Interpreter für die Sprache sh wie bash, ksh und yash unterstützen Arrays als Erweiterung, aber sie sind nicht Teil der Sprache wie gcc, ein Compiler für die Standardsprache C unterstützt Erweiterungen über die Standardsprache C. Und genau wie für C gibt es keine "offizielle" Implementierung eines "sh" -Interpreters.
Stéphane Chazelas
1
Related - Kommentare in dieser PPCG Antwort
Digital Trauma
4
Vielleicht ein bisschen vom Thema abweichend, aber relevant. Die Römer zählten inklusive und starrten von eins statt von null. Übermorgen, für uns "zwei Tage voraus", für sie "drei Tage voraus". Sie zählten heute als eins und nicht als null. Als ihre ägyptischen Astronomen alle vier Jahre einen Schalttag empfahlen, führten die Römer ihn ab 45 v. Chr. Alle drei Jahre ein. Es dauerte bis 12 v. Chr., Bis der Fehler behoben war.
Harry Weston

Antworten:

32
  • Praktisch alle Shell-Arrays (Bourne, csh, tcsh, fish, rc, es, yash) beginnen bei 1. ksh ist die einzige mir bekannte Ausnahme (bash hat gerade ksh kopiert).
  • Die meisten interpretierten Sprachen zu der Zeit (Anfang der 90er Jahre): awk, tclzumindest, und Werkzeuge typischerweise aus der Schale verwendet wird ( cut -f1-3, head -n 3, sort -k1,3, cal 1 2015, comm -1) bei 1 beginnen sed, ed, viAnzahl ihre Linien von 1 ...
  • zsh nutzt das Beste aus der Bourne-Shell und csh. Das Bourne-Shell-Array $@beginnt bei 1. zsh entspricht der Behandlung von $@(wie in Bourne) oder $argv(wie in csh). Sehen Sie, wie verwirrend es ist, kshwenn ${@:0:1}Sie beispielsweise nicht den ersten Positionsparameter erhalten.
  • Eine Shell ist ein Anwenderprogramm, bevor sie eine Programmiersprache ist. Für die meisten Benutzer ist es sinnvoll, das erste Element in zu haben $a[1]. Dies bedeutet auch, dass die Anzahl der Elemente mit dem letzten Index identisch ist (in zsh wie in den meisten anderen Shells mit Ausnahme von ksh sind Arrays nicht spärlich).
  • a[1]denn das erste Element stimmt mit a[-1]dem letzten überein .

Die Frage sollte also lauten: Was ist in David Korns Kopf geraten, damit seine Arrays bei 0 beginnen?

Stéphane Chazelas
quelle
7
Es ist ein Fehler in den menschlichen Sprachen, dass die Nummerierung auf einer Grundlage basiert und ein bemerkenswerter Zufall ist, dass die meisten Programmiersprachen es geschafft haben, dieses Erbe aus ihrem Design herauszuhalten. Umso trauriger ist es, dass nach der Einführung der auf Null basierenden Indexierung als Standard so viele „benutzerorientierte“ Sprachen die Indexierung rückgängig machten und versuchten, „einfacher“ zu werden, indem sie erneut die falsche einseitige Indexierung verwendeten. - Das heißt: Der beste Weg, Verwechslungen bei der Indexierung zu vermeiden, besteht natürlich darin, numerische Indizes gänzlich zu vermeiden.
links um 31.12.15 Uhr
Lesen wir hier: "Wenn wir uns mit einer Folge der Länge N befassen, deren Elemente wir durch den Index unterscheiden wollen, ... a) ergibt sich beginnend mit dem Index 1 der Indexbereich 1 ≤ i <N + 1; beginnend mit 0 gibt jedoch den schöneren Bereich 0 ≤ i <N. " . Weiß nicht, ob TROLL oder STUPID, aber Sie können "1 ≤ i ≤ N" für Indizes verwenden, die mit 1 auf Arrays beginnen. Es ist nicht erforderlich, +1 am Ende des Array-Scans einzufügen, und keiner der Gesichtspunkte belegt, dass das Starten von Indizes mit 1 oder 0 besser ist.
1
Sie können entweder rechtfertigen, dass 0 NACH dem menschlichen Wissen hinzugefügt wurde, und es hat die Dinge in dieser Zeit irgendwie durcheinander gebracht. theguardian.com/notesandqueries/query/0,5753,-1358,00.html - Auch dies ist nur eine Frage der Sichtweise :)
3
Das Bourne-Shell-Array $ @ beginnt bei 0 (nicht bei 1). $ 0 ist der Name des Programms, das Sie ausführen. Sie sollten Ihren dritten Punkt korrigieren
Edward Torvalds
2
@edwardtorvalds, Nein, $0ist kein Positionsparameter. Es ist nicht Teil von $@. "$@"ist "$1" "$2" .... Wenn es um Funktionen geht, sehen Sie in vielen Shells, dass dies "$@"die Argumente für die Funktion sind, während $0der Skriptpfad (oder Shell argv [0], wenn kein Skript ausgeführt wird)
beibehalten wird
7

Ich denke, die plausibelste Antwort auf diese Frage ist das eingebaute Reverse-Array von zsh

Wenn Sie ein Array mit 4 Elementen haben, nehmen wir an, myvar=(1 2 3 4)Sie möchten auf das 4. Element zugreifen print $myvar[4], oder?

Wenn Sie jedoch eine Schleife erstellen möchten, in der die Elemente in diesem Array rückwärts aufgelistet werden, müssen nur negative Indizes verwendet werden:

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

Dies sollte erklären, da Sie ab Null keines dieser Elemente erreichen, da es kein Element gibt -0.

Der zweite Grund dafür ist wahrscheinlich, dass der C-Code, der sich auf Variablen in zsh bezieht , Array-Indizes verwendet intoder double intdefiniert. Da hier das Zweierkomplement zur Darstellung negativer Zahlen verwendet wird, gibt es keine Möglichkeit zur Darstellung -0( Null mit Vorzeichen ), wie dies bei float möglich ist Punktvariablen.

Wenn Sie es wirklich gewohnt sind, Indizes zu erstellen, die bei 0 beginnen, empfehle ich Ihnen, die KSH_ARRAYSOption zu verwenden, um dies zu beheben.

Und der Haken von @cuonglm Kommentar nehmen, die cshimplementierten Funktionen auf zsherläutert hier . Es scheint kein historischer Grund zu sein, sondern ein Weg, ein angenehmes Arbeitsumfeld für diejenigen zu schaffen, die es gewohnt sindcsh


quelle
3
Dann sollten Sie gleichzeitig auf das erste und das letzte Array-Element zugreifen und so die gesamte Logik zum Scannen eines Arrays aufheben. LOL
3
Ersetzen Sie -bei Arrays mit 0-Index das mit ~.
mikeserv
1
@mfxx - ich habe darüber gesprochen bash. Ich denke, es behandelt negative Indizes für Set- Elemente als Syntax-Zucker, aber sonst nicht. kann mich nicht erinnern. Aus meiner Sicht sollten die Leute einfach ein Verzeichnis erstellen und Dateien für alles verwenden, was sie in den gesamten Shell-Status einfügen. Sie können diese Elemente beliebig indizieren.
mikeserv
1
~ist binäre Inversion. ~0ist -1. (Alle Bits werden umgedreht, dies hängt davon ab, wie negative Zahlen normalerweise bitweise dargestellt werden.) Auf einem nicht gesetzten Array oder einem Array mit nur einem Element des Index 0 geben ein [0], ein [-0], ein [-1] und ein [~ 0] dasselbe in einem ksh-ähnlichen Array.
Stéphane Chazelas
1
@ StéphaneChazelas - Ja, ich denke, ich erinnere mich, wie ich damit umgegangen bin, ~als -indexes nicht funktioniert hat. Ich schätze, alles was ich getan habe war ~-index. Ja. das klingt richtig Ja! und das funktioniert natürlich auch für nicht gesetzte elemente. Also, ich denke, der Kommentar oben sollte sein - für 0-indizierte Arrays hinzufügen ~ . Ich denke, es hat den -1-Teil vielleicht einfacher gehandhabt. Ich weiß nicht. Es ist im Moment nicht an die Spitze meines Gedächtnisses
gesprungen