Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Functional Library
- --
- -- @version 1.0
- --
- -- @file origin: functional.lua, now: underscore.lua
- -- @author Shimomura Ikkei and expanded by Brandon Weaver
- -- @date 2005/05/18, 2014/09/09
- --
- -- @brief porting several convenience functional utilities form Haskell,Python etc..
- -- map(list, function)
- -- e.g: map({1,2,3}, double) -> {2,4,6}
- function map(list, fn)
- local newList = {}
- for i,v in pairs(list) do newList[i] = fn(v) end
- return newList
- end
- -- filter(list, function)
- -- e.g: filter({1,2,3,4}, is_even) -> {2,4}
- function filter(list, fn)
- local newList= {}
- for i,v in pairs(list) do
- if fn(v) then newList[i]=v end
- end
- return newList
- end
- -- head(table)
- -- e.g: head({1,2,3}) -> 1
- function head(list)
- return list[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(list)
- if table.getn(list) < 1 then
- return nil
- else
- local newList = {}
- local listSize = table.getn(list)
- local i = 2
- while (i <= listSize) do
- table.insert(newList, i-1, list[i])
- i = i + 1
- end
- return newList
- end
- end
- -- foldr(function, default_value, table)
- -- e.g: foldr(op.mul, 1, {1,2,3,4,5}) -> 120
- function foldr(fn, val, list)
- for i,v in pairs(list) do val = fn(val, v) end
- return val
- end
- -- reduce(list, function)
- -- e.g: reduce({1,2,3,4}, op.add) -> 10
- function reduce(list, fn)
- return foldr(fn, head(list), tail(list))
- 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(fn, binding_value_for_1st)
- -- bind2(fn, 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(op.mul, 5) -- mul5(10) is 5 * 10
- -- local sub2 = bind2(op.sub, 2) -- sub2(5) is 5 -2
- function bind1(fn, val1)
- return function (val2)
- return fn(val1, val2)
- end
- end
- function bind2(fn, val2) -- bind second argument.
- return function (val1)
- return fn(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
- -- op table.
- -- @see also python's op module.
- op = {
- 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;
- -- additional ops (Brandon)
- _or = function(n,m) return n or m end;
- _nor = function(n,m) return not n or m end;
- _and = function(n,m) return n and m end;
- _xor = function(n,m) return (n or m) and not (n and m) end;
- _xnor = function(n,m) return not ((n or m) and not (n and m)) end;
- _nand = function(n,m) return not n and 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 newList = {}
- local step = bind2(op[(from < to) and "add" or "sub"], 1)
- local val = from
- while val <= to do
- table.insert(newList, table.getn(newList)+1, val)
- val = step(val)
- end
- return newList
- 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(list) -> function(...)
- function expand_args(fn)
- return function(...) return fn(arg) end
- end
- -------------------
- -- Additions by Brandon Weaver
- -- Heavily inspired by Unix and Ruby
- -- dotimes(number, function)
- -- see Ruby's Fixnum#times
- function do_times(n, fn)
- for i = 0, n do fn(i) end
- end
- -- pipe(initial_value, functions...)
- -- see Unix's pipe
- function pipe(...)
- local value = head(arg)
- local tail = tail(arg)
- for i, v in ipairs(tail) do value = v(value) end
- return value
- end
- -- alias for filter
- function select(list, fn)
- return filter(list, fn)
- end
- -- Opposite of select
- function reject(list, fn)
- local newList= {}
- for i,v in pairs(list) do
- if not fn(v) then newList[i] = v end
- end
- return newList
- end
- -- Finds a value in a table, returns false if not present
- function find(list, fn)
- for i, v in pairs(list) do
- if fn(v) then return v end
- end
- return false
- end
- -- Runs a function on each element without explicitly modifying it
- function each(list, fn)
- for i, v in pairs(list) do fn(v) end
- return list
- end
- -- Checks to see that all are true by a function
- function all_are(list, fn)
- return reduce(op._and, map(fn,list))
- end
- -- Opposite of all_are
- function none_are(list, fn)
- return not all_are(list, fn)
- end
- -- Alias for find
- function any_are(list, fn)
- return find(list, fn)
- end
- -- Partitions an array based on a function, returns two arrays, true and false
- function partition(list, fn)
- local true_table = {}
- local false_table = {}
- local partitioner_fn = function(entity)
- if fn(entity) then
- table.insert(true_table, table.getn(true_table)+1, entity)
- else
- table.insert(false_table, table.getn(false_table)+1, entity)
- end
- end
- each(partitioner_fn, list)
- return {true_table, false_table}
- end
- -- Uses Luas pattern matcher to 'grep' for strings
- function grep(pattern, list)
- local pattern_fn = function(str) return string.find(str, pattern) end
- return select(pattern_fn, list)
- end
Advertisement
Add Comment
Please, Sign In to add comment