lua-users home
lua-l archive

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


On Tue, Aug 28, 2012 at 7:15 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> 2012/8/27 Jay Carlson <nop@nop.com>:
>> The alternative is ml=require"ml", and we seem to be trying
>> to discourage that.
>
> Are we? Even in Lua 5.2, we still have "lua -i -l mymodule"
> and hey presto, there's something in the global namespace called
> "mymodule".
>
> No, what we are trying to discourage is modules assigning things
> directly to global names, instead of the user program doing it.

Uh, so the Lua interpreter assigning a module to a global variable is
okay but for require() it's not okay?

> There's nothing evil about global variables.  What is evil, is code
> that you can't see in front of your nose assigning stuff to them.

No, global variables are indeed very evil. We regularly have problems
with them in the Nmap Scripting Engine where code is threaded (in the
Lua sense) and threads unintentionally overwrite each other's
variables.

> I absolutely agree with the title of your post, but I disagree with
> the imputation that it's a weakness of the current require. I believe
> the notion that module names should be local variables all the time is
> misguided.  Sometimes maybe, for special reasons, such as sandboxing,
> but not regularly.

Again, an example from the Nmap Scripting Engine:

Scripts would require libraries, many written in plain Lua, such as
http.lua. These would be done quite simply and in the encouraged
fashion:

require("http")

Because the library is stored in a global, all subsequent access would
be correct. This quickly deteriorates into a situation where the
script writer depends on a library which depends on another library
that the script uses incidentally but forgets to require:

-- script.nse --
require("http")

function foo (...)
  local a = base64.encode(str)
end

-- http.lua --
require "base64"


This script.nse will "just work" but is going to fail when http.lua
for whatever reason no longer needs base64.

What's an even worse (and not necessarily NSE specific) example, if
you have a script which depends on a library but does not require it,
it may have that library loaded via another script. And, because
scripts are run in an arbitrary and random looking order, you won't
know the library wasn't required until a user comes back complaining
with an error: 'attempt to index global 'get' (a nil value)'.

All of this is prevented by *forcing* code to localize a copy to the
library. It doesn't have access otherwise and so it cannot
accidentally forget to require. This problem is so insidious and
annoying that we (Nmap) have nixed globals in almost every instance in
favor of locals. A local is always predictable.

-- 
- Patrick Donnelly