I can't understand how the closure works in Dart. Why does BMW stay? This explanation causes my neurons to overheat. A lexical closure is a functional object that has access to variables from its lexical domain. Even if it is used outside of its original scope.
`void main() {
var car = makeCar('BMW');
print(makeCar);
print(car);
print(makeCar('Tesla'));
print(car('Audi'));
print(car('Nissan'));
print(car('Toyota'));
}
String Function(String) makeCar(String make) {
var ingane = '4.4';
return (model) => '$model,$ingane,$make';
}`
Console
Closure 'makeCar'
Closure 'makeCar_closure'
Closure 'makeCar_closure'
Audi,4.4,BMW
Nissan,4.4,BMW
Toyota,4.4,BMW
Calling car('Audi') is equal to calling (makeCar('BMW'))('Audi');
A lexical closure is a functional object that has access to variables from its lexical domain. Even if it is used outside of its original scope.
in simple english:
String make will stay valid as long as the returned function is not out of scope because the returned function has reference to String make.
In essence, you "inject" information needed for the newly created function. Your car knows that make is "BMW"
I think I figured it out. Here is an example where I left comments. Maybe it will help someone.
void main() {
var pr = funkOut(10); // assign a reference to an object instance
// of the Function class to the pr variable. pr is a closure because
// it is assigned a reference to an instance that contains a lexical
// environment (int a) and an anonymous function from this environment.
// 10 transfer to a
print(pr(5)); // 5 transfer to b //15
print(pr(10)); // 10 transfer to b //20
pr = funkOut(20);// 20 transfer to a
print(pr(5)); // 5 transfer to b //25
print(pr); // Closure: (int) => int
}
Function funkOut(int a) {
return (int b) => a + b;
}
EDIT: Turns out this is not something possible with Lua, having the __index method AND methods like class instance methods. It's either or.
Trying to get my Lua interface to work where both fields and instance methods are supported. It seems that by manipulating the initialization, I can only get the functions (_f), or the methods (_m) to work, not both.
I feel like it's something really simple I'm just missing.
How I initialize the library:
void PushUserdata(const void *data, const char *metatable)
{
const void **wrapped_ptr = (const void**)lua_newuserdata(l, sizeof(const void*));
*wrapped_ptr = data;
luaL_getmetatable(l, metatable);
lua_setmetatable(l, -2);
}
static int player_head(lua_State *L)
{
if (!Player::playerHead)
lua_pushnil(L);
else
PushUserdata(Player::playerHead, "player");
return 1;
}
static int playerget(lua_State *L)
{
Player *player = *CHECKPLAYER(L, 1); // Get double pointer and dereference to get real pointer
const char *field = luaL_checkstring(L, 2);
if (!strcmp(field, "next"))
{
if (!player->next)
lua_pushnil(L);
else
PushUserdata(player->next, "player");
}
else if (!strcmp(field, "prev"))
{
if (!player->prev)
lua_pushnil(L);
else
PushUserdata(player->prev, "player");
}
else if (!strcmp(field, "obj"))
{
if (!player->obj)
lua_pushnil(L);
else
PushUserdata(player->obj, "wobj");
}
else if (!strcmp(field, "AddCollisionObjHook")) // This ends up here if __index is in the table below...
{
}
else
return 0;
return 1;
}
static const struct luaL_Reg playerlib_f[] = {
{"head", player_head},
{"AddPreThinker", AddPreThinker},
{"AddPostThinker", AddPostThinker},
{NULL, NULL}
};
static const struct luaL_Reg playerlib_m[] = {
{"__tostring", player2string},
{"__index", playerget},
{"__newindex", playerset},
{"AddCollisionObjHook", AddCollisionObjHook},
{NULL, NULL}
};
int Lua_PlayerLib(lua_State *L)
{
luaL_newmetatable(L, "player");
lua_pushvalue(L, -1); // duplicates the metatable...but why?
luaL_setfuncs(L, playerlib_m, 0);
luaL_newlib(L, playerlib_f, 0);
lua_setglobal(L, "player");
return 1;
}
Lua script:
me = playerlib.head()
me:AddCollisionObjHook(playerHitObj)
Error message:
Warning: [string "postload.lua"]: attempt to call method 'AddCollisionObjHook' (a nil value)
'me' is absolutely a valid non-nil value.
What you're trying to do is possible, but not in the way you're trying to do it.
I think it's worth reviewing how method calls and metatables/metamethods work, and what your code, as written, is actually doing. The tl;dr is:
method calls are just normal field lookups
metatables, and the metamethods they contain, are operator overloads, not method definitions
if you're implementing this for userdata you need an __index metamethod that can handle both field and method lookups
First of all, Lua has no inbuilt distinction between "methods" and "fields". You may find it convenient to differentiate the two when organizing your code, but as far as the Lua language is concerned methods and fields are the same thing. A method is just a field where the key is a valid lua identifier and the value is a function.
So, when you write something like me:AddCollisionObjHook(playerHitObj), what actually happens is something like:
local self = me
local method = self["AddCollisionObjHook"]
method(self, playerHitObj)
(Two notes on this:
no actual new locals are created; this all happens in the internals of the Lua interpreter.
self["AddCollisionObjHook"] and self.AddCollisionObjHook are two ways of writing the same thing; the latter is just a convenient shortcut for the former.)
So, how does that self["AddCollisionObjHook"] lookup work? The same way any other field lookup works. The Lua Manual goes into detail on this, including pseudocode, but the part relevant to your code is:
-- We're looking up self[key] but self is userdata, not table
local mt = getmetatable(self)
if mt and type(mt.__index) == 'function' then
-- user provided an __index function
return mt.__index(self, key)
elseif mt and mt.__index ~= nil then
-- user provided an __index table (or table-like object)
-- retry the lookup using it
return mt.__index[key]
else
-- no metatable, or metatable lacks __index metamethod
error(...) -- don't know how to do field lookup on this type!
end
Note that at no point in this process are fields other than __index looked up in the metatable. The metatable exists only to tell Lua how to implement operators for types that don't normally have them; in this case the field lookup ("index") operator ([], and its aliases . and :) for a specific kind of userdata. It's entirely down to __index itself to handle the actual process of turning field names into values, either by being a table that the lookup can be retried with or by being a function that can return the associated value.
So, this brings us to the answer of how to support both (settable) fields and (callable) methods:
__newindex needs to understand how to set fields
__index needs to understand how to return both field values and method implementations
Since, from Lua's perspective, both field lookups and method lookups are the same operation, and thus __index gets used for both.
In light of that, how should we organize the code to support both, and how can we restructure your code to work? There's lots of ways to do this, although for the purposes of this answer I'm going to make a few assumptions:
fields are stored entirely C-side, with no corresponding data to manage in Lua
methods cannot be overwritten by Lua code
metamethods are stored separately from instance methods
The last one is not strictly necessary; in fact it's very common to store both metamethods and instance methods in the same table (I usually do this myself). However, I think this also tends to engender confusion among Lua newbies about the distinction between them, so the interest of making the code as clear as possible, I'm separating them out in this answer.
With that in mind, let's rework the setup code. I've looked at your edits to try to reconstruct what you originally had in mind.
static int playerget(lua_State *L)
{
Player *player = *CHECKPLAYER(L, 1);
const char *field = luaL_checkstring(L, 2);
// Check if it's a method, by getting the method table
// and then seeing if the key exists in it.
// This code can be re-used (or factored out into its own function)
// at the start of playerset() to raise an error if the lua code tries
// to overwrite a method.
lua_getfield(L, LUA_REGISTRYINDEX, "player-methods");
lua_getfield(L, -1, field);
if (!lua_isnil(L, -1)) {
// Lookup in methods table successful, so return the method impl, which
// is now on top of the stack
return 1;
} else {
// No method, so clean up the stack of both the nil value and the
// table of methods we got it from.
lua_pop(L, 2);
}
if (!strcmp(field, "next"))
// ... code for reading fields rather than methods goes here ... //
}
// Functions that are part of the player library rather than tied to any
// one player instance.
static const struct luaL_Reg playerlib_api[] = {
// player.head() -> returns the first player
{"head", player_head},
{NULL, NULL}
};
// Metamethods defining legal operators on player-type objects.
static const struct luaL_Reg playerlib_metamethods[] = {
// Overrides the tostring() library function
{"__tostring", player2string},
// Adds support for the table read operators:
// t[k], t.k, and t:k(...)
{"__index", playerget},
// Adds support for the table write operators:
// t[k]=v and t.k=v
{"__newindex", playerset},
{NULL, NULL}
};
// Instance methods for player-type objects.
static const struct luaL_Reg playerlib_methods[] = {
// player_obj:AddCollisionObjHook(hook)
{"AddCollisionObjHook", AddCollisionObjHook},
// player_obj:AddPreThinker(thinker)
{"AddPreThinker", AddPreThinker},
// player_obj:AddPostThinker(thinker)
{"AddPostThinker", AddPostThinker},
{NULL, NULL}
};
int Lua_PlayerLib(lua_State *L)
{
// Create the metatable and fill it with the stuff from playerlib_metamethods.
// Every time a player object is pushed into Lua (via player_head() or similar)
// this metatable will get attached to it, allowing lua to see the __index,
// __newindex, and __tostring metamethods for it.
luaL_newmetatable(L, "player");
luaL_setfuncs(L, playerlib_metamethods, 0);
lua_pop(L, 1);
// Create the method table and fill it.
// We push the key we're going to be storing it in the registry under,
// then the table itself, then store it into the registry.
lua_pushliteral(L, "player-methods");
luaL_newlib(L, playerlib_methods, 0);
lua_settable(L, LUA_REGISTRYINDEX);
// Initialize the `player` library with the API functions.
luaL_newlib(L, playerlib_api, 0);
// Set that table as the value of the global "player".
// This also pops it, so we duplicate it first...
lua_pushvalue(L, -1);
lua_setglobal(L, "player");
// ...so that we can also return it, so that constructs like
// local player = require 'player'; work properly.
return 1;
}
Breaking it down, this gives us three tables:
player, which holds the actual library API like player.head()
REGISTRY["player"], which holds the metatable shared by all player objects
__tostring which is invoked for prettyprinting
__newindex which is invoked for field writes
__index which is invoked for field reads (including method lookup!)
REGISTRY["player-methods"], which holds all the instance methods
__index looks here for method implementations
As noted above, I've kept the table of metamethods and the table of methods separate in the hopes of minimizing conceptual confusion; idiomatic code would probably store all the methods and metamethods together, and use luaL_getmetafield() at the start of playerset() and playerget() to do method lookup.
Everybody knows it is good programming practice to keep the stack balanced. What I'm wondering, though, is whether I'm allowed to modify stack values in a C function called from a Lua script? Consider the following code:
int myfunc(lua_State *L)
{
int arg1 = luaL_checkinteger(L, 1);
int arg2 = luaL_checkinteger(L, 2);
// pop arg 2
lua_pop(L, 1);
// this is to be our return value
lua_newtable(L);
...do complicated stuff...
// restore second parameter but set it to nil for convenience's sake
lua_pushnil(L);
lua_insert(L, 2);
// return our table
return 1;
}
So the code above replaces the second parameter with nil. Is this allowed or do I have to restore the original value, i.e. would I have to do
lua_pushinteger(L, arg2);
instead of
lua_pushnil(L);
? Or doesn't this matter as long as myfunc returns with the stack balanced?
The stack values are the property of the C function being called. You can do whatever you wish with them. The only effect to the outside is the values returned by the function.
C functions called from Lua do not need to keep the stack balanced, that is, with the same contents or number of items it had on entry.
Can you alias a function (not in a class) in LUA in a similar way to Ruby? In ruby you would do something like this:
alias new_name_for_method method()
def method()
new_name_for_method() # Call original method then do custom code
i = 12 # New code
end
I'm asking because I'm developing for a program that uses LUA scripting and I need to override a function that is declared in a default file.
In Lua, functions are values, treated like any other value (number, string, table, etc.) You can refer to a function value via as many variables as you like.
In your case:
local oldmethod = method
function method(...)
oldmethod(...)
i = 12 -- new code
end
keep in mind that
function method() end
is shorthand for:
method = function() end
function() end just creates a function value, which we assign to the variable method. We could turn around and store that same value in a dozen other variables, or assign a string or number to the method variable. In Lua, variables do not have type, only values do.
More illustration:
print("Hello, World")
donut = print
donut("Hello, World")
t = { foo = { bar = donut } }
t.foo.bar("Hello, World")
assert(t.foo.bar == print) -- same value
FYI, when wrapping a function, if you want its old behavior to be unaffected for now and forever, even if its signature changes, you need to be forward all arguments and return values.
For a pre-hook (new code invoked before the old), this is trivial:
local oldmethod = method
function method(...)
i = 12 -- new code
return oldmethod(...)
end
A post-hook (new code invoked after the old) is a bit more expensive; Lua supports multiple return values and we have to store them all, which requires creating a table:
local oldmethod = method
function method(...)
local return_values = { oldmethod(...) }
i = 12 -- new code
return unpack(return_values)
end
In lua, you can simply override a variable by creating a new function or variable with the same name.
function name_to_override()
print('hi')
end
If you still want to be able to call the old function:
local old_function = name_to_override
function name_to_override()
old_function()
print('hi')
end
How does one get the value back from a Lua function call in LuaJava.
Lets say I have calc.lua:
function foo(n) return n*2 end
I call the function in Java as follows:
LuaState luaState;
this.luaState = LuaStateFactory.newLuaState();
this.luaState.openLibs();
this.luaState.LdoFile("calc.lua");
this.luaState.getGlobal("foo");
this.luaState.pushNumber(5.0);
int retcode=this.luaState.pcall(1, 1,0);
Now what do I have to call on LuaState object to get the result of this last function call foo(5)?
Is there an example somewhere showing Java->Lua invocation with return values from the call?
Would something like this do the trick?
int top_index = luaState.getTop();
double result = luaState.isNumber(top_index) ?
luaState.toNumber(top_index) : 0.0;