lua-users home
lua-l archive

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


Thank you; this is very helpful.

I didn’t expect that a return statement from a main chunk would leave the returned value(s?) on the stack. (I assumed it only works in modules because of require.) Top level returns are a syntax error in all the languages I’m familiar with.

Since it seems the interpreter literally wraps main chunks in a function call (I assumed load was just doing some back-end hand-waving), if the main chunk is only a single function declaration, will load then leave the declared function on the stack, or will it be wrapped in another layer of function call?

This message composed at the mercy of thumbs and autocorrect.

> On Nov 14, 2021, at 11:31 AM, Javier Guerra Giraldez <javier@guerrag.com> wrote:
> 
> On Sun, 14 Nov 2021 at 04:09, Benjamin Riggs
> <riggs@entropicengineering.com> wrote:
>> 
>> I'm new to Lua and using it to run user-supplied business logic on an embedded system. The API I would like is for chunks to be loaded and run with each chunk leaving a function (with a closure) on the stack. This returned function will then be called periodically and will update state values. I'm trying to avoid requiring user code to use a designated name and trying to minimize the boilerplate of registering or assigning the function.
>> 
>> Is there an elegant pattern that enables what I want?
> 
> I see two ways to do it:
> 
> 1: the chunk is a function
> as you probably know, the result of loading a Lua source file, either
> with `load()` or `loadfile()` from Lua or `lua_load()`,
> `luaL_loadbuffer()`, or `luaL_loadfile()` from C, is a function in the
> stack.  So, if you just write your code straight in a file, _without_
> wrapping with `function()...end`, it will produce a function that you
> can call repeatedly.
> 
> there are some limitations with this:
> 
> 1.1: no named parameters:  obviously, without a `function(...)` at the
> beginning, you don't have named parameters, but you can still call it
> with any number of arguments if you wish.  to give a name in the user
> function, just start with `arg1, arg2, argxxxx = ...`  (the dots at
> the end are the trick, it's not me trying to say "put something here",
> actually write three dots)
> 
> 1.2: no upvalues, unless your system provides some.  but that limits
> flexibility for the end user
> 
> 1.3: no "load time" for the user.  unless there's some contract that
> the function is called with some parameter indicating it's just been
> loaded, or use some upvalue to keep a count... neither is a nice way.
> 
> 
> 2. return the function
> 
> just end the user's file with a `return ffff` statement, where `fff`
> is a function.  Either it was a `local function myfunc () .... end`
> and then `return myfunc`, or directly like `return function() ...
> end`.   for this to work, the system must first load the file as a
> chunk, then call the chunk and the returned function will be found in
> the stack.
> 
> any Lua code "outside" the function would be executed at "load time"
> (on that first call, just after loading the chunk), so it can perform
> any required initialization, and define any wanted upvalues (so the
> returned function is a full featured closure).
> 
> the only limitation here is about the possibility of wanting more than
> one function on a single user file.  for example, to share upvalues.
> The easiest way to "extend" this would be to return a table instead of
> a function.  which is exactly the same as defining a Lua module, that
> can be loaded with `require`.
> 
> Of course, you could return any object with a `__call()` metamethod,
> so it looks like a function and can be called normally, but keeps more
> state besides upvalues, or could return other functions or values as
> "fields", (either because it's actually a table, or by adding an
> `__index`).
> 
> 
> In short, if you're absolutely, positively sure that you won't require
> multiple functions in the same file, just ask the user to return the
> function at the end of the file.  Otherwise, ask for a small module.
> 
> -- 
> Javier