lua-users home
lua-l archive

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


On Sat, Feb 25, 2017 at 3:31 PM Tony Papadimitriou <tonyp@acm.org> wrote:
The command-line –l option help says: -l name  require library 'name'
 
I assumed this to be equivalent to starting a script with: require ‘name’
 
Now, if I have a library file named xxx.lua which also includes a function named xxx,
using the –l method vs the explicit require method does not behave the same.
 
To reproduce:
 
File xxx.lua contains just this: function xxx() print 'hello' end
 
And, here’s the output I get for each case:
 
c:\temp>lua -l xxx -e "xxx()
lua: (command line):1: attempt to call a boolean value (global 'xxx')
stack traceback:
        (command line):1: in main chunk
        [C]: in ?
 
c:\temp>lua -e "require 'xxx' xxx()
hello
 
Is this expected behavior, or bug? If expected, then perhaps the help message is a bit misleading.
 
Thank you.

`-l name` is not equivalent to `require "name"`. It is equivalent to `name = require "name"`. This is important because require() always returns a value. This value is either the value returned by the module chunk, or if that returns nothing, the value of package.loaded["name"]. If the module does not modify that field or explicitly return a value, then that field is set to true before require returns, so require will return true in that case.

So what happens here is that Lua finds xxx.lua and runs it, which defines the global `xxx` variable as a function. However, xxx.lua neither returns a value nor modifies package.loaded["xxx"], so that field is set to true, and the call to require "xxx" then returns true, which is then assigned to the global `xxx`, overwriting the function that was there. All of this behavior of require() is expected and documented behavior [1], and this is why you get "attempt to call a boolean value".

The fact that `-l xxx` is equal to `xxx = require "xxx"` rather than merely `require "xxx"` is not clear from reading the reference manual, but it, and the change in behavior from 5.1 to 5.2, make sense when you consider standard Luaisms and the history of Lua. In 5.1, the standard way of writing a module used the module() function [2], which directly injected the module contents into a specified global variable, so there was no need to capture a return value, and the behavior of `-l` assumed this. In 5.2, module() was removed as part of the general changes to environments, and the standard way of writing modules, especially modules aiming to be cross-compatible with 5.1 and 5.2, shifted to explicitly returning the module table, so the behavior of `-l` changed to adapt to this.

P.S. Please don't use Comic Sans. Really. It's not appropriate for serious discussions, and drives me crazy when it is used that way. [3]

[1] https://www.lua.org/manual/5.3/manual.html#pdf-require
[2] https://www.lua.org/manual/5.1/manual.html#pdf-module
[3] http://www.comicsanscriminal.com/