從 1 開始計算

lua-users home
維基

與現今最流行的程式語言相反,Lua 陣列的索引表示陣列中的順序位置,而不是從陣列開頭所偏移的位置。(這種方式不幸地被稱為「從 1 開始算」,導致許多人主張那是自然的計算方式。實際上,爭論在於使用偏移量相對於順序號來表示序列中的元素。)

Lua 核心確實 有一個 地方遵循這個原則:建構器的剖析,例如 {10,20,30} 。從 1 開始的慣例只由函式庫強制執行,而函式庫不是語言的一部分。--lhf

自 Lua 5.1 起,這種情況不再正確,因為 # 算子也依賴基本索引 1。


您誤解長度算子了。引用 Nick Gammon 在幾個段落後所說的話

從 Lua 手冊

表的長度定義為一個整數索引 n,其中 t[n] 非 nil,而 t[n+1] 為 nil;

此定義(源自 Lua 5.1 手冊)暗示表 { [-3] = 0 } 的長度為 -3,而完全空的表 {} 沒有長度(而不是長度為 0)。這比從 0 開始算更違背直覺。由於某些原因,PUC-Lua 5.1 不遵循這個定義:#{ [-3] == 0 } == 0。(Lua 5.2 手冊將定義變更為明確從 1 開始算。對於空的表來說,這仍然相當定義不明確,除非您知道範圍 {1..n} 對小於 1 的 n 應如何處理 -- 而且在不陷入類似陷阱的情況下對其進行定義有些棘手)。--f.

還有,讓我們直接處理這個問題:針對真實的表定義一個代理表,且索引中繼資料方法覆寫為在真實表中存取 i-1(如果 i 為正數)。決定是否直接將負數索引對應到真實表,或進一步處理它們。決定如何處理真實表中的索引 0。

完成後,在需要從 0 開始算的時候就使用代理表。在需要函式庫函數時就使用真實表。為了方便記憶,將您的表命名為『tablename1』,而代理表命名為『tablename0』。問題解決。


如果您是自稱為「腳本撰寫者」或「非程式設計師」的人士,以下是針對未來語言而提出的立場聲明。請讓大家知道您和任何一位程式設計師一樣,都能完全掌握偏移量概念。Lua 清單的基本索引為 1,因為這被認為對非程式設計師最友善,因為它讓索引與序數元素位置相符。然而,這種有爭議的讓步讓程式設計師非常苦惱,進而降低他們為您提供工具以完成工作的效率。原因之一是 Lua 與 C 緊密結合,而 C 的陣列基本索引為 0-- 索引代表與陣列開頭的偏移量。這表示同時編寫 Lua 和 C 的程式設計師必須不斷在他們的程式碼和思維中切換參考,這很惱人也很容易出錯。此外,事實證明使用偏移量會與某種不包含結尾的方式指定範圍(稱為半開範圍)有關,但使用序數位置則不會。半開範圍允許更自然地處理零長度範圍,進而產生更簡潔且一致的程式。

身為 C++ 和 Lua 程式設計師,我必須完全不同意這番咆哮。從 1 算起是「自然」的計算方式。在數學中,每個人都從 1 算起。從 0 算起只適用於 C 慣例,即陣列和指標是相等的,並且 a[i] 等於 *(a+i)。此外,我認為程式設計師可以輕鬆適應這種不像 C 的計算方式。但它讓 Lua 對「休閒程式設計師」更容易理解。--PeterPrade

同意,這是一番咆哮 :-)。然而,你的論點沒有說明半開範圍如何允許更簡潔的編碼,而這是我論點的主要重點。當使用範圍 Lua 時,程式會傾向充斥著 +1,因為 Lua 不使用半開範圍,但 C++(特別是在使用 STL 時,它整體上使用這種風格的範圍)時則不會發生這種情況。此外,我同意從 1 算起對人類來說是自然的(我從未表示過相反的意見),然而使用 [n, n-1] 來表示零長度範圍非常尷尬。告訴某人以地板上的某一點作為起點,然後再告訴他以落後一步的某一點作為終點,並不是傳達「不要往前走任何一步」的自然方式。相較之下,人類可以很輕易地理解「不要往前走任何一步」,方法是給他地板上的某一點作為起點,然後再給他與該點相同的點作為終點-- 相當於半開範圍 [n, n)。--JohnBelmonte

