Есть ли причина, по которой первый элемент массива Zsh индексируется 1 вместо 0?

27

Исходя из моего опыта работы с современными языками программирования и сценариев, я полагаю, что большинство программистов обычно привыкли ссылаться на первый элемент массива 0 как индекс.
Есть ли существенные преимущества в использовании 1 ?

Я уверен, что слышал о большем количестве языков, кроме Zsh, которые ведут себя аналогично с массивами; это нормально для меня, так же как и удобно.
Однако, поскольку ранее выпущенные и широко используемые языки сценариев оболочки, такие как ksh и bash, все используют 0, почему кто-то решил изменить этот общий "стандарт"?

Мой немедленный ответ на мой вопрос будет «конечно, нет»;
затем, единственное объяснение, которое я могу придумать, относясь к этой несколько «исключительной функции» к оболочкам, это « они просто сделали это, чтобы показать немного больше своей крутой оболочки ».

Я не знаю много ни о Zsh, ни о его истории, и есть большая вероятность, что моя тривиальная теория об этом не имеет никакого смысла.

Есть ли объяснение этому? Или это просто из личного вкуса?

deekin
источник
5
Некоторые исторические исследования (или бессмысленные размышления?) На тему 0 против 1: exple.tive.org/blarg/2013/10/22/citation-needed
thrig
По историческим причинам, это, вероятно, произошло csh, который также использовал индексацию массивов на основе одного.
cuonglm
3
в настоящее время sh является стандартным языком (не реализацией), который имеет разные возможные интерпретаторы. Некоторые из этих интерпретаторов для языка sh, такие как bash, ksh и yash, поддерживают массивы в качестве расширений, но они не являются частью языка так же, как gcc, компилятор для стандартного языка C поддерживает расширения по сравнению со стандартным языком C. Как и в случае с C, нет «официальной» реализации интерпретатора «sh».
Стефан Шазелас
1
Связанный - комментарии в этом ответе PPCG
Цифровая Травма
4
Может быть, немного не по теме, но актуально. Римляне использовали инклюзивный подсчет, начиная с одного, а не с нуля. Послезавтра для нас «на два дня вперед» было для них «на три дня вперед». Они считаются сегодня как один, а не ноль. Как следствие, когда их египетские астрономы рекомендовали високосный день каждый четвертый год, римляне фактически вводили его каждый третий год, начиная с 45 г. до н.э. Для исправления ошибки потребовалось до 12 г. до н.э.
Гарри Уэстон

Ответы:

32
  • Практически все массивы оболочки (Bourne, csh, tcsh, fish, rc, es, yash) начинаются с 1. ksh - единственное исключение, которое я знаю (bash только что скопировал ksh).
  • Наиболее интерпретируемые языки в то время ( в начале 90 - х годов): awk, tclпо крайней мере, и инструменты , как правило , используются из оболочки ( cut -f1-3, head -n 3, sort -k1,3, cal 1 2015, comm -1) начинаются с 1. sed, ed, viчисло их линии от 1 ...
  • zsh берет лучшее из оболочки Bourne и csh. Массив оболочки Bourne $@начинается с 1. zsh соответствует его обработке $@(как в Bourne) или $argv(как в csh). Посмотрите, как это сбивает с толку, kshгде, например ${@:0:1}, не дает вам первый позиционный параметр.
  • Оболочка - это инструмент пользователя, прежде чем стать языком программирования. Для большинства пользователей имеет смысл иметь первый элемент в $a[1]. Это также означает, что количество элементов совпадает с последним индексом (в zsh, как и в большинстве других оболочек, кроме ksh, массивы не редки).
  • a[1]для первого элемента согласуется с a[-1]последним.

Так что IMO вопрос должен быть: что пришло в голову Дэвиду Корну, чтобы его массивы начинались с 0?

