Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

lua

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.

like image 565
Niccolo M. Avatar asked Aug 29 '13 23:08

Niccolo M.


People also ask

Is nil null Lua?

When programming in Lua, it is important to understand the different meanings of nil and NULL. Nil is the "unknown type" in the context of Lua whereas null and NULL represent the SQL NULL. The NULL constant is not part of standard Lua and was added by us so the user can do NULL comparisons of result data.

How do you return a value from a function in Lua?

The Lua return keyword is a built in keyword in the Lua programming, which is used to return the result from a function. There is an implicit return at the end of the Lua functions. As per syntactic reason the return statement should be the last statement of a block or function, before the end keyword.

Does return end a function Lua?

A return statement returns occasional results from a function or simply finishes a function.


2 Answers

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.

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

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.

like image 51
Lorenzo Donati -- Codidact.com Avatar answered Oct 03 '22 05:10

Lorenzo Donati -- Codidact.com


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.

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

like image 42
Mario Avatar answered Oct 03 '22 05:10

Mario