預設為區域變數

lua-users home
wiki

對於 Lua 的範圍限制規則經常在郵件清單中引發相關議題。其設計背後的論證將在此發揮效用。

Lua 的宣告被描述為「預設為全域變數」,與「預設為區域變數」(Python 和 Ruby)形成對比。另一種選擇是讓宣告皆「無預設值」(亦即,要求同時明確宣告區域變數和全域變數)。以下是這方面的一些見解精闢的引言:

[4]「預設為區域變數是錯誤的。預設為全域變數可能也錯,[但]解決方案並非預設為區域變數。」(Roberto)

[5]「我真不懂為什麼有人希望變數在預設情況下成為*任何*一種型態,例如在自動宣告中。這所做的只是偶爾為你節省幾個按鍵,同時卻也開啟無窮盡的樂趣,試著找出愚蠢、難以發現的拼寫錯誤和名稱混淆錯誤。 (將指派誤寫成宣告,反之亦然。)」(David Olofson)

[6]「問題點在於,若無[明確宣告的]區域變數,你便無法判斷變數的區域限制為何。」(RiciLake

[7] 「預設為區域變數」與其字面上的意思格格不入....適當的字面含義範圍限制實際上要求你能夠在變更繫結(指派)與建立新繫結(宣告)之間做出選擇。唉,「預設為區域變數」的規則將兩者混為一談,並使指派同時執行兩項動作。」(MikePall

[8] 「在我看來,預設為區域變數的主要論點是為了防止意外存取全域環境,其次則是為了讓區域變數宣告成為可選動作,如此一來便能減少打字量。我個人認為非強制性宣告是一個壞主意,對區域變數和全域變數來說都是。為了強制明確宣告全域變數,並防止意外存取全域環境,我使用 require 'strict'。或許有可能在編譯時執行等同(或更好的)動作。但我的重點是,或許我們應該問問自己,是否真的需要/想要預設為區域變數,抑或只是明確的全域變數宣告。」(Mark Meijer)

[Python PEP 3104] -- Python 對「預設為區域變數」的修正,其與ReubenThomas的提案(見下方)相同(除了關鍵字選擇之外)。

[1]「[目前的區域變數範圍限制規則]是 Ruby 中最大的單項設計缺陷。」(Ruby 設計師 Yukihiro Matsumoto)(留言:[9][10][7]

[2] -- 針對各種範圍限制規則的討論,以及程式語言 Converge 為何選擇「預設為區域變數」,並搭配「nonlocal」(類似 PEP 3104)關鍵字的原因。 (Converge 設計師 Laurence Tratt)

[3] 「我厭惡 lexical 隱式宣告,因為它往往會抵消其主要用途,也就是偵測拼寫錯誤…宣告應該是宣告的樣子…我相信使用 my 宣告就是符合赫夫曼編碼。」(Larry Wall,Perl 設計者)

另請參閱


先前提案

以下是另一項「預設為區域」提案。我個人認為它更簡單、更不突兀,卻能帶來比其他提案更好的成果。(-- ReubenThomas

更動內容為

1. 新增一個新的關鍵字「outer」,運作方式與「local」類似,但它是宣告給定名稱,以指向同一 enclose 函式中同名的最內層變數,如果沒有,則指向同名的全域變數(即使目前沒有)。

2. 函式中變數的第一次指定會隱式視為「local」宣告,除非它已在該函式中明確或隱式宣告。函式外的指定運作方式維持現狀,表格元素的指定也一樣。

備註

a. 保留使用組態檔風格進行全域指定的能力,代價是在函式內部進行指定的方式與外部不同。實務上這不應該是問題,因為少數 Lua 腳本包含頂層複雜的程式碼。如果您需要頂層程式碼中的區域變數,您必須照現有方式宣告它們。

b. 唯一的語法變更部分在於新增「outer」(類似於其他建議的解決方案,使用「nonlocal」、「extern」或「static」關鍵字,宣告這些未在詞法範圍或任何封閉區域中定義的符號使用方式)。

c. 唯一的語義變更部分在於函式內指定的意思。

d. 指定僅讓變數在執行時變為區域,而非函式全部。這符合最少驚訝原則:您不需要閱讀整個函式,就能找出給定變數是否為區域(編譯器也是如此,因此實作很簡單)。


RecentChanges · 喜好設定
編輯 · 歷史記錄
最後編輯時間為格林威治時間 2020 年 6 月 2 日下午 3:14 (差異)