Lua中是否包含'none'作为基本类型?

在Lua中定义了以下基本类型:

/*
** 基本类型
*/
#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

正如Lua文档所述,Lua中只有8种基本类型。而实际上有10种。我知道LUA_TLIGHTUSERDATALUA_TUSERDATA 最终可以表示为 userdata,但是 LUA_TNONE 是什么呢?nonenil 的区别是什么?

点赞
用户3197530
用户3197530

正如在评论中已经提到的那样,none 在 C API 中用于检查是否没有值。考虑以下脚本:

function foo(arg)
    print(arg)
end

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

在 Lua 中,您可以使用 select('#', ...) 来获取传递给 foo 的参数数目,使用 C API 可以检查用户是否没有提供任何参数(使用 lua_isnone)。考虑以下类似 type 的小型 C 库,除了它能识别是否给定参数之外:

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

static int which_type(lua_State* L)
{
    // 首先,我们从检查是否没有参数开始
    // 如果为 false,则必须至少有一个参数
    if(lua_isnone(L, 1))
    {
        puts("none");
    }
    // 现在迭代所有参数并打印它们的类型
    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;
}

使用 gcc -shared -fPIC -o testclib.so testclib.c 这样的命令编译它。在 Lua 中,现在我们加载库并使用函数 type

local p = require "testclib"

p.type(nil)    --> nil
p.type({})     --> table
p.type("foo")) --> string
-- 现在不使用任何参数调用它
p.type())      --> none, not nil
--type()       -- 错误:'type' 的第 1 个参数类型不正确

请注意,您不能从一次调用中获取“none”和其他类型(使用多个参数可以接收多个类型,例如 p.type("foo", 42))。这是相当合理的,因为使用类似这样的东西将是一种语法错误:

p.type(, 42) -- 错误

其中一种用途可以在 print 函数中看到,其中 print(something) 会打印值(即使它不是有效的,例如 nil),而 print() 则打印一个换行符。

2016-07-25 09:23:17