集合論者、論理学者、組合数学者はゼロから数えます。Z/nZ リング(n を法とする整数環)の要素は通常 {0, 1, ..., n-1} と名付けられているため、代数学者もゼロから数えます。これらはすべて CS と密接に関連した分野であり、したがってプログラミングにもつながります。解析では、1 から数えることがよくありますが、実際には関係ありません。自然数集合は通常、トポロジーで使用されるか、単に定義された「後退」および「前進」操作を使用する便利なインデックス設定として使用されます(ゼロを含めれば定義がよりエレガントになります)、そのため開始ポイントの選択はかなり恣意的になります(42 であっても同じです)。1 を選択するのは、習慣によるか、「下位互換性」(つまり、1 からの番号付けを使用する資料との相互理解可能性)を損なわないようにするか、分母/指数/その他にゼロを考慮しないようにするためです。 --f

半開区間を使用すると、簡潔なコーディングになる場合もあれば、そうでない場合もあります。私は、半開区間と閉区間、どちらでもフェンスポストエラーをたくさん見てきました(そして犯しました)。たとえば、C 配列の最後の要素のインデックスが配列の長さより 1 小さいという事実は、コード内にさまざまな種類の -1 が生じる可能性があります。これを排除するための手法があることは確かですが、私の Lua コードが +1だらけで、私の C コードが -1 で乱雑であるとは私は言いません。ただし、半開区間については深刻な問題があります。範囲内にない数値を表す必要があることです。その結果、たとえば、長さ 256 の文字列のインデックスの型は、すべての有効なインデックスがバイトであっても、少なくとも short である必要があります。同様に、ベクトルの終了位置への半開区間記述子には、ベクトルの格納に含まれないアドレスが含まれており、他のオブジェクトへの有効なポインターである可能性があります。たとえば、これは、保守的ガベージコレクションでは複雑になります。(少なくとも 1 つの保守的ガベージコレクターは、この問題を補うために過剰割り当てを行います。)私はどちらか一方を支持しません。どちらも有効であり、どちらにも利点と欠点があります。 --RiciLake

あなたの議論は成り立ちません。RiciLake。256 バイトの配列があり、「閉じた」表現を使用しています。この表現では、(n, m) は [n, n+1, n+2 ... m-1, m] を意味し、配列内の区間を表します。上で述べたように、ゼロ長の範囲の表現は (n, n-1) です。たとえば、[4, 3] です。では、ゼロから始まるゼロ長の範囲の表現は何でしょうか? (0, 256) には別の意味があります。したがって、配列インデックスに必要なビット数に関するあなたの議論は、区間の半開表現と閉表現のどちらにも同様に問題です。使用するビット数を選択できない Lua などの言語には関係ありません。 --KragenJavierSitaker?

與從零開始進行計算相同,我認為閉合區間比半開區間更直觀,至少在您不是在討論零長度區間的特殊情況時。我說「直觀」是指對至少沒有當過幾年程式設計師的人來說,這更自然。--PeterPrade

我沒有實際計算過,但我認為有絕大部分程式語言的計數都是從零開始的...由於我第一種學習的語言是 C,因此對我來說,從 1 開始算起很混淆,事實上,我用從 0 開始算起的陣列寫了一堆亂七八糟的 Lua 程式碼。--AdrianPerez

儘管從零開始計數有其優點,但我發現從 1 開始計數更自然,即使在寫程式時也是如此。對我來說,在 Lua 和 C 之間切換並不是個問題,因為過去我在 Visual Basic 和 C 之間也切換了很多次。--匿名

第一個是第 1 個,不是第 0 個。--Kazimir Majorinc

「我正在評估 Lua 以作為我應用程式中的嵌入式指令碼語言,到目前為止我所看到的一切都非常正面,直到我發現 Lua 是從索引 1 開始計算的。糟透了。糟透了。糟。糟糕到足以考慮把它全部丟出去。至於正當理由,即使不應該有任何理由:長度為 N 的陣列的索引是整數模 N 環的自然對應,有許多巧妙的特性。例如,當您想循環存取陣列時,只要進行 index = (index+1) %N 運算即可。從 1 開始的索引來做同樣的事情會很麻煩。此外,這會讓將 C 常式繫結到 Lua 變得很麻煩。」

