[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: "formula" short anonymous func
- From: spir <denis.spir@...>
- Date: Fri, 25 Dec 2009 12:28:47 +0100
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]: ?