lua-users home
lua-l archive

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


Hi,

with the implementation of full featured lexical scoping in Lua 4.1
I would suggest a change in the semantics of the function statement:

  A function statement with a single identifier as the functions
  name makes the name implicitly local.  That is:

    function name(...

  has the semantic of

    local name
    name = function(...

  The semantics with complex names (x.name etc) stays the same.



The reason I suggest this change is that the current behavior is not
what you would normally expect.  Namely:

  function foo()
    ...
    function bar()
       ...
       bar()
       ...
    end
    ...
    bar()
    ...
  end

While this works as expected, bar becomes a global function and this
is not what you would expect.  It may result in hard to find bugs when
i.e. foo or bar call a function that itself creates a helper function
named bar.  When trying to work around this problem, people may try
this:

  function foo()
    ...
    local bar = function()
       ...
       bar()
       ...
     end
     ...
     bar()
     ...
  end

But this will _not_ work: The local bar will not be visible while the
initialization expression is evaluated so the first (recursive) call
to bar will use the global variable bar while the later call will take
the local bar.  The real solution to this problem is:

  function foo()
    ...
    local bar
    function bar()
      ...
      bar()
      ...
    end
    ...
    bar()
    ...
  end

And IMHO this is what should be the default.  I can't think of very
much cases where you really want a nested function statement to create
a global function.



Now, what about function statements in the top level chunk (main) and
how to define global functions?  One may be tempted to restrict my
proposed change to nested functions.  But I would not do so because
of three reasons: first, by making top level functions local too means
that each file by default will have it's own namespace for functions.
You have to perform explicit actions to export a function.  Second,
access to locals is faster than access to globals.  And at last,
restricting the local behavior to nested functions make the rules
non-uniform, more complicated, and may give other problems.

So, how do you create global functions?  Two methods; either use the
normal assignment syntax:

  foo = function()
    ...
  end

or, what I would prefer, introduce a global variable named 'global'
that holds the global table (global=globals(), exported by baselib)
and then write:

  function global.foo()
    ...
  end

That way you immediately see which functions are local and which are
global.



So, what do you think about this proposal?  Discussion opened :-)

Ciao, ET.