index = index % N + 1 --Milano Carvalho

沒錯,突然之間我們多了一個錯誤和額外的任務,原本這些都不需要出現的。此外,程式設計師現在必須記住「索引是一個位置,會破壞模數的前提條件,還是實際的模數?」最後,這個的反向運算式是什麼?是:「modindex = index - 1 % N」?還是「modindex = index % N - 1」?這是個陷阱題:答案是「modindex = (index - 1) % N」。 --Andrew Lentvorski

我同意。Lua C 函式庫對 C 的介面使用對 C 來說不自然的慣例。例如,當將 Lua 表格分析成 C 陣列時,您必須記得使用 iterator+1 才能存取表格索引。--DanHollis?


對我個人而言,從 0 計數並非棘手的問題;從 1 計數只是 Lua 中資料型態稀少的其中一個症狀,絕非問題的全部。我的問題在於缺乏資料型態,包括陣列,無論是以 1 或 0 為基準都沒差。表格可能有一個密合的「陣列」部分,但我並不希望我的 33 字陣列佔用 64 字元的空間(必須是 2 的次方)。別讓我在開始提我甚至無法擁有一個位元組陣列,只能擁有龐大的雙精度浮點數(或雙精度,或 Lua 編譯確定的唯一(1)數值資料型態)的事實。是的,我知道 Lua 能輕鬆地將自身黏著於 C 中的真實陣列。但之後它實質上並不在 Lua 中,它變成一種次等的「使用者資料」型態,我無法真正地將它視為一個真正的清單。

Lua 5.1 提供 lua_createtable() API 呼叫,允許您明確指定表格的陣列大小。您也可以指定雜湊大小,但那部分總是受限於 2 的次方。如果您建立一個具有特定陣列大小的表格,只要您沒有強制該表格擴充,其陣列部分就會準確地為那個大小,所以在您預先知道表格大小時,這會非常順利。對 int 等小型原子物件進行陣列繫結,在 5.1 中也變得稍微容易一些,因為有可能覆寫 # 運算子,但要讓 userdata 真正像一個 Lua 表格運作,您需要修改 ipairs 的預設定義,並可能修改 unpack 的預設定義。我在 Wiki 的 GeneralizedPairsAndIpairs 中放置了一些前者的程式碼,以防任何人需要使用它。--RiciLake

一個很優秀的觀點,我也是為此而掙扎。將大型 C 結構化介面至 lua 中,特別是大型結構化的 C 陣列並不輕鬆。Lua 並未使這些映射變得直接明瞭。--DanHollis?


Lua 原始碼有一個常數 lua_Number 設定為將雙精度數值設為預設。同樣地,定義一個常數 lua_FirstIndex(例如)並將其設為 1 作為預設,以參考第一個索引,或許會很有趣。與陣列第一個索引(例如,ipairforeachi 等)相關的 Lua 的每個部分都應該使用這個常數。如果使用者想要將這個常數變更為 0 並重新編譯,他/她可以自行承擔失去相容性的風險,使用從 0 開始的 Lua 表格。相同的常數應該可以從 Lua 存取,以允許指令碼具備可攜性或與索引陣列的第一個值無關。--Salvador Espana


電腦科學中數字從何開始算起,是零還是從一,這個問題已經是老生常談了。我發現在艾傑‧迪克斯塔拉 (Edsger Dijkstra) 的文章「為什麼數字應該從零開始」(http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF) 中的論點相當有力,從此我也成為從 0 開始算起的堅定支持者。可惜的是 Lua 主張從 1 開始算起。這樣一來,表格/陣列建構就會變得有點不順手: {[0]=10, 20, 30} ,而表格函式庫函式的價值也會因此降低。--Ulrich Hoffmann <uho@xlerb.de>

的確,好文章。我特別喜歡開頭第一句話:「用於標示 2,3,...,12 [...] 等自然數的子序列。」現在,與「程式語言主要應清楚傳達意圖給讀者,其次才是傳達給電腦」這個標準結合來看,我們可以發現,即使對迪克斯特拉來說,最自然的標示方式就是包含式的... 得出自己的結論吧。


