lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> Le 31 janv. 2015 à 11:45, Bertrand Mansion <lua@mamasam.net> a écrit :
> 
> In Lua programs, I often see code like the following:
> 
>  if host.devices and host.devices.bridge and host.devices.bridge.friendlyName then
> 
> Are there other ways in Lua to check for a key existence ?

This can easily be done by configuring Lua with the C API (supposing that you have access to the C code integrating Lua in your environment).

The idea here is to add a metatable to the nil value, so that `nil[anIndex]` returns nil.

Here is the code to do it (also on gist: https://gist.github.com/jlj/9a9d4ce166092ba427ce):

static int handleNilIndexing (lua_State* luaState)
{
	return 0;  // returning zero results is equivalent to returning nil
}

lua_State* setupLua()
{
	// Create the new lua state
	lua_State* luaState = luaL_newstate();
	
	// Set the indexing of nil as a valid operation
	lua_pushnil(luaState); // <-- nil
	lua_createtable(luaState, 0, 2); // <-- nil_metatable
	lua_pushcfunction(luaState, handleNilIndexing); // <-- nil_field_handler
	lua_setfield(luaState, -2, "__index"); // nil_metatable.__index = nil_field_handler
	lua_setmetatable(luaState, -2); // nil.metatable = nil_metatable
	lua_pop(luaState, 1); // -x- nil
	
	return luaState;
}

With this you can write `local friendlyName = host.devices.bridge.friendlyName` without having to check for intermediate nil values.

If you need it, you can also add a `__newindex` or a `__call` metamethod, to avoid triggering errors when setting a field in a nil table or when calling a function in a nil object.

Jean-Luc