Dofile 命名空間提案

lua-users home
wiki

我發現 dofile() 在 global 命名空間中而不是在呼叫者的命名空間中執行這一點很不直觀。

對於一個真實的例子,我有一個內嵌 Lua 的應用程式,並為使用者建立一個命名空間用來執行程式。使用者可能會想要載入和執行其他程式碼,但因為 dofile 會對 global 命名空間進行處理並將結果放入其中,所以 dofile 實際上不能在這裡為使用者工作,而呼叫程式可能甚至無法看到這些結果。使用者可能甚至不會知道自己是在一個本機命名空間中進行操作(有人可能會說,他也不應該知道)。因此,我的應用程式為使用者建立一個新的函式 myapp.import,定義如下

function myapp.import(name)
  local f,e = loadfile(name)
  if not f then error(e, 2) end
  setfenv(f, getfenv(2))
  return f()
end

但是一個這樣的使用者剛剛回報說 dofile 沒有執行他們想要的操作(實際上可能是第二個使用者),而我回應說他們應該改用 myapp.import,所以顯然有一些混淆,而很多人可能不是很熟悉 Lua 命名空間,所以不明白為什麼。不過,我還是很好奇為什麼 dofile 在一開始沒有按照我想要的方式執行,以避免這個問題。

RiciLake 同意,並指出目前的執行有點不合時宜(即其語義是指舊版的 Lua)。

為了減少混淆,我有個選項是將 dofile 重新定義如下

function dofile() error("Use myapp.import(name) instead of dofile(name)", 2)

或者,也許混淆的情況會更少,但會對內建語義做出一個小小的變更,我可以在本地命名空間內重新定義 dofile 如下。我試著避免變更語義,但也許這是可以接受的,因為在使用者擁有完美的本地命名空間時,他們甚至不應該使用修改 global 命名空間的原始語義。

dofile = myapp.import

或者,這個變更可以在 Lua 中進行,但這當然有可能(是否會)破壞現有的程式碼。另一種選項可能是允許指定命名空間的額外參數,例如 dofile("hello.lua", "caller"),但這有點違反默認行為應該滿足最常見的情況(即呼叫者不是 global)的經驗法則。

提案詳細資訊


最新變更 · 偏好設定
編輯 · 歷程
最後編輯時間 2006 年 11 月 28 日,凌晨 3:56 (GMT)(diff)