Functional Library


 -- Functional Library
 --
 -- @file functional.lua
 -- @author Shimomura Ikkei
 -- @date 2005年05月18日
 --
 -- @brief porting several convenience functional utilities form Haskell,Python etc..

 -- map(function, table)
 -- e.g: map(double, {1,2,3}) -> {2,4,6}
 function map(func, tbl)
 local newtbl = {}
 for i,v in pairs(tbl) do
 newtbl[i] = func(v)
 end
 return newtbl
 end

 -- filter(function, table)
 -- e.g: filter(is_even, {1,2,3,4}) -> {2,4}
 function filter(func, tbl)
 local newtbl= {}
 for i,v in pairs(tbl) do
 if func(v) then
	 newtbl[i]=v
 end
 end
 return newtbl
 end

 -- head(table)
 -- e.g: head({1,2,3}) -> 1
 function head(tbl)
 return tbl[1]
 end
 -- tail(table)
 -- e.g: tail({1,2,3}) -> {2,3}
 --
 -- XXX This is a BAD and ugly implementation.
 -- should return the address to next porinter, like in C (arr+1)
 function tail(tbl)
 if table.getn(tbl) < 1 then
 return nil
 else
 local newtbl = {}
 local tblsize = table.getn(tbl)
 local i = 2
 while (i <= tblsize) do
 table.insert(newtbl, i-1, tbl[i])
 i = i + 1
 end
 return newtbl
 end
 end

 -- foldr(function, default_value, table)
 -- e.g: foldr(operator.mul, 1, {1,2,3,4,5}) -> 120
 function foldr(func, val, tbl)
 for i,v in pairs(tbl) do
 val = func(val, v)
 end
 return val
 end
 -- reduce(function, table)
 -- e.g: reduce(operator.add, {1,2,3,4}) -> 10
 function reduce(func, tbl)
 return foldr(func, head(tbl), tail(tbl))
 end

 -- curry(f,g)
 -- e.g: printf = curry(io.write, string.format)
 -- -> function(...) return io.write(string.format(unpack(arg))) end
 function curry(f,g)
 return function (...)
 return f(g(unpack(arg)))
 end
 end

 -- bind1(func, binding_value_for_1st)
 -- bind2(func, binding_value_for_2nd)
 -- @brief
 -- Binding argument(s) and generate new function.
 -- @see also STL's functional, Boost's Lambda, Combine, Bind.
 -- @examples
 -- local mul5 = bind1(operator.mul, 5) -- mul5(10) is 5 * 10
 -- local sub2 = bind2(operator.sub, 2) -- sub2(5) is 5 -2
 function bind1(func, val1)
 return function (val2)
 return func(val1, val2)
 end
 end
 function bind2(func, val2) -- bind second argument.
 return function (val1)
 return func(val1, val2)
 end
 end

 -- is(checker_function, expected_value)
 -- @brief
 -- check function generator. return the function to return boolean,
 -- if the condition was expected then true, else false.
 -- @example
 -- local is_table = is(type, "table")
 -- local is_even = is(bind2(math.mod, 2), 1)
 -- local is_odd = is(bind2(math.mod, 2), 0)
 is = function(check, expected)
 return function (...)
 if (check(unpack(arg)) == expected) then
 return true
 else
 return false
 end
 end
 end

 -- operator table.
 -- @see also python's operator module.
 operator = {
 mod = math.mod;
 pow = math.pow;
 add = function(n,m) return n + m end;
 sub = function(n,m) return n - m end;
 mul = function(n,m) return n * m end;
 div = function(n,m) return n / m end;
 gt = function(n,m) return n > m end;
 lt = function(n,m) return n < m end;
 eq = function(n,m) return n == m end;
 le = function(n,m) return n <= m end;
 ge = function(n,m) return n >= m end;
 ne = function(n,m) return n ~= m end;
 }

 -- enumFromTo(from, to)
 -- e.g: enumFromTo(1, 10) -> {1,2,3,4,5,6,7,8,9}
 -- TODO How to lazy evaluate in Lua? (thinking with coroutine)
 enumFromTo = function (from,to)
 local newtbl = {}
 local step = bind2(operator[(from < to) and "add" or "sub"], 1)
 local val = from
 while val <= to do
 table.insert(newtbl, table.getn(newtbl)+1, val)
 val = step(val)
 end
 return newtbl
 end

 -- make function to take variant arguments, replace of a table.
 -- this does not mean expand the arguments of function took,
 -- it expand the function's spec: function(tbl) -> function(...)
 function expand_args(func)
 return function(...) return func(arg) end
 end

Sample codes

 local product = bind1(reduce, operator.mul)
 local sum = expand_args(bind1(reduce, operator.add))
 -- @see Python: fact=lambda num: reduce((lambda n,m: n*m), xrange(num,0,-1))
 -- @see Haskell: fact = (foldr (*) 1) . (enumFromTo 1)
 local factorial = curry(product,bind1(enumFromTo,1))


See also: LuaFunctors
RecentChanges · preferences
edit · history
Last edited February 18, 2009 9:44 am GMT (diff)

AltStyle によって変換されたページ (->オリジナル) /