lua-users home
lua-l archive

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

Lightroom's code goes through a lint phase based on analyzing the bytecode
looking for globals. We've certainly never found ourselves wanting
local-by-default because of the semantic mess that creates about scopes. I
have on occasion wondered whether the lint notion should somehow migrate
into a compile-time option. In fact, I believe there's been code circulated
here to do so. There are, however, two problems with doing so:

1. You really want it to be optional or else interactive, console-level
programming becomes a real pain. That's not that bad, but it does mean that
we then potentially need a more complicated patch to the compiler.

2. I keep looking at Ruby's expressiveness relative to Lua and I've realized
that some of this comes from being able to execute code blocks in other
environments and access those environments as globals. For example:

    local Foo = makeClass( "Foo", function()

        function method1( self )
            print "Hello"

        function method2( self, x )
            print "Got: " .. x

    end )

(For that matter, makeClass could have populated the environment in which it
was invoked.)

A linter looking for writes to globals, however, would complain about
method1 and method2.

So, I think there may be room to improve the compile-time checks in Lua for
unexpected writes to globals, but local-by-default is not the answer.


P.S. A bigger problem with the above class definition construct is that if
we instead want to call functions that define additional methods, we really
need a way to propagate the environment down or we need to have those
functions become savvy about a table other than the global environment as
the place to add methods. At that point, we might be better off with the
slightly wordier:

    local Foo = makeClass( "Foo", function( T )

        function T:method1()
            print "Hello"

        function T:method2( x )
            print "Got: " .. x

        T:addReadAccessor( "name", "_name" )

    end )

That's not quite as pretty as the Ruby version, but it's close.