lua-users home
lua-l archive

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


Hello,

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.

Denis

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

http://spir.wikidot.com/



=======================================================================

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")
    print(expression)
    -- function definition
    local funcbody = "local x = ... ;  return " .. expression
    local func,error = assert(loadstring(funcbody))
    return func
end

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
    else
        error("Map expects a function or (string) formula.")
    end
    -- new sequence
    local newseq = {}
    for _,item in ipairs(seq) do
        newitem = func(item)
        table.insert(newseq, newitem)
    end
    return newseq
end

test = function()
    print "=== number squares"
    numbers = {1,2,3}
    print (table.view(numbers))
    squares = map(numbers, "¤*¤")
    print (table.view(squares))
    print()
    
    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()
    
    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()
    
    print "=== error case"
    numbers = {1,2,3}
    squares = map(numbers, "¤ ¤")
    print (table.view(squares))
end
test()

==>

=== number squares
{1  2  3}
x*x
{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]: ?