2012-08-03 55 views
0

我一直在使用googling這個問題到目前爲止無濟於事,所以我想知道是否有人可能知道答案 - 當你在lua中索引一個零值時,腳本會產生一個錯誤 - 試圖索引'variableName ' - 一個零值 - 是否有可能取而代之以可能是一個元方法,做一些處理而不是出錯?例如,如果未定義變量'num',並且您說'num = 2',則可以設置__newindex metamethod來執行一些處理,並且在堆棧中同時具有變量名'num'和值'2'但是如果你說'num [2] = 3'並且'num'沒有被定義,你就會出錯 - 而不是像__newindex那樣,我想捕獲那個事件並且可以訪問nil變量的名字 - 'num',指數 - 2,和設定值 - 3.任何幫助,將不勝感激。lua索引無值

+0

這個問題並不完全清楚。你是說num是一個表變量?或者num只是腳本的局部變量? – 2012-08-03 15:11:28

+0

它不是,'num'還沒有被定義 - 但你嘗試索引它反正而不是提出一個錯誤我想要未定義的變量名稱'num',索引和值,所以我可以做一些處理,就像使用__newindex – user1452276 2012-08-03 15:20:53

回答

0

您可以覆蓋全局表上的__newindex metamethod。

function OnNewIndex(tbl, key, value) 
    if tbl[key] == nil then 
     print(tostring(key).. " doesn't exist.") 
    end 
end 

setmetatable(_G, { __newindex = OnNewIndex }) 

num = 15 

但是,默認情況下,我不認爲lua有這種行爲。只是在做類似:

num = 15 

應該只是聲明變量「NUM」作爲一個全球性的和值15分配給它。你是否將lua作爲一些嚴格檢查這個框架的框架的一部分?

編輯:一個簡單的方法來「抓」這個錯誤不讓它泡到面將包裹在這樣的PCALL分配...

pcall(function() num[2] = 15 end) 
如果打印此

,你」將獲得的輸出:

false test2.lua:18: attempt to index global 'num' (a nil value) 

這至少給你發生了什麼的指示,如果你命名的功能,我想你可能會嘗試恢復。

function TrySetValue() 
    num[2] = 15 
end 

local result, msg = pcall(TrySetValue) 
if (not result) then 
    num = {} 
end 

result, msg = pcall(TrySetValue) 
print(result, msg) 
print(num[2]) 

看起來像是一個可怕的很多工作,當你可能只是預先修復代碼。

+0

我想我不夠清楚:如果我重寫__newindex metamethod語句如:num = 15,其中num是一個未聲明的變量將被捕獲,你可以做一些事情與字符串'num'和值爲15.但是,如下所示的語句:num [2] = 15,其中num未聲明將導致錯誤,無論我們是否覆蓋__newindex。錯誤是:'嘗試索引'num' - 一個零值' – user1452276 2012-08-03 15:55:04

+0

是的,我不認爲有一種方法可以讓你'捕捉'你想要捕捉的東西,而不用在pcall中包裝任務)並嘗試從錯誤中恢復。想想你在做什麼。你正試圖爲_G表捕獲__index,創建一個新表,捕獲__index,併爲THAT賦值。我不確定你會怎麼做,當你真的應該明確創建數字之前,試圖索引它。這是非常標準的編程原則。 – 2012-08-03 17:26:11

1

首先,如果您聲明您正在嘗試解決的問題,則更容易提供幫助。你是否試圖阻止未初始化的全局變量被使用?你可以用metatable做到這一點。你是否試圖確保腳本錯誤永遠不會滲透到你的應用程序?你可以用pcall來做到這一點。你真的只是試圖抓住這個全球性的nil的具體用法,並以某種方式從中恢復嗎?您提供的背景越多,其他人就越容易找到您可能沒有想到的解決方案。

至於你描述的情況,你想趕上的地方num[index]其中numnil,你不能直接檢測到。

有兩個部分是:

  1. 當從當前環境表(又名_ENV或_G)讀取num當前值
  2. 當您試圖索引值。

你無法檢測#2,因爲nil不是表格,所以你不能給它一個metatable。

但是,你可以檢測#1。根據您的需求,您可以使用#1返回一個代理對象,這樣將使您檢測#2,然而,這將意味着沒有全球性的將永遠是nil,所以像這種邏輯是行不通的:

--- initialize globalFoo if it doesn't exists 
if not globalFoo then 
    globalFoo = CreateGlobalFoo() 
    .... 

當然,你總是可以做類似名稱的代理對象NIL,所以你可以寫:

local nil_proxy_mt = { 
    __index = function(t,k) print('Attempted to index nil!') end, 
    __newindex = function(t,k,v) print('Attempted to index nil!') end, 
} 

local NIL = setmetatable({}, nil_proxy_mt) 

setmetatable (_G, { __index = function(t,k) return NIL end }) 
:一個代理對象,就像是的

if globalFoo == NIL then -- globalFoo is not initilalize 
    globalFoo = CreateGlobalFoo() 

有了這個地方,如果你嘗試以下任一:

foo = num[2] 
num[2] = 15 

你會得到「!試圖索引零」程序繼續運行。

+0

當我週一回來併發回任何其他評論時,我會放棄這一點。 – user1452276 2012-08-03 17:49:01

相關問題