lua-users home
lua-l archive

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


This is an attempt at solving the here often debated issue of short anonymous funcs such as 
    x --> x * x
    function(x) return x * x end
in a simplistic manner, in the case where a single variable is in play. This is rather intended to be used in higher-order funcs such as map or filter.

'formula' uses loadstring to construct a func from a string definition of the formula, in which a placeholder character (default: '¤') stands for the variable.
A higher-order func can easily call formula in case it is passed a string instead of a func.

See code below. Maybe some of you find this pattern useful.


PS: For any reason, I do not like cases like 'formulafunc' below where I'm forced to define an ambiguous parameter like 'formulafunc' in map below. Even if naming can somewhat help, some part of my brain feels it -stinks- smells. But I know of no clean way to handle such cases: hints welcome.

la vita e estrany


formula = function (expression, placeholder)
    --[[ func corresponding to given formula string --]]
    -- 'placeholder' stands for variable, typically sequence item
    if not placeholder then placeholder = '¤' end
    expression = string.gsub(expression, placeholder, "x")
    -- function definition
    local funcbody = "local x = ... ;  return " .. expression
    local func,error = assert(loadstring(funcbody))
    return func

map = function(seq, formulafunc, placeholder)
    --[[ new sequence resulting of mapping formula/func on seq --]]
    -- actual func
    local func
    if type(formulafunc) == "string" then
        func = formula(formulafunc, placeholder)
    elseif type(formulafunc) == "function" then
        func = formulafunc
        error("Map expects a function or (string) formula.")
    -- new sequence
    local newseq = {}
    for _,item in ipairs(seq) do
        newitem = func(item)
        table.insert(newseq, newitem)
    return newseq

test = function()
    print "=== number squares"
    numbers = {1,2,3}
    print (table.view(numbers))
    squares = map(numbers, "¤*¤")
    print (table.view(squares))
    print "=== with slot access"
    require "math"
    points = {{x=1,y=2}, {x=3,y=4}, {x=5,y=6}}
    print (table.view(points,true))
    distances = map(points, "math.sqrt(¤.x*¤.x + ¤.y*¤.y)")
    print (table.view(distances))
    print "=== case direct func"
    numbers = {1,2,3}
    print (table.view(numbers))
    squares = map(numbers, function(x) return x*x end)
    print ("function(x) return x*x end")
    print (table.view(squares))
    print "=== error case"
    numbers = {1,2,3}
    squares = map(numbers, "¤ ¤")
    print (table.view(squares))


=== number squares
{1  2  3}
{1  4  9}

=== with slot access
{{y:2  x:1}  {y:4  x:3}  {y:6  x:5}}
math.sqrt(x.x*x.x + x.y*x.y)
{2.2360679774998  5  7.8102496759067}

=== case direct func
{1  2  3}
function(x) return x*x end
{1  4  9}

=== error case
x x
lua: formulaMap.lua:31: [string "local x = ... ;  return x x"]:1: '<eof>' expected near 'x'
stack traceback:
    [C]: in function 'assert'
    formulaMap.lua:31: in function 'formula'
    formulaMap.lua:40: in function 'map'
    formulaMap.lua:80: in function 'test'
    formulaMap.lua:83: in main chunk
    [C]: ?