Expression Templates In Lua |
|
Here is an example of using an expression-template-like technique in Lua.
-- Expression object. local expression_mt = {} function Expression(name) return setmetatable( {name=name, eval=function(vars) return vars[name] end}, expression_mt) end local function eval(o, vars) if type(o) == 'table' then return o(vars) else return o end end function expression_mt.__add(a, b) return setmetatable( {eval=function(vars) return eval(a, vars) + eval(b, vars) end}, expression_mt) end function expression_mt.__pow(a, b) return setmetatable( {eval=function(vars) return eval(a, vars) ^ eval(b, vars) end}, expression_mt) end function expression_mt.__call(a, vars) return a.eval(vars) end -- auto-create expression objects from globals local G_mt = {} function G_mt:__index(k) return Expression(k) end setmetatable(_G, G_mt) -- example usage: local function sum(expr, first, last) local result = 0 for x=first,last do result = result + expr{x=x} end return result end print( sum(x^2 + 1, 1, 10) ) --> 395
Compare:
print( sum(x^2 + 1, 1, 10) )
with a more conventional approach:
print( sum(function(x) return x^2 + 1 end, 1, 10) )
In the latter case, the function "function(x) return x^2 + 1 end
" is a black box to the function sum
(bar sum
doing string.dump
on the function and examining bytecodes). sum
can merely invoke the function but cannot see the implementation inside it. In the former case, the individual operations inside x^2 + 1
can be made accessible to sum
.
To illustrate the power of this, the example could be rewritten in order to do symbolic integration on expressions [1]:
print( integral(x^2 + 1) ) --> expression object representing the --- polynomial (1/3)*x^3 + x print( sum(integral(x^2 + 1), 1, 10 ) --> 1063.333...
Note that Lua operations not supporting metamethods (e.g. and
/or
/not
) cannot necessarily be used inside expressions in this technique.