Returning 'nil' from a Lua function in C vs returning 0 values

时间:2021-04-25 09:52:00

Some Lua functions return nil to signal the user that the function couldn't carry out some task (e.g., tonumber(), string.find()).

一些Lua函数返回nil以通知用户该函数不能执行某些任务(例如,tonumber(),string.find())。

In C, returnig nil is done like this:

在C中,returnig nil是这样完成的:

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

HOWEVER, I wonder if it's alright to do the following instead:

但是,我想知道是否可以做以下事情:

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

It's shorter. I tried it and it seems to works, but I don't know if that's by-design. I examined Lua's source code and I don't see this return 0 pattern so I wonder if it's legit to do this.

它更短。我尝试了它似乎工作,但我不知道这是否是按设计。我检查了Lua的源代码,我没有看到这个返回0模式,所以我想知道这样做是否合法。

Are the two different ways to return nil equivalent?

返回零的两种不同方式是否相同?

(BTW, I know all about signaling errors via exceptions (that is, lua_error()) so please don't mention it.)

(顺便说一下,我知道所有关于通过异常发出的信号错误(即lua_error())所以请不要提及它。)

UPDATE:

I now see that there's a subtle difference between the two methods: print((function() end)()) would print nothing whereas print((function() return nil end)()) would print "nil". I don't know how important this is.

我现在看到两种方法之间存在细微的差别:print((function()end)())什么都不打印而print((function()return nil end)())会打印“nil”。我不知道这有多重要。

3 个解决方案

#1


12  

Functions in Lua may return nil but may also return nothing, and this behavior is not exactly equivalent, although in most context will produce the same results.

Lua中的函数可能返回nil,但也可能没有返回任何内容,并且这种行为并不完全等效,尽管在大多数情况下会产生相同的结果。

The following Lua script shows you how to detect how many return values a function returns:

以下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

I said the behavior is almost equivalent because as soon as you try to assign to a variable the result of a function that variable will get nil in both cases, thus the subsequent code won't be able to tell the difference. But, as I showed above, you can detect the difference if you really need.

我说行为几乎是等价的,因为只要你尝试为变量分配一个函数的结果,变量在两种情况下都会得到nil,因此后续的代码将无法区分。但是,正如我上面所示,如果你真的需要,你可以发现差异。

#2


5  

Yes, this is perfectly valid. If you're trying to request/assign more return values than there are (no matter whether you try to get one or ten), you'll get nil for the undefined ones (i.e. those not returned).

是的,这完全有效。如果您尝试请求/分配的返回值多于(无论您是尝试获得一个还是十个),那么未定义的返回值(即未返回的值)将为零。

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

You probably can't find it in Lua's source because it's no special case or anything. It's just Lua's generic way to handle return values.

你可能无法在Lua的源代码中找到它,因为它不是特例或任何特殊情况。这只是Lua处理返回值的通用方法。

Update:

The difference you've noticed when trying to print return values is the fact that this is not just an assignment. Of course there is a slight difference between returning nil and returning nothing at all - and it's possible to differentiate there. In the end you'll just have to make sure you document your function's behavior properly, i.e. tell the user what's supposed to happen. For example, returning nil (or getting nil in an assignment) could represent an error state, but it's also possible to return nothing in case there's been an error and return nil if some value is supposed to be invalid or nil (but no error happened).

您在尝试打印返回值时注意到的差异是,这不仅仅是一项任务。当然,在返回零和返回任何内容之间存在细微差别 - 并且可以区分那里。最后,您必须确保正确记录您的功能行为,即告诉用户应该发生什么。例如,返回nil(或在赋值中获取nil)可能表示错误状态,但是如果出现错误也可以返回任何内容,如果某个值应该是无效或为零,则返回nil(但没有发生错误) )。

#3


2  

(This is not an answer, just an opinion about the subject)

(这不是答案,只是关于这个问题的意见)

As for me, this artifical difference between nil and no value is inconsistent and rather annoying.

至于我,nil和no值之间的这种人为差异是不一致的而且相当烦人。

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, function's parameter passing must fully comply with semantic of assignment statement.

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

#1


12  

Functions in Lua may return nil but may also return nothing, and this behavior is not exactly equivalent, although in most context will produce the same results.

Lua中的函数可能返回nil,但也可能没有返回任何内容,并且这种行为并不完全等效,尽管在大多数情况下会产生相同的结果。

The following Lua script shows you how to detect how many return values a function returns:

以下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

I said the behavior is almost equivalent because as soon as you try to assign to a variable the result of a function that variable will get nil in both cases, thus the subsequent code won't be able to tell the difference. But, as I showed above, you can detect the difference if you really need.

我说行为几乎是等价的,因为只要你尝试为变量分配一个函数的结果,变量在两种情况下都会得到nil,因此后续的代码将无法区分。但是,正如我上面所示,如果你真的需要,你可以发现差异。

#2


5  

Yes, this is perfectly valid. If you're trying to request/assign more return values than there are (no matter whether you try to get one or ten), you'll get nil for the undefined ones (i.e. those not returned).

是的,这完全有效。如果您尝试请求/分配的返回值多于(无论您是尝试获得一个还是十个),那么未定义的返回值(即未返回的值)将为零。

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

You probably can't find it in Lua's source because it's no special case or anything. It's just Lua's generic way to handle return values.

你可能无法在Lua的源代码中找到它,因为它不是特例或任何特殊情况。这只是Lua处理返回值的通用方法。

Update:

The difference you've noticed when trying to print return values is the fact that this is not just an assignment. Of course there is a slight difference between returning nil and returning nothing at all - and it's possible to differentiate there. In the end you'll just have to make sure you document your function's behavior properly, i.e. tell the user what's supposed to happen. For example, returning nil (or getting nil in an assignment) could represent an error state, but it's also possible to return nothing in case there's been an error and return nil if some value is supposed to be invalid or nil (but no error happened).

您在尝试打印返回值时注意到的差异是,这不仅仅是一项任务。当然,在返回零和返回任何内容之间存在细微差别 - 并且可以区分那里。最后,您必须确保正确记录您的功能行为,即告诉用户应该发生什么。例如,返回nil(或在赋值中获取nil)可能表示错误状态,但是如果出现错误也可以返回任何内容,如果某个值应该是无效或为零,则返回nil(但没有发生错误) )。

#3


2  

(This is not an answer, just an opinion about the subject)

(这不是答案,只是关于这个问题的意见)

As for me, this artifical difference between nil and no value is inconsistent and rather annoying.

至于我,nil和no值之间的这种人为差异是不一致的而且相当烦人。

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, function's parameter passing must fully comply with semantic of assignment statement.

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