從一數起「比較直覺」,但從零數起演算法會好很多。程式語言是給人寫用來在電腦上執行的演算法,而不是供人類之間日常對話的語言。程式設計師都很聰明,他們自己想得出來。不要把他們當成是小孩子看。:) --DanHollis?


我贊成採用半開範圍而非封閉範圍,因此也贊成從 0 開始數起,而不從 1 開始。不僅可以將長度為零的範圍自然地表示成 [n,n),相鄰的範圍也能很好地加總 -- [a,b)+[b,c)=[a,c) -- 而不必過度地在兩端加倍。產生的範圍長度為 (b-a)+(c-b)=c-a - 長,其中任何一個或兩個組成都可以是長度為 0。另外,還能考慮 [m,n) 的「負範圍」,其中 m>n,而範圍加總運算依然有效,現在甚至可以從非零長度的範圍中得到長度為零的範圍。

現在,考慮數字 abx。一個正確的「xab 之間」(在於 min(a,b)<=x<max(a,b))的表達(半開範圍)是 (a<=x)=(x<b)。如果它是封閉範圍(...<=x<=...),我們就無法有這麼漂亮的表達。-- Boyko Bantchev


我個人對於從 1 開始數起,倒是沒有問題。原因之一,就是把 1 當成字串中的第一個字元,而 -1 當成最後一個字元,這樣子很好記。如果把第一個字元改成 0 的話,這個方法就不能用了。

作為一個指令碼語言,它的首要目標就是讓指令碼編寫者容易上手。一個有 5 個元素的陣列,其中最後一個元素的數字是 5,這樣的陣列肯定比最後一個元素是 4 的陣列,更容易向剛入門的指令碼編寫者解釋吧?

我在系統中介接了很多客戶端函式,好讓 Lua 可以呼叫這些函式。在很多情況下,從 0 開始或從 1 開始這個問題根本就無從適用。例如,很多函式都使用字串做為索引鍵(這樣一來問題就不存在了),不然就是根本沒有用到任何形式的陣列。

如果您希望 Lua 成為通用腳本語言,我絕對不建議使用編譯時間選項,以便基於零編寫的 Lua 腳本有一半可以執行,而基於 1 編寫的腳本也有一半可以執行。如果您這樣做,就會開啟噩夢的大門。我甚至看不出如果您想介接類似於 LuaSocketLuaCom 等函數,這會有什麼作用。這些函數的寫作會假設使用現有公約,也就是陣列從 1 開始,並且很多函數都提供針對 Windows 的預先編譯二進位檔案。如果您的系統是以零為基礎,這些函數可能完全無法執行,或者每個套件的作者都必須讓他們的程式碼因應各種不同的基礎而產生混亂,這肯定會讓變更基礎的任何優點都消失無蹤。-- NickGammon


再提一點,Lua 內部在很多地方都使用慣例,將 1 視為第一,-1 視為最後。例如:

double num = luaL_checknumber (L, 1); /* get first item on stack */

因此,向 C 介接 Lua 的程式設計師對此公約非常熟悉,您必須熟悉。如果將陣列改成從零開始,您也會跟著變更這個公約嗎?那您要如何從堆疊中取得最後一個元素(目前是 -1)?

上面有些文章並未明確提及是否也指的是字串。例如,字串中的第一個項目

c = string.sub ("ABC", 1) --> "A"

您是否也會把它改成零?如果是,您要如何取得最後一個項目?-- NickGammon

將 -1 用作最後一個元素的別名與半開區間完全一致(例如從零開始算起)。請看 Python。事實上,與封閉區間相比,它更為一致。想像一下清單會環繞,您可以從頭到尾,再從尾到頭(「捷徑」)移動。位置 0(清單開頭)的左邊一個位置是 -1(清單結尾)。換句話說,您只要從您的位置減去 1 就可以往左移動,這很自然。如果您清單從 1 開始,則會在清單的開頭和結尾產生兩個奇怪的位置差。當您要往左移動時,必須從您的位置減去一個,除非您處於位置 1,這時您必須減去 2。

