The BASIC interpreter scans the program line by line, starting necessarily with the main program. When it meets a procedure or function name for the first time it starts to look for a program line beginning with DEF followed by its name. If it cannot find it, it raises an error. If it does find it, it links the name and position of the definition into a linked list, for a faster lookup next time. This means that recursive and mutually recursive definitions work without any difficulty.
The Lua interpreter does none of this scanning. So that a variable just has the value nil until it has been assigned a non-nil value. When the interpreter meets a declaration of a local variable it assigns to the variable's name the number of the next free slot on the current chunk's stack. Henceforth only the stack slot is used for referring to the variable's value.
This definition does not work:
local f = \ (a, n) if n <= 0 then => a end => f (n * a, n - 1 ) endbecause f's scope only begins after the statement declaring it local. Instead you must write
local f f = \ (a, n) if n <= 0 then => a end => f (n * a, n - 1 ) endA similar discipline must be observed for mutually recursive functions.
local f, g f = \ ..... g .... end g = \ ..... f .... endThe first time the interpreter meets g its value is nil, but f will not care about this until it is called as a function. By the time either f or g is called each will have its correct value. This is rather like the forward declarations that have to be made in C to implement mutually recursive definitions.
Tables can be used as objects.
local P = { x = 120, y = 300 } P.move = \ (self, a, b) self.x + = a self.y + = b end -- function P:move (10, -50) print (P.x, P.y) --> 130 250We have seen that P.move is just sugar for P [ "move" ]. The colon notation makes
P:move ( a, b)an abbreviation for
P.move ( P, a, b)Note that there is no independent function P:move. Despite this some people refer to P:move as a method for the object P.
We could also have written the code above as
local P = { } do local _ENV = P x, y = 120, 300 move = \ (self, a, b) self.x + = a self.y + = b end -- function show = \ (self) print (self.x, self.y) end -- function end -- do P:move (10, -50) P:show ( ) --> 130 250It comes down to personal preferences in style.
The point of the colon notation is that it puts the table itself within the scopes of function values of the table. I never really got object-oriented programming until I understood how Lua lets you use tables this way.