3

これは機能します...

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 スタックにプッシュされた引数を取得しますlua_toboolean

では、なぜ最初は機能し、2 番目と 3 番目はエラーを返すのでしょうか?

編集:

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 を返すことです。したがって、nil が表示されると、ブール値が渡されなかったことを返します。ブール値リテラルのエラー チェックを削除したのは、(私を含む) 人々は通常、ブール値リテラルではない引数がブール値として正しく扱われることに依存しているためです。

4

3 に答える 3

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;
}
于 2010-07-12T00:24:26.820 に答える
1

そのand値が true でないと見なされる場合、演算子は最初の引数を返し、それ以外の場合は 2 番目の引数を返します。

演算子は、or真と見なされる場合は最初の引数を返し、それ以外の場合は 2 番目の引数を返します。

したがって、A or (B and C)理論的には次のいずれかを返すことができます。

  • AAが true と見なされる場合
  • BifBは false と見なされる値であり、false とA見なされます
  • C上記のいずれでもない場合

AB、およびは、実際のブール値である必要はなく、ブール値として解釈Cできるもののみであることに注意してください。は偽の値と見なされるため、2 番目のケースが発生している可能性があり、渡される引数はorではなく です。nilSetNoClipniltruefalse

これを修正する 1 つのオプションは、単にオブジェクトを使用する代わりに、明示的に nil と比較することです。

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

~=演算子はブール値を返すことが保証されているためです。

于 2010-07-11T17:54:51.067 に答える
0

SetNoClip の内部で何が行われているかによって異なります (つまり、これが一般的に問題を引き起こすとは限りません)。ただし、問題は、またはに評価するのではなく、どちらかの側で値andを返すことであると確信しています。言い換えると、ortruefalse

foo and bar

がまたはのfoo場合fooはを返し、そうでない場合は を返します。nilfalsebar

あなたの場合、元のコードはSetNoClip にtrueorを渡しますが、他の例では、またはブール値を SetNoClip に渡します。SetNoClip が文字列を詰まらせている可能性があります。false"water"

于 2010-07-11T17:49:00.730 に答える