Có một lý do tại sao phần tử đầu tiên của mảng Zsh được lập chỉ mục bằng 1 thay vì 0?


27

Từ kinh nghiệm của tôi với các ngôn ngữ lập trình và kịch bản hiện đại, tôi tin rằng hầu hết các lập trình viên thường quen với việc coi phần tử đầu tiên của một mảng bằng 0 là chỉ mục.
Có bất kỳ lợi thế đáng kể trong việc sử dụng 1 ?

Tôi chắc rằng tôi đã nghe nói về nhiều ngôn ngữ khác ngoài Zsh hoạt động tương tự với các mảng; nó ổn với tôi, vì nó tiện lợi không kém.
Tuy nhiên, như các ngôn ngữ kịch bản lệnh shell được phát hành và sử dụng rộng rãi như ksh và bash đều sử dụng 0, tại sao ai đó lại chọn thay đổi "tiêu chuẩn" phổ biến này?

Câu trả lời ngay lập tức của tôi cho câu hỏi của tôi sẽ là "tất nhiên là không";
sau đó, lời giải thích duy nhất tôi có thể nghĩ đến liên quan đến "tính năng độc quyền" này đối với đạn pháo là " họ chỉ làm điều này để thể hiện một chút vỏ sò tuyệt vời của họ ".

Tôi không biết nhiều về Zsh hoặc lịch sử của nó, và có khả năng cao lý thuyết tầm thường của tôi về điều này không có ý nghĩa gì.

Có một lời giải thích cho điều này? Hay chỉ là ra khỏi sở thích cá nhân?


5
Một số nghiên cứu lịch sử (hoặc suy nghĩ lại?) Về chủ đề 0 so với 1: exple.tive.org/blarg/2013/10/22/cites-needed
thrig

Vì lý do lịch sử, điều đó có lẽ đến từ csh, cũng sử dụng lập chỉ mục mảng dựa trên một.
cuonglm

3
ngày nay, sh là một ngôn ngữ tiêu chuẩn (không phải là một triển khai) có các thông dịch viên khác nhau có thể. Một số trình thông dịch cho ngôn ngữ sh như bash, ksh và yash hỗ trợ các mảng như phần mở rộng, nhưng chúng không phải là một phần của ngôn ngữ giống như gcc, trình biên dịch cho ngôn ngữ C tiêu chuẩn hỗ trợ các phần mở rộng so với ngôn ngữ C tiêu chuẩn. Và cũng giống như đối với C, không có triển khai "chính thức" của trình thông dịch "sh".
Stéphane Chazelas


4
Có thể một chút lạc đề, nhưng có liên quan. Người La Mã đã sử dụng tính bao gồm, nhìn chằm chằm từ một thay vì số không. Ngày sau ngày mai, đối với chúng tôi "hai ngày trước", là với họ "ba ngày trước". Họ tính hôm nay là một, không phải không. Hậu quả là khi các nhà thiên văn học Ai Cập của họ đề xuất một ngày nhuận mỗi năm thứ tư, người La Mã thực sự đã giới thiệu nó vào mỗi năm thứ ba, bắt đầu từ năm 45 trước Công nguyên. Phải mất đến 12 BCE để sửa lỗi.
Harry Weston

Câu trả lời:


32
  • Hầu như tất cả các mảng vỏ (Bourne, csh, tcsh, fish, rc, es, yash) bắt đầu từ 1. ksh là ngoại lệ duy nhất mà tôi biết (bash chỉ sao chép ksh).
  • Ngôn ngữ giải thích nhất vào thời điểm đó (những năm 90): awk, tclít nhất, và các công cụ thường được sử dụng từ vỏ ( cut -f1-3, head -n 3, sort -k1,3, cal 1 2015, comm -1) bắt đầu từ 1. sed, ed, visố dòng họ từ 1 ...
  • zsh lấy tốt nhất vỏ Bourne và csh. Mảng vỏ Bourne $@bắt đầu từ 1. zsh phù hợp với việc xử lý $@(như trong Bourne) hoặc $argv(như trong csh). Xem làm thế nào nó gây nhầm lẫn ở kshnơi ${@:0:1}không cung cấp cho bạn tham số vị trí đầu tiên chẳng hạn.
  • Shell là một công cụ người dùng trước khi trở thành ngôn ngữ lập trình. Nó có ý nghĩa cho hầu hết người dùng có yếu tố đầu tiên trong $a[1]. Điều đó cũng có nghĩa là số lượng phần tử giống như chỉ số cuối cùng (trong zsh như trong hầu hết các shell khác ngoại trừ ksh, mảng không thưa thớt).
  • a[1]cho phần tử đầu tiên phù hợp với a[-1]phần cuối cùng.

Vì vậy, IMO câu hỏi nên là: những gì đã vào đầu David Korn để làm cho mảng của nó bắt đầu từ 0?


7
Đó là một lỗi trong ngôn ngữ của con người, việc đánh số là dựa trên một, và sự ngẫu nhiên đáng chú ý mà hầu hết các ngôn ngữ lập trình quản lý để giữ di sản đó ra khỏi thiết kế của họ. Tất cả các buồn hơn đó, sau khi lập chỉ mục zero-based được hầu như thành lập như là tiêu chuẩn, do đó, nhiều ngôn ngữ “sử dụng theo định hướng” đã nhận nó ngược, cố gắng trở thành “đơn giản” bằng sai , lập chỉ mục một dựa trên một lần nữa. - Điều đó nói rằng: cách tốt nhất để tránh nhầm lẫn lập chỉ mục là tất nhiên để tránh các chỉ số số hoàn toàn.
leftaroundabout