那麼您是否也要提議在 greatest_index + 1 環繞到第一個元素?如果不是,當您從最後一個元素(以正向索引指定)移動到第一個元素時,仍然會有這些「奇怪」的跳躍,所以此論點毫無意義。

不,如果您希望索引環繞,請使用 i modulo n。這種等式的簡潔性是使用偏移索引的優點之一。

對,這點沒錯。但由於「事情已經發生」,我建議,如果應用程式需要基於數學或其他原因從 0 開始計算,就簡單定義自己的 foreachi 函數,以變通目前行為。畢竟,目前沒有任何規定禁止你在資料表的 0 位置輸入元素。

如果你要讓資料表建構從 0 開始做這件事。

t = { [0] = "a", "b", "c" }  -- a is in position 0, b is in 1 and so on

-- NickGammon

很不幸的是 #t 計算出來是 2。大多數問題來自於將數字與序數混淆。當索引是偏移量時,0 是陣列中第一個項目的偏移量。如果我們在口語中使用數字時更謹慎地保留型態資訊,這樣爭議會比較少。在數學中,將非負整數 n 視為從 0 到 n-1 的數字集合,會比將其視為從 1 到 n 的數字集合得到更簡潔的公式。-- GavinWraith

儘管在數學中,矩陣和向量通常是從 1 開始編號的[1][2][3]。類似地,在 LuaMatrix 中,第一個元素會被參照為 mtx[1][1]。序列會比較多變[4]。關於數學軟體,Mathcad 預設是從 0 開始編號(但可以更改),而 Matlab、Maple 和 Mathematica 則是從 1 開始編號。--DavidManura


然而,#t(或 table.getn)的定義並非回傳資料表中的元素數量。例如:

t = { foo = 1, bar = 2 } ; print (table.getn (t))  --> 0

從 Lua 手冊

表的長度定義為一個整數索引 n,其中 t[n] 非 nil,而 t[n+1] 為 nil;

我的範例與定義是一致的。#t 回傳最後一個項目的索引。

-- NickGammon

這說法不對。t[0] 為 nil。根據該定義,這資料表根本沒有定義明確的長度。參閱上述。--f


Visual Basic 和特別是 JavaScript? 都是兩個與 Lua 類似的語言。如果讓這些語言轉來的非技術使用者比較好入門,會是一件很好的事。在 JavaScript? 中,陣列從 0 開始編號。在 Visual Basic 中,陣列預設從 0 開始編號。(變更預設設定非常不建議,而且也不受 VB.Net 等現代實作支援。)


我在找 Perl 是從 0 還是 1 開始編號(看來像是 0),結果在我的 Perl 手冊中找到這顆寶石

陣列下標 n(其中 n 是任何非負整數)總是表示陣列元素 n+1。

很顯然,我們無法就此達成共識,不過你覺得這樣不會造成 一點 混淆嗎?「下標 n…表示元素 n+1?」至少在 Lua 中,下標 n 表示元素 n。

-- NickGammon

如果您的底數為 0,而您將索引視為一個位置,才會造成混淆。如果您的底數為 0,那麼最好將索引視為從清單一開始的偏移值,而不是一個位置。這與 Gavin 剛剛提出的觀點相同。一般而言,偏移值在程式設計中比位置更有用。


「自然數字集合」 在美國是指大於或等於零的整數集合,而在蘇聯則是特指大於零的整數集合。這就像縮排一樣。

個人淺見是,從 1 開始算很好。第一個元素是 1,最後一個元素是 -1。這樣就不必記住「這不是數學,這不是自然的事,習慣它」這樣的說法,就好像你在處理 Python 中的索引時一樣。

-- muntyan

而 Lua 讓您可以在整數中儲存 0 -- 所以它會帶您到哪個元素?


Lua 的關鍵優勢在於,它是所有腳本語言中最易於嵌入的 -- 它並非用於一般程式設計任務的最佳頂層腳本語言(Python 和 Perl 更好)。身為一個嵌入式腳本語言,它會嵌入在編譯語言中。其中絕大多數都使用以 0 為基礎的索引,所以大多數新使用者都會有這樣的參考架構。VB 曾經有過這樣的爭論(以及動態的選擇選項),而據我所見,人們都投給了以 0 為基礎的索引。所以讓我們就此定案,結束這個話題。-- GRB

