2013-08-29 96 views
7

某些Lua函数返回nil以通知用户函数无法执行某些任务(例如,tonumber(),string.find())。从C中的Lua函数返回'nil'与返回0值

在C,returnig nil像这样做:

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; 
    } 
    ... 
} 

这是短。我试过了,它似乎有效,但我不知道这是否是设计。我检查了Lua的源代码,我没有看到这个return 0模式,所以我不知道这是否合法。

是两种不同的方式返回nil相同呢?

(顺便说一句,我都知道通过异常信号错误(即,lua_error()),所以请不要客气。)

UPDATE:

我现在看到,有一个细微的差别在两种方法之间:print((function() end)())将不打印任何内容,而print((function() return nil end)())将打印“无”。我不知道这有多重要。

+0

“我检查了Lua的源代码,我没有看到这个返回0模式”你看起来有多难?所有不返回值的Lua库函数(例如print,table.insert等)在它们的C实现中返回0。 – Mud

+0

@Mud:你给出的例子'print()'和'table.insert()'是不相关的,因为这些函数不应该返回任何东西。我正在讨论通常返回值的函数,比如'tonumber()',如果你检查它们的源代码,你会看到它们执行'lua_pushnil(L);返回1;'。 –

回答

12

函数可能返回nil但也可能返回任何结果,而这种行为是不完全等同,但在大多数情况下会产生相同的结果。

下的Lua脚本显示了如何检测许多回报如何值函数返回:

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 

我说的行为,一旦几乎是等效的,因为当你试图给一个变量的结果函数该变量将得到nil在这两种情况下,因此后续的代码将无法区分。但是,正如我上面所展示的那样,如果您真的需要,您可以检测到差异。

+0

然而,如果你使用'tostring(ReturnNothing())'或者'type(ReturnNothing())',那么会产生一个很大的差别,但是如果在布尔上下文中使用它,lua会认为它是错误的。 –

+0

@XavierCombelle正如我在我的回答中指出的那样,*如果你真的需要,你可以*说出不同之处。而这两个Lua内置函数完全是这样做的:它们区分了这两种情况(很可能是因为在这种情况下,缺少一个值,而不是“无”值,可能是编程错误而不是有意的)。 –

+0

我有这样一行代码'如果没有ReturnNothing()然后打印(tostring(ReturnNothing()))end'花了相当长的调试时间(从我的python背景)以下神秘异常的原因'坏论据#1 to'tostring'(期望值)。“我想说的是,无论是在这两种情况下,还是在没有的情况下,它都是编程错误。 –

5

是的,这是完全有效的。如果你试图请求/分配更多的返回值(不管你是否尝试获得一个或十个),你会得到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,如果某个值应该是无效或nil(但没有发生错误)。在Lua

+0

谢谢。我编辑了我的答案,以说明返回'nil'与不返回任何东西之间的细微差别。但我是Lua的新手,所以我自己无法判断这是否重要。我知道这种行为的原因(我正在阅读PiL书)。我只是想知道为什么,例如,在'tonumber()'的源头(在lbaselib.c中),他们提出了返回'nil'的一点。 –

+0

为您添加的更新:它基本上取决于解释。当然,返回一个值并返回一个值为'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? 

恕我直言,函数的参数传递必须完全符合赋值语句的语义。

+0

如果您有陷入这种情况的危险,您可以像这样写'print(type((f0())))'。错误来自C函数'type',而不是来自语言。是的,'type'在stdlib中,但语言本身至少是一致的。 – dualed

+0

如果使用'tostring',则会出现相同的行为 –