在C中从Lua函数返回'nil'与返回0值的区别

一些 Lua 函数会返回 nil 来向用户指示该函数无法执行某些任务(例如 tonumber()string.find())。

在 C 中,返回 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())来指示错误,所以请不要提到它。)

更新:

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

点赞
用户409744
用户409744

是的,这是完全有效的。如果你想请求/分配比返回值还多的返回值(无论你是要获取一个还是十个),你会得到未定义的那些的 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-29 23:07:56
用户2633423
用户2633423

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-30 06:04:10
用户1847592
用户1847592
这种人为区别 `nil` 和 `无值` 之间的差别是不一致和相当烦人的:

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

local v1 = f1() -- OK,赋为 nil print(type(f1())) -- OK,打印 'nil'

local v0 = f0() -- OK,赋为 nil print(type(f0())) -- 为什么会引发错误?


在我看来,函数参数传递必须完全遵守赋值语句的语义。 
2013-08-31 07:12:08