的確如此 -- JeanClaudeWippler


請不要未署名就以第一人稱寫作。

所以,所有那些數論都付諸東流?天啊,你在出生的那一刻就變成了一歲小孩,而克拉克先生對於 2001 年的說法是錯的。-0 的模數真有幫助。抱歉,但我認為整個概念都需要重新思考、修改和修正。不,從一開始並不像某個人寫的那樣自然,因為零是被直覺假設的;因此;無需說明。但老舊的電腦並沒有假設。純粹是我的想法 ---trav
在 BASIC 中,您可以從任何數字開始,例如
 DIM arrayname(5 to 18)
在 Forth 中,您也可以從任何數字開始,例如
 HERE 14 ALLOT 5 - CONSTANT arrayname

非程式設計師實際上已經在無意識的情況下從 0 開始計算。在計算時,猜猜看人們以什麼作為十位數、百位數、千位數等的第一個數字?提示:它不是 1。因此,使用 1 作為第一個單位極為不一致。這樣的矛盾導致從 19... 開始的年份被稱為 20 世紀:我們只是錯過了 0 世紀。這種矛盾也導致許多人認為 21 世紀始於 2000 年。這麼假設的話,他們只是更方便地從...零開始計算。另一個例子:白天/下午的第一個小時使用哪個數字?提示:它也不是 1。從一開始計算的另一個矛盾:我們使用十個數字,現在請指出最後一個數字?參閱 Stefan Ram 的文章「數字從零開始」,瞭解更多非呆板、非數學的範例。

看起來從一數起是來自一元制系統的古老遺產。我們應該在發明零的時候擺脫這個遺產,但很遺憾,我們沒有做到。


從 1 開始計數是我不用 Lua 的頭號理由。除此之外,它是一款非常好的語言,但使用半開範圍編寫程式容易得多。當人們告訴我「從一數起更自然」時,我不同意。這只是過去的一種古老殘留。如果你真的仔細想想,從 0 開始計數更有道理。

--Zifre


Zifre,你的意思是「從 1 開始計數是我不用 Lua 的第 *零* 個原因」嗎?畢竟,你聲稱從 0 開始計數對你來說更有意義。

讓我們打個賭。我們將去公園並與隨機的人交談。我們將向他們展示一行中的三塊石頭,並請他們大聲數出石頭。如果有人說「零、一、二」,那麼你贏了。如果每個人都說「一、二、三」,那麼我贏了。我想我總是會贏得這個賭注。沒有人從零開始計數,因為這沒有道理。當以 0 訪問陣列的第一個元素時,該數字表示偏移量,而不是索引。問題不在於計數,而在於陣列應使用偏移量還是索引。

當然,使用偏移量而不是索引確實有一些優點。但很難與此爭論:如果陣列使用索引,那麼第「n」個元素則以數字「n」訪問。你需要第四個元素嗎?然後使用 4。想要第十個嗎?然後使用 10。這很有道理,並有其自己的一組好屬性。不幸的是,許多程式設計師對這個問題持封閉態度,並以某種方式說服自己相信荒謬的說法,例如「從 0 開始計數有更多的意義。」(然後,在他們自己的文章中,說明他們實際上從一個開始計數,就像這個星球上的其他人一樣。)

讓我們打第二個賭。在請人們數石頭後,我們會說:「請指出一塊石頭」。如果有人指著中間的石頭,那麼你贏得賭注。否則,我贏了。同樣,我看不出我如何才能輸掉這個賭注。-- 匿名

Zifre 與匿名者對此頁面中的討論毫無幫助。你閱讀了第一段嗎?問題不在於從一或零開始計數,而在於如何指明序列中的元素。使用偏移量會導致更少的邊界情況,從而簡化代碼和 API。這與公園裡的人如何計數無關。--JohnBelmonte

