是否有理由将Zsh数组的第一个元素索引为1而不是0?


27

根据我对现代编程和脚本语言的经验,我相信大多数程序员通常习惯于将0数组的第一个元素称为索引。
使用1有什么实质性的优势?

我敢肯定,除了Zsh之外,我还听说过更多其他与数组类似的语言;我也很好,因为它同样方便。
但是,由于以前发行和广泛使用的shell脚本语言(例如ksh和bash都使用0), 为什么有人会选择更改此通用“标准”?

我对我的问题的立即回答是“当然不是”。
那么,我能想到的关于外壳的这种“专有功能”的唯一解释是“ 他们只是这样做是为了炫耀更多酷的外壳 ”。

我对Zsh或它的历史一无所知,而我对此琐碎的理论很有可能没有任何意义。

对此有解释吗?还是只是出于个人品味?


5
关于0:1:1的一些历史研究(或值得反思)?exple.tive.org/blarg/2013/10/22/citation-needed
thrig 2015年

由于历史原因,这可能来自csh,它也使用了基于1的数组索引。
cuonglm

3
如今,sh是一种具有不同可能解释器的标准语言(不是实现)。一些b语言,bsh,ksh和yash等sh语言的解释器支持数组作为扩展,但它们不像gcc那样是语言的一部分,gcc是标准C语言的编译器支持对标准C语言的扩展。就像C语言一样,没有“ sh”解释器的“正式”实现。
斯特凡Chazelas


4
也许有点偏离主题,但相关。罗马人使用包容性计数,从一开始而不是从零开始。后天,对我们来说,“提前两天”,对他们来说,是“提前三天”。今天,他们算为1,而不是0。结果,当埃及天文学家每四年建议一次leap日时,罗马人实际上是从公元前45年开始每三年介绍一次leap日。直到12 BCE才纠正了错误。
哈里韦斯顿

Answers:


32
  • 几乎所有的shell数组(Bourne,csh,tcsh,fish,rc,es,yash)都从1开始。ksh是我所知道的唯一例外(bash只是复制了ksh)。
  • 当时大多数解释型语言(90年代初): awktcl至少和工具通常从外壳使用(cut -f1-3head -n 3sort -k1,3cal 1 2015comm -1)从1开始sededvi数他们的线路,从1 ...
  • zsh充分利用了Bourne shell和csh。Bourne shell数组$@从1开始。zsh与其对$@(如在Bourne中)或$argv(如在csh中)的处理一致。例如,ksh${@:0:1}没有给您第一个位置参数的地方,看看它有多混乱。
  • Shell是成为编程语言之前的用户工具。对于大多数用户来说,在中拥有第一个元素是有意义的$a[1]。这也意味着元素的数量与最后一个索引相同(在zsh中,与除ksh以外的大多数其他shell一样,数组不是稀疏的)。
  • a[1]第一个元素与a[-1]最后一个元素一致。

因此,IMO的问题应该是:是什么使David Korn想到使数组从0开始?


7
在人类语言中,有一个错误,即编号是基于一个的,并且具有惊人的偶然性,大多数编程语言设法将其遗留物排除在设计之外。令人遗憾的是,几乎从零开始的索引被确立为标准之后,许多“面向用户”的语言将其倒退,试图通过再次使用基于错误的基于错误的索引来变得“更简单” 。—也就是说:避免索引混乱的最好方法当然是完全避免数字索引。
大约

在此阅读:“当处理长度为N的序列时,我们希望通过下标来区分元素,... a)从下标1开始产生,下标范围1≤i <N + 1;从0给出了更好的范围0≤i <N。不知道是TROLL还是STUPID,但是可以对数组中以1开头的下标使用“ 1≤i≤N”。无需在数组扫描的末尾加上+1,而且任何一种观点都不能证明以1或0开头的索引更好。

1
您可以证明在人类知识之后添加了0,这在某种程度上搞乱了当时的情况。theguardian.com/notesandqueries/query/0,5753,-1358,00.html-再次,只是一个问题:)

3
Bourne shell数组$ @始于0(而不是1)。$ 0是您正在运行的程序的名称。您应该纠正您的第三点
爱德华·托瓦尔兹

2
@edwardtorvalds,否,$0不是位置参数。它不是的一部分$@"$@""$1" "$2" ...。当涉及到函数时,在许多shell中,您会看到它们"$@"是函数的参数,而$0保留了脚本路径(或不运行脚本时为shell argv [0])
StéphaneChazelas 16/02/22

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

这背后的第二个原因可能是与zsh上的变量相关的C代码正在使用intdouble int定义数组索引,并且由于它使用Two's Complement表示负数,因此无法表示-0Signed zero),就像在float上一样点变量。

如果您真的习惯于从0开始的索引,我建议您使用该KSH_ARRAYS选项来解决此问题。

并使用@cuonglm注释的钩子,此处说明csh实现的功能。这似乎不是历史原因,而是一种为那些习惯于工作的人提供舒适的工作环境的方法。zshcsh


3
然后,这应该使您可以同时访问第一个和最后一个数组项,从而破坏了扫描数组的所有逻辑;)甚至可能会创建一个黑洞。大声笑

3
为0索引的数组代替-~
mikeserv

1
@mfxx-我在说bash。我认为它可以将设置元素的负索引作为语法糖处理,但否则就不这样做。不记得了。从我的角度来看,人们应该只创建一个目录并使用文件填充到所有这些shell状态。您可以按自己喜欢的方式对这些元素建立索引。
mikeserv

1
~是二进制反转。~0-1。(所有位都翻转,取决于通常如何按位表示负数)。在未设置的数组或仅包含索引0的一个元素的数组上,a [0],a [-0],a [-1]和a [〜0]将在类似ksh的数组中提供相同的功能。
斯特凡Chazelas

1
@StéphaneChazelas-是的,我想我记得~-index无法正常工作时处理此问题。我想我可能所做的只是~-index。是的 听起来不错。是!当然也适用于未设置的元素。所以我想上面的评论应该是-对于0索引数组add ~。我想它也许更容易处理-1部分。我不知道。它现在还没有跳到我记忆的最前沿……
mikeserv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.