2010-07-11 55 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