lua-users home
lua-l archive

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


On Wed, Oct 30, 2002 at 11:25:14AM -0700, C.S. Brooks wrote:
> What do upvalues do? How do they work? Where might I use them?

They are Lua's (pre 5.0) answer to lexical scoping and closures from
functional programming languages. You need them whenever you want to
access a local variable in an outer scope. A common application is,
e.g.:

function dosomething(table)
   local a = 12
   foreach(table, function(key, value) print(key, value + %a) end)
end

The inner function that prints the key and adds 12 to each value
accesses the variable "a" from the outer scope. The only way to do
this in Lua pre-5.0 is by treating "a" as an upvalue.

Another application is for creating function objects. Suppose you have
something like this:

function make_addn(n)
  return function(a)
           return a + %n
         end
end

This is basically the equivalent of a closure in a functional
programming language. make_addn creates a function that adds a fixed
number to its argument. This fixed number is parameterizable. It could
be used like this:

add1 = make_addn(1)
add5 = make_addn(5)

print(add1(3))  --> 4
print(add5(3))  --> 8

Function objects and closures look esoteric on a first glance, but are
in fact an extremely powerful concept. It takes a certain frame of
mind to use them effectively, but once you do, you will start to
wonder how you could live without them before. :-)

In all this it is important to realize that upvalues are evaluated at
the time when you create the function. As a result, they are
immutable. In other words, you cannot assign to them from within the
function.

If an upvalue is a table, you cannot assign a new table to
it. However, you *can* change any entry *inside* that table. This
allows you to create functions that remember a value, much like C's
"static" keyword. In C something like:

int generate_number(void)
{ 
  static int number = 0;
  return number++;
}

would correspond to the following in Lua:

do
  local vars = { number=0 }
  function generate_number()
    local value = %vars.number
    %vars.number = value + 1
    return value
  end
end

I think I've generated enough confusion for now. :-) Lua 5.0 is
supposed to have real lexical scoping, so there should be no need for
special treatment of upvalues anymore.

- Christian