lua-users home
lua-l archive

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


Ivan-Assen Ivanov <ivanassen <at> gmail.com> writes:

> throughout our code we frequently use the following construct:
> 
> foobar( function() ..... end )
> 
> where the anonymous function body is often very small.

Here's something that's only slightly insane:

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

F = setmetatable({}, { __index = function (t,k)
  local functionDef = "return function " .. 
                      string.gsub(k, "%)", ") return ", 1) .. 
                      " end"
  t[k] = assert(loadstring(functionDef))()
  return t[k]
end })

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

double = F["(x) 2*x"]
assert( double(7) == 14)

add = F["(x,y) x + y"]
assert( add(1,2) == 3 )

add2 = F["(x,y) x + y"]
assert( add == add2 )

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

-- An even more streamlined syntax, at some efficiency cost:

function L (s)  return F[s]  end

multiply = L"(x,y) x * y"
assert( multiply(3,4) == 12 )

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

In general:

  F["(parameters) expression"]

turns into:

  function (parameters) return expression end
  
The disadvantage, obviously, is that you can't use external local
variables.  But a significant advantage is that these anonymous
functions are *cached*, as shown in the add2 example above.
Normally, if you write

  function calledManyTimes ()
    foobar( function (a,b) return a + b end )
  end
  
a new closure will be allocated every time calledManyTimes is called,
even though the anonymous function doesn't actually close over anything.
F["(a,b) a + b"] only allocates the first time.

-Bret