lua-users home
lua-l archive

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


I tried hard to stay out of this discussion, because I believe it is
only a rehash of many years' discussion of one programming language
design issue.  But 3 really good points have been made and 1 really
good question raised in the last days, and I want to highlight the
former and answer the latter.

On Fri, 9 Jul 2010 08:47:49 -0400, David Goehrig <dave@nexttolast.com> wrote:
> The problem isn't globals, the problem is that coordinating usage of shared resources is hard.
>
> But this isn't a technical or linguistic problem. This is a social/political problem, pretty much THE problem.

David is correct.  Our tools (languages, compilers, IDE's, etc.) can
help us avoid many common errors, but they cannot know what we
*intended* when we wrote some code.  Globals are shared resources, so
when they appear in a program, our tools must assume that we wanted to
share them.

On Thu, 8 Jul 2010 09:45:38 -0700, Mark Hamburg <mark@grubmah.com> wrote:
> globals are viewed as "bad" and Lua makes them easy to create. In addition, that ease of
> creation can also hide errors caused by typos.

Right -- It reminds me of when someone quotes the saying that "money
is the root of all evil", when the actual quote is "the love of money
is the root of all evil".  Globals are not bad.  The
unnecessary/inappropriate use of globals is bad.

> P.S. With regard to typos, in addition to detecting inadvertent globals, a lint should perhaps
> also check the names of messages used in message sends...

It is a powerful attribute of Lua that certain "internals" are
exposed, e.g. that environments are tables.  This allows all kinds of
neat tricks, like using metatables to implement "strict" and it also
allows ugly things like this variant of something recently mentioned
on the list:

> foo="print"
> getfenv()[(function() return foo end)()]("Hello, world!")
Hello, world!

In my opinion, large projects (say, more than 10 lines :-) require
static analysis tools that are impossible to use (and I do mean
"uncomputable") in an unmodified Lua.  But it is easy to add
constraints to Lua (again, a strength of the language).

We can use tricks like "strict" to help catch spelling errors; we can
write module systems that generate and maintain static lists of
exports; we can prevent Lua programs from directly accessing their
environment so that tricks based on _G[] and getfenv() cannot foil
static analysis.

On Thu, 8 Jul 2010 13:16:46 -0400, Patrick Donnelly
<batrick@batbytes.com> wrote:
> A major problem Nmap's NSE (Nmap
> Scripting Engine) has had is libraries used by multiple scripts
> accidentally using a global instead of a local. Note that these
> libraries use module so each one has its own environment. Still, all
> our scripts are coroutines so they step on each others' toes when
> setting/getting globals within the library! (For example, an http.get

In Patrick's post, he goes on to implicitly ask why we do not have
compile-time analysis tools to address this problem.  Excellent
question.  A lot of programmers do not write thread-safe code.
Whether they are not in the habit or do not understand how to do it, I
have no idea.

Again, globals are fine, but inappropriate use of globals is clearly a
bad thing!  The http library mentioned should of course have been
written to be thread-safe so that multiple threads can use the library
simultaneously.  All of the per-thread state can be kept in an
(opaque) object that the client thread receives from the library and
passes back to the library.

A truly convenient alternative approach is to add support for
thread-local ("dynamic", "fluid") variables.  I have not tried to do
this (yet) in Lua, but all it requires is the ability to associate a
unique table to each thread.  Presumably, one could create (in C) a
thread metatable that holds a weak population of thread-local variable
tables, indexed by thread.

A function, e.g. "set_fluid(var, value)", can be closed over the
current thread's table and used to set variables there.  A
corresponding "get_fluid(var)" retrieves the value.

Here's how to make the http library thread-safe:  Find all the globals
that should be thread-local, and replace assignments to them with
calls to set_fluid, and accesses with calls to get_fluid.  This cannot
be automated because you have to know which globals really should be
globally shared values and which should be thread-local -- i.e. you
must understand the design and use of the library.

As I have now circled back to David Goehrig's comment about the use of
globals being a "social/political" issue about shared resources, I
shall stop here.

Jim