Стефан Шазелас
источник
7
Это ошибка в человеческих языках в том, что нумерация основана на одном, и это удивительно, что большинству языков программирования удалось сохранить это наследие в своем дизайне. Весьма печально, что после того, как индексирование на основе нуля фактически стало стандартом, многие «ориентированные на пользователя» языки получили его задом наперед, пытаясь быть «проще», снова используя неправильную индексацию на основе одного. Тем не менее, лучший способ избежать путаницы при индексировании - это, конечно, полностью избегать числовых индексов.
оставил около
Чтение здесь: «Имея дело с последовательностью длины N, элементы которой мы хотим различить по нижнему индексу, ... a), получая, начиная с нижнего индекса 1, диапазон нижнего индекса 1 ≤ i <N + 1; начиная с 0, однако, дает более хороший диапазон 0 ≤ i <N . " Не знаю, TROLL или STUPID, но вы можете использовать «1 ≤ i ≤ N» для индексов, начинающихся с 1 на массивах. Нет необходимости помещать это +1 в конце сканирования массива, и ни одна из точек зрения не доказывает, что начальные индексы с 1 или 0 лучше.
1
Вы можете либо оправдать, что 0 был добавлен ПОСЛЕ человеческих знаний, и это как-то испортило вещи в то время. theguardian.com/notesandqueries/query/0,5753,-1358,00.html - опять- таки , просто вопрос точки зрения :)
3
Массив оболочки Bourne $ @ начинается с 0 (не 1) $ 0 - это имя программы, которую вы запускаете. Вы должны исправить свой третий пункт
Эдвард Торвальдс
2
@edwardtorvalds, Нет, $0это не позиционные параметры. Это не часть $@. "$@"есть "$1" "$2" .... Когда дело доходит до функций, во многих оболочках вы видите, что они "$@"являются аргументами функции, в то время как $0остается путь к сценарию (или оболочка argv [0], когда сценарий не запущен)
Стефан Шазелас
7

Я думаю, что наиболее вероятный ответ на это обратный массив, встроенный из zsh

Если у вас есть массив с 4 элементами, допустим, myvar=(1 2 3 4)и вы хотите получить доступ к 4-му элементу, это будет так print $myvar[4], верно?

Однако, если вы хотите создать цикл, который будет перечислять элементы внутри этого массива в обратном порядке, это просто вопрос использования отрицательных индексов:

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

Это должно быть объяснено, поскольку, начиная с нуля, вы не достигнете ни одного из этих элементов, поскольку его нет -0.

Вторая причина этого, вероятно, заключается в том, что код C, связанный с переменными в zsh, использует intили double intдля определения индексов массива, и, поскольку он использует дополнение Two для представления отрицательных чисел, нет способа представить -0( подписанный ноль ), как вы можете сделать в float. точечные переменные.

Если вы действительно привыкли к индексам, начинающимся с 0, я предлагаю вам использовать KSH_ARRAYSопцию, чтобы это исправить.

И, взяв крюк комментария @cuonglm, cshфункции, которые были реализованы, zshописаны здесь . Кажется, это не историческая причина, а способ обеспечить комфортную рабочую среду для тех, кто используется сcsh


источник
3
Затем это должно заставить вас обращаться к первому и последнему элементам массива одновременно, нарушая всю логику сканирования массива;) Может даже создать черную дыру. LOL
3
для 0-индексированные массивы заменить -с ~.
mikeserv
1
@ mfxx - я говорил о bash. я думаю, что он обрабатывает отрицательные индексы для элементов набора как синтаксический сахар, но в противном случае не делает этого иначе. не могу вспомнить с моей точки зрения, люди должны просто создать каталог и использовать файлы для всего, что они вставляют во все это состояние оболочки. Вы можете индексировать эти элементы по своему усмотрению.
mikeserv
1
~это двоичная инверсия ~0есть -1. (все биты перевернуты, полагается на то, как отрицательные числа обычно представляются побитовым образом). В неустановленном массиве или массиве, содержащем только один элемент с индексом 0, a [0], a [-0], a [-1] и a [~ 0] даст вам то же самое в массиве, подобном ksh.
Стефан Шазелас
1
@ StéphaneChazelas - да, я думаю, я помню, ~как -indexсправлялся с этим, когда не работал. Наверное, все, что я сделал, было ~-index. Да. это звучит правильно. да! и, конечно, это работает и для неустановленных элементов. поэтому я думаю, что комментарий выше должен быть - для 0-индексированных массивов добавить ~ . Я полагаю, это просто легче справиться с -1 частью. не знаю. это не прыгает на передний план моей памяти в данный момент ...
mikeserv