Đọc ở đây: "Khi xử lý một chuỗi có độ dài N, các yếu tố mà chúng tôi muốn phân biệt bằng chỉ mục, ... a) mang lại, khi bắt đầu với chỉ mục 1, phạm vi chỉ số 1 ≤ i <N + 1; bắt đầu bằng 0, tuy nhiên, cung cấp phạm vi đẹp hơn 0 ≤ i <N . " . Không biết TROLL hoặc STUPID, nhưng bạn có thể sử dụng "1 ≤ i ≤ N" cho các đăng ký bắt đầu bằng 1 trên mảng. Không cần phải đặt +1 đó vào cuối quá trình quét mảng và cả hai quan điểm đều không chứng minh rằng các chỉ mục bắt đầu với 1 hoặc 0 là tốt hơn.

1
Bạn có thể biện minh rằng 0 đã được thêm SAU vào kiến ​​thức của con người và bằng cách nào đó nó đã làm rối tung mọi thứ vào thời điểm đó. theguardian.com/notesandqueries/query/0,5753,-1353,00.html - Một lần nữa, chỉ là vấn đề quan điểm :)

3
Mảng shell Bourne $ @ bắt đầu từ 0 (không phải 1) $ 0 là tên chương trình bạn đang chạy. bạn nên sửa điểm thứ ba của mình
Edward Torvalds

2
@edwardtorvalds, Không, $0không phải là một tham số vị trí. Nó không phải là một phần của $@. "$@""$1" "$2" .... Khi nói đến các hàm, trong nhiều shell, bạn thấy đó "$@"là các đối số của hàm, trong khi $0vẫn giữ đường dẫn tập lệnh (hoặc shell argv [0] khi không chạy tập lệnh)
Stéphane Chazelas 22/2/2016

7

Tôi nghĩ rằng câu trả lời hợp lý nhất cho điều này là mảng ngược được tích hợp từ zsh

Nếu bạn có một mảng với 4 phần tử, giả sử myvar=(1 2 3 4)và bạn muốn truy cập phần tử thứ 4 thì nó sẽ như vậy print $myvar[4], phải không?

Tuy nhiên, nếu bạn muốn tạo một vòng lặp sẽ liệt kê các phần tử bên trong mảng này về phía sau, thì đó chỉ là vấn đề sử dụng các chỉ mục tiêu cực:

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

Điều này sẽ giải thích vì bắt đầu từ số không, bạn sẽ không đạt được một trong những yếu tố đó vì không có -0.

Lý do thứ hai đằng sau điều này có lẽ là mã C liên quan đến các biến trên zsh đang sử dụng inthoặc double intđể xác định các chỉ mục mảng và vì nó sử dụng Two's Compuity để biểu diễn các số âm nên không có cách nào để biểu thị -0( Đã ký 0 ), giống như bạn có thể làm trên float biến điểm.

Nếu bạn thực sự quen với các chỉ mục bắt đầu từ 0, tôi khuyên bạn nên sử dụng KSH_ARRAYStùy chọn để sửa lỗi này.

Và lấy ý kiến ​​của @cuonglm, các cshtính năng được triển khai trên zshđược giải thích ở đây . Nó dường như không phải là một lý do lịch sử mà là một cách để cung cấp một môi trường làm việc dễ hiểu cho những người đã quen vớicsh


3
Sau đó, điều này sẽ khiến bạn truy cập vào các mục mảng đầu tiên và cuối cùng cùng một lúc, phá vỡ mọi logic của việc quét một mảng;) thậm chí có thể tạo ra một lỗ đen. LOL

3
cho các mảng 0 chỉ mục thay thế -bằng ~.
mikeserv

1
@mfxx - Tôi đã nói về bash. tôi nghĩ rằng nó xử lý các chỉ số tiêu cực cho các phần tử được đặt thành đường cú pháp, nhưng sau đó không làm như vậy. không thể nhớ từ quan điểm của tôi, mọi người chỉ nên tạo một thư mục và sử dụng các tệp cho bất cứ điều gì họ đang nhồi vào tất cả trạng thái vỏ đó. bạn có thể lập chỉ mục các yếu tố đó theo bất kỳ cách nào bạn thích.
mikeerv

1
~là nghịch đảo nhị phân. ~0-1. (tất cả các bit được lật, dựa vào cách các số âm thường được biểu diễn theo bit-khôn ngoan). Trên một mảng không đặt hoặc một mảng chỉ có một phần tử của chỉ số 0, [0], [-0], [-1] và [~ 0] sẽ cung cấp cho bạn cùng một thứ trong mảng giống như ksh.
Stéphane Chazelas

1
@ StéphaneChazelas - vâng, tôi nghĩ tôi nhớ xử lý việc này ~khi -indexkhông hoạt động. Tôi đoán có lẽ tất cả những gì tôi đã làm là ~-index. vâng Nghe có vẻ đúng. Vâng! và tất nhiên là cũng hoạt động cho các yếu tố unset. vì vậy tôi đoán những nhận xét trên nên được - cho mảng 0-lập chỉ mục thêm ~ . tôi đoán nó có thể xử lý phần -1 dễ dàng hơn có thể. tôi không biết. nó không nhảy lên hàng đầu trong trí nhớ của tôi vào lúc này ...
mikeerv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.