2013-08-29 21 views
7

一部のLua関数は、関数が何らかのタスクを実行できなかったことをユーザーに知らせるためにnilを返します(例えば、tonumber()string.find())。 nilをreturnig Cで CのLua関数から 'nil'を返す0の値を返します。

は、次のように行われている:それは代わりに、次の操作を行うために大丈夫だ場合

int some_function(lua_State* L) { 
    ... 
    if (some condition) { 
     lua_pushnil(L); 
     return 1; 
    } 
    ... 
} 

しかし、私は疑問に思う:

int some_function(lua_State* L) { 
    ... 
    if (some condition) { 
     return 0; 
    } 
    ... 
} 

それは短いです。私はそれを試して、それは動作するようだが、私はそれが設計であるかどうかわからない。私はルアのソースコードを調べましたが、このreturn 0パターンが表示されないので、これを行うのが正当かどうか疑問です。

nilを返す方法は2通りありますか?

(ところで、私はそれを言及しないでください(つまり、lua_error()である)すべての例外を経由してのエラーをシグナルについて知っている。)

UPDATE:

私は今、微妙な違いがあることを見ます2つの方法の間:print((function() end)())は何も印刷しませんが、print((function() return nil end)())は「nil」を印刷します。これがどれほど重要かわかりません。

+0

"私はLuaのソースコードを調べましたが、このリターン0のパターンは表示されません。値を返さないすべてのLuaライブラリ関数(print、table.insertなど)は、C実装で0を返します。 – Mud

+0

@Mud: 'print()'と 'table.insert()'の例は何も返されないので、関係しません。私は通常、 'tonumber()'のような値を返す関数について話しています。もしそれらのソースを調べると 'lua_pushnil(L); 1を返します。 –

答えて

12

Luaの関数はnilを返すことがありますが、ほとんどの場合、同じ結果が得られますが、この動作は全く同じではありません。

local function PrintNRetVals(...) 
    local nargs = select('#', ...) 
    print("Number of values returned: " .. nargs) 
end 

local function ReturningSomething() 
    return "hello" 
end 

local function ReturningNil() 
    return nil 
end 

local function ReturningNothing() 
    return 
end 


PrintNRetVals(ReturningSomething()) --> 1 
PrintNRetVals(ReturningNil())   --> 1 
PrintNRetVals(ReturningNothing())  --> 0 

私は行動があなたが変数に結果を代入しようとするとすぐに理由はほぼ同等であることを特徴とする。

次のLuaスクリプトは、多くのリターンは、関数が返す値どのように検出する方法を示しています関数はその変数が両方の場合でnilを取得するので、後続のコードはその違いを伝えることができません。しかし、私が上に示したように、あなたが本当に必要であれば、違いを検出することができます。

+0

しかし、 'tostring(ReturnNothing())'や 'type(ReturnNothing())'を使用するとエラーが発生しますが、ブール値コンテキストで使用されている場合はfalseとみなされます。 –

+0

@XavierCombelle私が私の答えで指摘したように、あなたが本当に必要な場合は、*違いを伝えることができます。これらの2つのLua組み込み関数はまさにそれを行います。それらは2つのケースを区別します(おそらく、そのコンテキストでは 'nil'値ではなく欠損値がプログラミングエラーで意図的ではないためです)。 –

+0

私はこれらの行に沿ってコードを持っていました 'ReturnNothing()then print(tostring(ReturnNothing()))end'これはかなり長い時間(私のpythonの背景から)、次の潜在的な例外の理由' bad argument #1 to 'tostring'(value expected).'私が言いたいのは、どちらの場合でも、ない場合でもプログラミングエラーであるということです。 –

5

はい、これは完全に有効です。あなたが1つまたは10を取得するかどうかに関わらず、より多くの戻り値を要求/割り当てしようとすると、未定義の値(つまり返されない値)に対してはnilが返されます。

function test1() 
    return 5 
end 

local a, b = test1() 
-- a = 5, b = nil 

function test2() 
    return 1, 2 
end 

local c, d, e = test2() 
-- c = 1, d = 2, e = nil 

function test3() 
end 

local f, g = test3() 
-- f = nil, g = nil 

Luaのソースでは、特殊なケースではないため、おそらく見つけられません。戻り値を扱うのはLuaの一般的な方法です。

アップデート:

戻り値を印刷しようとしたとき、あなたが気づいた違いは、これは単なる代入ではないという事実です。もちろん、nilを返すことと、何も返すこととの間には若干の違いがあります。それを区別することは可能です。最後に、関数の振る舞いを適切に文書化する、つまり何が起こるべきかをユーザーに伝えるだけで十分です。たとえば、nilを返すか(代入でnilを返す)エラー状態を表す可能性がありますが、エラーがあった場合は何も返しません。値が無効であると思われる場合はnilを返します。 )。

+0

ありがとうございます。私は答えを編集して、何も返さないものと返すものとの間の微妙な違いについて教えてくれました。しかし、私はルアの初心者ですので、私は自分がこれが重要かどうかを判断できません。私はこの行動の理由を知っている(私はPiLの本を読んでいる)。私はちょうどなぜ、例えば 'tonumber()'(lbaselib.c内)のソースで 'nil'を返しているのかを疑問に思います。 –

+0

あなたの追加されたアップデートのために:それは本質的に解釈するまでです。もちろん、単一の値を返さず、1つの値を返すことには 'nil'という違いがあります。代入では違いはありませんが、戻り値をどのように使用しているかによって実際に差異があることに気付くことができます。 – Mario

2

(これが答え、主題についてちょうど意見ではありません)

私のためとして、nilno value間のこの人工的な違いは一貫性がなく、むしろ迷惑です。

local function f1() return nil end 
local function f0() end 

local v1 = f1()  -- OK, assigns nil 
print(type(f1())) -- OK, prints 'nil' 

local v0 = f0()  -- OK, assigns nil 
print(type(f0())) -- Why the hack it raises an error? 

IMHOでは、関数のパラメータ渡しは、代入文の意味に完全に準拠している必要があります。

+0

このような状況に陥る危険がある場合は、この 'print(type((f0()))'のように書くことができます。そしてエラーは、言語からではなく、C関数 'type'から来ています。はい、 'type'はstdlibにありますが、それでも言語自体は少なくとも一貫しています。 – dualed

+0

'tostring'を使うと同じ振る舞いをします –

関連する問題