lua-users home
lua-l archive

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


Hi,

John Belmonte wrote:
> So what went wrong with this design?  The problem relates to upvalues, which
> are being used to emulate local namespaces for the modules.  Lua only allows
> upvalue access to the next outer scope.  This prevents the following:
> 
>     function m.func()
>         local test1 = function()
>             %m.hey = 10  --error
>         end
>     end

Right.  This _is_ annoying.

>  There is a workaround, but it can hardly be considered acceptable:
> 
>     function m.func()
>         local m2 = %m			[btw,  local m = %m  works, too]
>         local test2 = function()
>             %m2.hey = 10
>         end
>     end

I made a patch for lua 4.0a that allows upvalues to access locals in outer
scopes.  Semantically it does just what you did by hand, that is inserting
a "local foo=%foo" (but without actually creating the intermediate local).
Everything else stays the same.  You can find the patch at
http://user.exit.de/froese/lua/upvalue-4a-patch

I ask the designers to look at the patch and include it into the final 4.0
version.  It's fully backwards compatible, makes the upvalue handling more
orthogonal, fits pretty well into the parser, and removes this annoying
restriction.


> I think that with the recent issues brought up regarding the upvalue
> concept, it's an area of the language that warrants research into
> improvement.

I totally agree.  But if it were that easy... ;-)

> So is lexical scoping (binding variables at parse time) incompatible with
> the goals of Lua?

Well, I think one goal of Lua is speed and in this sense - yes.
It's a problem with the lifetime of locals.  With strict lexical scoping lua
has to do the equivalent of:

   function foo(...)
     local shared_foo = { local1=1, local2=2 }
     function bar(...)
       local shared_bar = { local1=11, local2=22 }
       %shared_foo.local1 = ...
       function baz(...)
         %shared_foo.local1 =...
         %shared_bar.local2 =...
   ...

And that is very expensive - every call of foo/bar has to create a gc'ed
object.  I've found no way how to make this lighter.

In the moment I'm thinking about a different method: only allow access to
the locals as long as they live.  That is, generate a run time error if a
function tries to access an outer local that no longer exists.  Maybe that
this limitation helps...

Please note:  IMO, even if we could find a proper way to implement lexical
scoping that would not make the upvalue concept obsolete.  It's a different
thing and has its use.

Ciao, ET.