2010-07-11 31 views
3

這工作...Lua的錯誤沒有通過布爾

if (tileType == "water" or 
    (otherObj and otherObj:GetType() == "IceBlock")) then 
    self:SetNoClip(true) 
else 
    self:SetNoClip(false) 
end 

- 這些不...

self:SetNoClip(tileType == "water" or 
    (otherObj and otherObj:GetType() == "IceBlock")) 

//---------------------------------------------------------- 

local noClip = (tileType == "water" or 
    (otherObj and otherObj:GetType == "IceBlock")) 
self:SetNoClip(noClip) 

otherObj測試只是計算結果爲otherObj是否nil與否。給出的變量在前一行中檢索。我得到了應用程序運行時的錯誤是:

unprotected error to call in Lua API(script path...: Did not pass boolean to SetNoClip).

SetNoClip是,抓住論證通過lua_toboolean壓入堆棧LUA應用程序的功能。

那麼爲什麼第一個工作和第二個和第三個返回錯誤?

編輯:

SetNoClip 這個定義。

int GameObject::LuaSetNoClip(lua_State *L) { 
    if (!lua_isboolean(L, -1)) { 
    LogLuaErr("Did not pass boolean to SetNoClip for GameObject: " + m_type); 
    return luaL_error(L, "Did not pass boolean to SetNoClip"); 
    } 
    m_noClip = lua_toboolean(L, -1); 
    return 0; 
} 

的問題是,lua_isboolean沒有做任何隱式類型轉換(但lua_toboolean那樣),將只用於文字布爾值返回true。所以如果它看到零,它會返回一個布爾值不被傳遞。我只是刪除了布爾文字的錯誤檢查,因爲人們(包括我)通常依賴於非布爾文字的參數被正確對待爲布爾值。

+1

FWIW,錯誤消息不只是胡言亂語。無論何時遇到錯誤,發佈消息總是有幫助的。通常他們會告訴你究竟在哪裏以及是什麼問題。我們很樂意幫助他們解決問題,以便下次可以利用他們。 – Cogwheel 2010-07-11 17:50:45

+0

我沒有發佈它。這不是胡言亂語。問題是什麼非常清楚。沒有將布爾值傳遞給SetNoClip。 – random 2010-07-11 18:04:03

+0

哦,對不起,我錯過了它<需要更多的咖啡因(對我的評論投票的人也是如此:P)。我讓它脫穎而出... – Cogwheel 2010-07-11 18:13:12

回答

1

and運算符返回它的第一個參數,如果該值被認爲是非真的,則返回它的第一個參數,否則返回第二個參數。

or運算符返回它的第一個參數,如果它被認爲是真的,則返回它的第一個參數,否則返回第二個參數。

因此,A or (B and C)理論上可以返回下列任一:

  • A如果A是考慮真值
  • B如果B是一個值認爲是假和A被認爲是假
  • C如果以上都不是這種情況

請注意,ABC不需要是實際的布爾值 - 只有可以是的東西纔會將解釋爲布爾值。由於nil被視爲虛假值,所以第二種情況可能會發生在您身上,並且傳遞給SetNoClip的參數是nil而不是truefalse。解決這個問題

一種選擇是明確與零比較,而不是隻使用對象,:

(otherObj ~= nil and otherObj:GetType() == "IceBlock") 

因爲~=操作是保證返回一個布爾值。

+0

謝謝,正是我需要知道的。然而,這並沒有解釋,但它仍然評估爲布爾在if條件。如果語句做了隱式類型轉換,而參數傳遞則不做(即如果(nil)將nil轉換爲false,但SetNoClip(nil)不轉換)。 – random 2010-07-11 18:08:32

+0

因爲這是'if'的設計方式。當我們說「被認爲是正確的」和「被認爲是錯誤的」時,「如果」是正在考慮的事情之一。除「false」和「nil」以外,所有值均被視爲「真」。 – Cogwheel 2010-07-11 18:10:34

+0

是的,但爲什麼不會應用於傳遞函數參數呢?如果函數需要一個布爾值,並且接收到nil,你會認爲它會將它轉換爲false,就像條件語句設計的那樣。是否有一個原因? – random 2010-07-11 18:16:56

0

這取決於SetNoClip內部發生的情況(即,這通常不一定會導致問題)。不過,我很確定問題是andor返回任何一方的值,而不是評估爲truefalse。換句話說,

foo and bar 

將返回foo如果foo或者是nilfalse,否則將返回bar

在你的情況下,原始代碼通過truefalse在你的其他例子SetNoClip而無論是通過"water",或者一個布爾值,SetNoClip。 SetNoClip可能會阻塞字符串。

1

正如您所看到的,任何對象都可以在Lua中進行布爾型解釋。因此,如果您期望只傳遞一個布爾對象,那麼您實現LuaSetNoClip 並不符合精神& Lua的練習。您應該直接使用lua_toboolean

我認爲唯一參數,你可以合理做的是luaL_checkany

int GameObject::LuaSetNoClip(lua_State *L) { 
    luaL_checkany(L, 1); 
    m_noClip = lua_toboolean(L, 1); 
    return 0; 
} 
+0

是的,這幾乎完全是如何改變功能。注意編輯中的部分說'有'這個定義。 – random 2010-07-12 02:58:32