|
Steve Johnson wrote:
For another reason, look into luaopen_io (and then the rest of the library, I guess). Once the function is in Lua you can alter its environment. This makes it easy to load a lot of functions and objects with shared state. http://lua-users.org/lists/lua-l/2005-04/msg00129.html Also, like the point about the stack, you're spared some cleanup effort, since you don't have to save and restore the original environment.
Yes, this is an excellent point and is most close to answering my question. I indicated in my previous message that I saw that these luaopen_* routines were made to be called from within Lua and not from C. You came a step closer to answering my question by reminding me about the environment concept. I then went and re-read the environment section in the manuals. So, this is primarily about the internals of Lua. Its all about scoping. These functions can declare local values in their functions, but they have to be explicitly declared as 'local'. If they do not, they augment the global environment; which affects all other chunks/ functions to come. This can clutter the namespace or cause collisions that this environment method avoids. Coming from an object oriented perspective: When Lua loads these libraries, some of them have a need for shared variables. This could be thought of as member data. Now, they do not want this member data available to the rest of the scope (global environments). So, in order to make this possible, it has to make a separate environment. Why not load these items into the table it creates for the functions? Is this setting of the environment a convenience, in this case? One which, that allows routines to push variables into the global (now private) environment without concerning itself with the name of the table? Why use such, apparent obfuscation, in manipulating these environments when tables injection provides this ability? After all, when the library is loaded, it is in a nice neat table with all its functions available as indice|name|key of that table. Sometimes, yes, it makes an additional global item, like print, or loadlib (if configured). Sorry if these questions are strange. I am not trying to just use Lua (thats easy!) I am trying to fully understand its engineering--how it works internally.
Alex Davies wrote:
I'd say the main reason is is that they can push arbitrary number of results on to the stack. Ie base pushes 2, and the rest 1. Future packages may push 0 or 30. Did you notice that your modified function messes the stack? :). And should Lua ever have more then 20packages, or a package which pushes lots of results, it'll cause a Lua stack overlua. The call is just proper stack handling - you specify how many results you want, you know where the stack is after the call.Indeed, when called from C it causes a problem. During my experiment I registered luaL_openlibs as a Lua C function. I did this by making it a Lua C function and modifying its prototype. Then in my host application I called lua_register(L, "init", luaL_openlibs), I then executed it from Lua and it ran without incident. I did modify the luaL_openlibs to return 0, which truncates the return stack, as indicated in the documentation. This was all just an experiment to learn and probe the internal workings of Lua. The reason I made this change was to see if it was possible to make the call to luaL_openlibs a Lua script writer's decision, rather than a hard coded one. Steve Johnson answered the question as to why, in this particular library (the Lua standard lib), it wants to be called from Lua and not just directly injected as table values. Perhaps with this internal library loading mechanism exposed, it may be able to realize a way to have Lua receive information about the underlying structure of an implementation, its need for private scope, and more, without having to specify those programatically as a Lua script, within the host implementation; because, it is possible to modify the environment of a function from within Lua itself. Again, why do it on the library side? And about private scope, what these environments are really talking about are very similar to encapsulation. Even if the variables are available to the table, which represents that member data, it is still possible for any function in Lua to access those variables in said table. So how do we really hide member data in Lua?
Alex Davies wrote:
Anyway, I'm curious why you're worried about the extra function calls? :) If via some scenario I can't imagine it's become a bottleneck, you could replace thepushcfunction, pushstring, and call with a regular c call and a lua_settop(L, 0), at thecost of some more ambiguity and less consistency with Lua :).
It was not about the overhead or speed or any optimization. It was trying to understand why a C library for Lua would invoke Lua to call that C library for its initialization, as part of that C library. This is a circular logic that did not make sense to me. I understand it now, but I still find it to be obfuscated.
Thanks for all the answers! I hope to hear back on the new questions I raised.
Cheers, Dustin Juliano