Lemur

functional.lua

Sep 9th, 2014
378
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.29 KB | None | 0 0
  1. -- Functional Library
  2. --
  3. -- @file    functional.lua
  4. -- @author  Shimomura Ikkei and expanded by Brandon Weaver
  5. -- @date    2005/05/18, 2014/09/09
  6. --
  7. -- @brief    porting several convenience functional utilities form Haskell,Python etc..
  8.  
  9. -- map(function, table)
  10. -- e.g: map(double, {1,2,3})    -> {2,4,6}
  11. function map(func, tbl)
  12.   local newtbl = {}
  13.   for i,v in pairs(tbl) do newtbl[i] = func(v) end
  14.   return newtbl
  15. end
  16.  
  17. -- filter(function, table)
  18. -- e.g: filter(is_even, {1,2,3,4}) -> {2,4}
  19. function filter(func, tbl)
  20.   local newtbl= {}
  21.   for i,v in pairs(tbl) do
  22.     if func(v) then newtbl[i]=v end
  23.   end
  24.   return newtbl
  25. end
  26.  
  27. -- head(table)
  28. -- e.g: head({1,2,3}) -> 1
  29. function head(tbl)
  30.   return tbl[1]
  31. end
  32.  
  33. -- tail(table)
  34. -- e.g: tail({1,2,3}) -> {2,3}
  35. --
  36. -- XXX This is a BAD and ugly implementation.
  37. -- should return the address to next porinter, like in C (arr+1)
  38. function tail(tbl)
  39.   if table.getn(tbl) < 1 then
  40.     return nil
  41.   else
  42.     local newtbl = {}
  43.     local tblsize = table.getn(tbl)
  44.     local i = 2
  45.     while (i <= tblsize) do
  46.       table.insert(newtbl, i-1, tbl[i])
  47.       i = i + 1
  48.     end
  49.      return newtbl
  50.   end
  51. end
  52.  
  53. -- foldr(function, default_value, table)
  54. -- e.g: foldr(operator.mul, 1, {1,2,3,4,5}) -> 120
  55. function foldr(func, val, tbl)
  56.   for i,v in pairs(tbl) do val = func(val, v) end
  57.   return val
  58. end
  59.  
  60. -- reduce(function, table)
  61. -- e.g: reduce(operator.add, {1,2,3,4}) -> 10
  62. function reduce(func, tbl)
  63.   return foldr(func, head(tbl), tail(tbl))
  64. end
  65.  
  66. -- curry(f,g)
  67. -- e.g: printf = curry(io.write, string.format)
  68. --          -> function(...) return io.write(string.format(unpack(arg))) end
  69. function curry(f,g)
  70.   return function (...)
  71.     return f(g(unpack(arg)))
  72.   end
  73. end
  74.  
  75. -- bind1(func, binding_value_for_1st)
  76. -- bind2(func, binding_value_for_2nd)
  77. -- @brief
  78. --      Binding argument(s) and generate new function.
  79. -- @see also STL's functional, Boost's Lambda, Combine, Bind.
  80. -- @examples
  81. --      local mul5 = bind1(operator.mul, 5) -- mul5(10) is 5 * 10
  82. --      local sub2 = bind2(operator.sub, 2) -- sub2(5) is 5 -2
  83. function bind1(func, val1)
  84.   return function (val2)
  85.     return func(val1, val2)
  86.   end
  87. end
  88.  
  89. function bind2(func, val2) -- bind second argument.
  90.   return function (val1)
  91.     return func(val1, val2)
  92.   end
  93. end
  94.  
  95. -- is(checker_function, expected_value)
  96. -- @brief
  97. --      check function generator. return the function to return boolean,
  98. --      if the condition was expected then true, else false.
  99. -- @example
  100. --      local is_table = is(type, "table")
  101. --      local is_even = is(bind2(math.mod, 2), 1)
  102. --      local is_odd = is(bind2(math.mod, 2), 0)
  103. is = function(check, expected)
  104.   return function (...)
  105.     if (check(unpack(arg)) == expected) then
  106.       return true
  107.     else
  108.       return false
  109.     end
  110.   end
  111. end
  112.  
  113. -- operator table.
  114. -- @see also python's operator module.
  115. operator = {
  116.   mod = math.mod;
  117.   pow = math.pow;
  118.   add = function(n,m) return n + m end;
  119.   sub = function(n,m) return n - m end;
  120.   mul = function(n,m) return n * m end;
  121.   div = function(n,m) return n / m end;
  122.   gt  = function(n,m) return n > m end;
  123.   lt  = function(n,m) return n < m end;
  124.   eq  = function(n,m) return n == m end;
  125.   le  = function(n,m) return n <= m end;
  126.   ge  = function(n,m) return n >= m end;
  127.   ne  = function(n,m) return n ~= m end;
  128.   -- additional operators (Brandon)
  129.   _or   = function(n,m) return n or m end;
  130.   _nor  = function(n,m) return not n or m end;
  131.   _and  = function(n,m) return n and m end;
  132.   _xor  = function(n,m) return (n or m) and not (n and m) end;
  133.   _xnor = function(n,m) return not ((n or m) and not (n and m)) end;
  134.   _nand = function(n,m) return not n and m end;
  135.  
  136. }
  137.  
  138. -- enumFromTo(from, to)
  139. -- e.g: enumFromTo(1, 10) -> {1,2,3,4,5,6,7,8,9}
  140. -- TODO How to lazy evaluate in Lua? (thinking with coroutine)
  141. enumFromTo = function (from,to)
  142.   local newtbl = {}
  143.   local step = bind2(operator[(from < to) and "add" or "sub"], 1)
  144.   local val = from
  145.   while val <= to do
  146.     table.insert(newtbl, table.getn(newtbl)+1, val)
  147.     val = step(val)
  148.   end
  149.   return newtbl
  150. end
  151.  
  152. -- make function to take variant arguments, replace of a table.
  153. -- this does not mean expand the arguments of function took,
  154. -- it expand the function's spec: function(tbl) -> function(...)
  155. function expand_args(func)
  156.   return function(...) return func(arg) end
  157. end
  158.  
  159. -------------------
  160.  
  161. -- Additions by Brandon Weaver
  162. -- Heavily inspired by Unix and Ruby
  163.  
  164. -- dotimes(number, function)
  165. -- see Ruby's Fixnum#times
  166. function do_times(n, func)
  167.   for i = 0, n do func(i) end
  168. end
  169.  
  170. -- pipe(initial_value, functions...)
  171. -- see Unix's pipe
  172. function pipe(...)
  173.   local value = head(arg)
  174.   local tail  = tail(arg)
  175.  
  176.   for i, v in ipairs(tail) do value = v(value) end
  177.  
  178.   return value
  179. end
  180.  
  181. -- alias for filter
  182. function select(func, tbl)
  183.   return filter(func, tbl)
  184. end
  185.  
  186. -- Opposite of select
  187. function reject(func, tbl)
  188.   local newtbl= {}
  189.   for i,v in pairs(tbl) do
  190.     if not func(v) then newtbl[i] = v end
  191.   end
  192.   return newtbl
  193. end
  194.  
  195. -- Finds a value in a table, returns false if not present
  196. function find(func, tbl)
  197.   for i, v in pairs(tbl) do
  198.     if func(v) then return v end
  199.   end
  200.  
  201.   return false
  202. end
  203.  
  204. -- Runs a function on each element without explicitly modifying it
  205. function each(func, tbl)
  206.   for i, v in pairs(tbl) do func(v) end
  207.  
  208.   return tbl
  209. end
  210.  
  211. -- Checks to see that all are true by a function
  212. function all_are(func, tbl)
  213.   return reduce(operator._and, map(func,tbl))
  214. end
  215.  
  216. -- Opposite of all_are
  217. function none_are(func, tbl)
  218.   return not all_are(func, tbl)
  219. end
  220.  
  221. -- Alias for find
  222. function any_are(func, tbl)
  223.   return find(func, tbl)
  224. end
  225.  
  226. -- Partitions an array based on a function, returns two arrays, true and false
  227. function partition(func, tbl)
  228.   local true_table  = {}
  229.   local false_table = {}
  230.  
  231.   local partitioner_fn = function(entity)
  232.     if func(entity) then
  233.       table.insert(true_table, table.getn(true_table)+1, entity)
  234.     else
  235.       table.insert(false_table, table.getn(false_table)+1, entity)
  236.     end
  237.   end
  238.  
  239.   each(partitioner_fn, tbl)
  240.  
  241.   return {true_table, false_table}
  242. end
  243.  
  244. -- Uses Luas pattern matcher to 'grep' for strings
  245. function grep(pattern, tbl)
  246.   local pattern_fn = function(str) return string.find(str, pattern) end
  247.  
  248.   return select(pattern_fn, tbl)
  249. end
Advertisement
Add Comment
Please, Sign In to add comment