考量到 Lua 目前主要用於業餘腳本撰寫,例如在程式設計技能不足,但仍能透過自訂功能的場合,「公園裡的人們」數量應相當有意義。這並非意味著需要為萬能消費者而簡化所有事物,尤其是程式設計師執行業務所需的工具,而且因為偏移與序數的爭論基本上是概念問題,與使用者對程式碼含義的內部理解有關,因此為何要責怪 Lua 迎合公園裡的人,而在石頭陣列中,第一個石頭是第 1 個石頭?對不熟悉這個概念的人來說,偏移有點難以掌握。

好吧,使用電腦來計算這 3 個石頭。你會得到類似這樣:00、01、10。你錯失整體畫面:你編寫程式不是為了人們,而是為了電腦。了解電腦的內部結構通常會有幫助。你無法讓電腦完全理解你(或者也許你可以,但如果是這樣,你應該得到諾貝爾獎)。不過,你可以完全理解電腦 :) -- shiretu


我針對此主題開啟新頁面,試圖總結此問題的幾個面向:[IndexIntervalFormatIssue]。[DeniSpir]
DeniSpir,該頁面存在巨大誤解。而在「程式設計師也一樣」區段中,半開式區間被描述為 [n,n],而應該為 [n,n)。

此外,這項說明 [a,b]+[b,c] 應為 [a,b]+[b+1,c] 的說法完全錯誤,因為原始主張需要半開式區間,而情況應為:[a,b)+[b,c)

因此,抗議完全錯誤,因為 [a,b)+[b,c) 並未包含 b 兩次。我將修正該部分,並刪除關於 [a,b]+[b+1,c] 的抱怨,因為這沒有意義。-- Tim


JohnBelmonte,使用偏移不會讓程式碼 API 更簡單。同意會減少臨界狀況,但別試著說服別人喜歡/不喜歡特定程式設計模式。此處重要的是 Lua 應支援多樣性。我本人難以設計以 1 為基礎的程式碼,而且比所謂的「臨界狀況」更容易產生錯誤。換句話說,我下意識地知道如何透過我使用其他 10001 種程式語言 發展的技能來避免臨界狀況,而不是採用你的「安全」方法來發展「更簡單的程式碼」。實際上,這只是喜好問題。你不能以「你這樣編寫程式很愚蠢,你那樣編寫程式很聰明」將人們歸類。儘管我討厭 Lua 的這個部分,它仍得到我的喜愛,因為還有許多其他正面的面向。但我仍遺漏了一個……能夠在編譯時指定索引基準……-- shiretu
這是錯誤的。原因如下:艾茲格·迪科斯徹論述從 0 開始陣列索引(pdf,1982 年)[5]。-- 匿名者


針對 Lua 5.3.4 原始碼散佈,我已嘗試加上修補程式,包含全部官方函式庫:lua-base-0。開放原始碼[6]。如果你有興趣,請去查看(並移植至最新的 lua,撰寫最佳的測試案例),看看我是否遺漏了什麼。

一些例外

string.gmatch 中, "%0" 是針對整個匹配,而 "%1%2"... 則針對第一、二次擷取。保持不變。

args 表的訂閱定義保持不變,但請注意,長度運算子現在將傳回一個大一的值。

math.random 是個不確定的點。目前狀況最適合實用性:提供一個引數時傳回 [0, n);提供兩個引數時傳回 [a, b]

數值 for 迴圈是另一個。目前狀況是:for i=0,3 為 {0,1,2};for i=3,0,-1 為 {3,2,1}。

我也考慮讓後者變成 {2,1,0},因為它就像反向迭代那樣運作。但這在定義上看起來很醜,而且也可能會發生一些浮點數的問題。(但說真的,有人在實際運用中使用過嗎?)你怎麼想?

table.remove 的邊界案例,其中 i==#t+1 (i==#t 十進位制) 已移除。我不明白這一點。現在會發生錯誤。

其餘應該是微不足道的,包括一些負數索引作為反向支援的情況,在這些情況下,它將大多數像在 python 中那樣運作。

我反對採用十進位制表的原因還有另一點:從/轉換成 JSON(廣泛使用的資料交換格式)時會造成問題與混淆。

--farter

另請參閱


最近的變更 · 偏好設定
編輯 · 記錄
上次編輯於 2018 年 3 月 19 日格林威治標準時間上午 2:54 (差異)