lua-users home
lua-l archive

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

Hi Jamie,

loved your talk at last years Lua workshop!

On 10 Mar 2017, at 15:23, Jamie Jennings <> wrote:

My question is:  Am I asking for trouble by taking this approach?
Apologies for the long post.  I did not have enough time to write a shorter one.  ;-)

Rosie[1] is an application which exposes a CLI and a C API.  The C API, librosie, can be used from languages like Python, node.js, Ruby, Go, and others[2].
But what about Lua users?  Rosie is written in Lua, so I wrote a proper Lua module in a file called 'rosie.lua' .  (The 'rosie.lua' file is created from a template when you install Rosie[3] and build the development branch, tranche-2, because it contains an explicit reference to the Rosie install directory.)
The 'rosie.lua' file can be copied to wherever the user keeps their Lua module files, such as /usr/local/lib/lua/5.3, and it will look in the Rosie installation directory for everything needed to run Rosie.  Thus a single installation of Rosie on a machine will be usable by CLI users, Lua developers, Python developers, etc.
Because Rosie uses C libraries like, 'rosie.lua' loads them from the Rosie installation directory, to ensure that exactly the supported versions are loaded[4].  This also simplifies things for the Lua user, who does not need to install those C libraries in their Lua environment, or who may have different versions of those libraries already installed.
The loading of Lua and C modules is done by a quick hack of a "private module system" that I wrote in an hour.  It's literally around 40 lines of code[5] (yay, Lua!).
This quick hack does two things: (1) it loads code from the right place, and (2) it hides all the Rosie internals from the Lua user, including the fact that some C libraries were loaded.

Why would you hide those modules?

It is a matter of opinion, but I think I’d rather have created a custom loader, as it (from a Lua perspective) adds less magic. See

Also: you’re setting a variable `ROSIE_HOME`, in your initial module you could use the output of `debug.getinfo(1)` to dynamically determine where it is located. 

When you type 'r = require "rosie"', you get exactly one new global, 'r'.  If you look in 'package.loaded', you will see only one new entry (for rosie).
When the user does 'lpeg = require "lpeg"', their own version of is loaded (from wherever they installed it) and everything appears to work fine.  Rosie has its "private" lpeg, and the user has their own.
Is this situation problematic?  In what situations will it cause trouble for users?

The only potential problem I see here is the use of 'something global’ by any of the used modules. Examples would be;
 - using Lua globals (considered bad practice these days, and easy to check)
 - using the Lua registry with named parameters (potential name collisions)

The usual alternative is to make the user install the various C libraries needed by Rosie into their usual Lua lib directory, and for 'rosie.lua' to load them from there.  But this can cause "dependency hell", if the user's needs and Rosie's needs diverge, right?

This relates much to the “why” question above. If you’re targeting regular Lua users with this, then I wouldn’t worry to much about the dependency hell. I’d just make sure it runs with all common Lua versions (if possible 5.1 - 5.3 and LuaJIT) and leave it there. Possibly publish it on LuaRocks which could deal with the dependencies.

If the intend is packaging in some user application and have Rosie work its magic behind the scenes, then I’d probably use some protection like your hiding of the underlying modules. As in that case a user wouldn’t have a clue probably as to what was wrong when getting an error. Yet at the same time, in such a scenario a user might not even have the possibility to add extra modules to the setup and hence the problem you’re trying to fix might not even exist there.


[2] Crude sample programs and modules are provided.  See, e.g. at
[3] The addition of 'rosie.lua' is not yet in a proper release.  It is in the development branch and is created when Rosie is built.
[4] rosie.lua loads init.lua which contains this line: loadfile(ROSIE_HOME .. "/src/core/load-modules.lua", "t", _ENV)