Dooo Reyn
Dooo Reyn

Reputation: 33

Is 'none' one of basic types in Lua?

The basic types defined in Lua as below :

/*
** basic types
*/
#define LUA_TNONE       (-1)
#define LUA_TNIL        0
#define LUA_TBOOLEAN        1
#define LUA_TLIGHTUSERDATA  2
#define LUA_TNUMBER     3
#define LUA_TSTRING     4
#define LUA_TTABLE      5
#define LUA_TFUNCTION       6
#define LUA_TUSERDATA       7
#define LUA_TTHREAD     8
#define LUA_NUMTAGS     9

As Lua Document says that there only 8 basic types in Lua. However, there gets 10. I know LUA_TLIGHTUSERDATA and LUA_TUSERDATA could finnally represented as userdata, but what about LUA_TNONE? And what is the differences of none and nil?

Upvotes: 2

Views: 3347

Answers (1)

pschulz
pschulz

Reputation: 1545

As was already mentioned in the comments, none is used in the C API to check whether there is no value. Consider the following script:

function foo(arg)
    print(arg)
end

foo(nil) --> nil
foo()    --> nil

In Lua you can use select('#', ...) to get the number of parameters passed to foo and using C API you can check if the user supplied no argument at all (using lua_isnone). Consider the following small C library, which works like type, except that it can recognize, if no argument was given:

#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>

static int which_type(lua_State* L)
{
    // at first, we start with the check for no argument
    // if this is false, there has to be at least one argument
    if(lua_isnone(L, 1))
    {
        puts("none");
    }
    // now iterate through all arguments and print their type
    int n = lua_gettop(L);
    for(int i = 1; i <= n; ++i)
    {
        if(lua_isboolean(L, i))
        {
            puts("boolean");
        }
        else if(lua_istable(L, i))
        {
            puts("table");
        }
        else if(lua_isstring(L, i) && !lua_isnumber(L, i))
        {
            puts("string");
        }
        else if(lua_isnumber(L, i))
        {
            puts("number");
        }
        else if(lua_isfunction(L, i))
        {
            puts("function");
        }
        else if(lua_isnil(L, i))
        {
            puts("nil");
        }
        else if(lua_isthread(L, i))
        {
            puts("thread");
        }
        else if(lua_isuserdata(L, i))
        {
            puts("userdata");
        }
    }

    return 0;
}

static const struct luaL_Reg testclib_functions[] = {
    { "type", which_type },
    { NULL,  NULL         }
};

int luaopen_testclib(lua_State* L)
{
    luaL_newlib(L, testclib_functions);

    return 1;
}

Compile this with something like gcc -shared -fPIC -o testclib.so testclib.c. In lua, we now load the library and use the function type:

local p = require "testclib"

p.type(nil)    --> nil
p.type({})     --> table
p.type("foo")) --> string
-- now call it without any arguments
p.type())      --> none, not nil
--type()       -- error: bad argument #1 to 'type' (value expected)

Note that you can't get 'none' and someother type from one call (while it is possible to receive multiple types by using multiple arguments, e.g. p.type("foo", 42)). This is quite logical, since it would be a syntactic error to use something like this:

p.type(, 42) -- error

One use of this can be seen in the print function, where print(something) prints the value (even it is not valid, e.g. nil), where print() prints a newline.

Upvotes: 4

Related Questions