9

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

In C, returnig nil is done like this:

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.

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.)

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.

4

3 回答 3

14

Lua 中的函数可能会返回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在两种情况下都会得到,因此后续代码将无法区分。但是,正如我在上面展示的,如果你真的需要,你可以检测到差异。

于 2013-08-30T06:04:10.740 回答
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(但没有发生错误)则返回。

于 2013-08-29T23:07:56.083 回答
2

nil和之间的这种人为差异no 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?

在我看来,函数的参数传递必须完全符合赋值语句的语义。

于 2013-08-31T07:12:08.877 回答