lua-users home
lua-l archive

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


2012/11/19 Kevin Martin <kev82@khn.org.uk>:

> Now, I've got into the habit of declaring all functions as local, and I think it's
> messy to declare some functions local, and some with forward declarations.

Each to his own taste. I think it is sloppy not to think carefully about
each function declaration whether it should be explicitly declared as
local.

A local variable is an already-allocated memory slot associated with
a name.  When you use that name, it's in effect translated immediately
to a memory reference.  debug.getlocal still knows what name was in use
for that memory slot when it was allocated, but apart from that the name
is forgotten as soos as the function is loaded.

As soon as you declare that name as local again, it is associated with
a different memory slot. The original name is said to be shadowed.
LuaInspect (which is available as a standalone program or as a gvim
plugin) warns you warns you when you shadow a local name.

Compare these:

function foo()
   local x=1
   local x=2
   print(debug.getlocal(1,1))
   print(debug.getlocal(1,2))
   print(x)
end

function bar()
   local x=1
   do
      local x=2
      print(x)
      print(debug.getlocal(1,1))
      print(debug.getlocal(1,2))
   end
   print(x)
end

> foo()
x	1
x	2
2

> bar()
2
x	1
x	2
1

In the first case, the local variable is not gone, but
you can no longer access it as 'x'.  In the second
case, you get it back when the shadowing variable
goes out of scope.

There are several non-messy habits, depending on
what you wish to achieve.

(a) If you use "local" for the perceived sake of efficiency
(NB it might not always be more efficient, look in the
list archives for a discussion), the neatest solution is
to shun the syntax sugar "local function".  Declare
all local functions first as names without values.
(b) If you use "local" to hide the names from the
surrounding environment, assign all global names that
you may need to local variables, and use the idiom

do _ENV={}
...
end

Inside that do..end bracket, no need to use "local" at all.