From fa0d3f641d21f3d3a17edd8f4945e6d103a16fdd Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 3 Feb 2015 13:28:09 +0100 Subject: [PATCH 01/21] Added simple_reduce and multi_map. Read comments for more information. --- lib/underscore.lua | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lib/underscore.lua b/lib/underscore.lua index 7415190..7aac133 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -225,6 +225,59 @@ function Underscore.funcs.sort(iter, comparison_func) return array end +-- usage: simple_reduce({...}, callback), where callback = function(x, y) end +-- simplifies a reduce function by ditching the memo base case +-- @param list_or_iter, following the underscoreLua specs +-- @param func, a callback of the form x -> y -> z +-- returns a list +Underscore.funcs.simple_reduce = (function() + local inner + inner = function(iter, func, accumulator) + local value = iter() + if value then + accumulator.value = func(accumulator.value, value) + inner(iter, func, accumulator) + end + end + local red = function(list_or_iter, func) + local accumulator = {} + local iter = Underscore.iter(list_or_iter) + accumulator.value = iter() + inner(iter, func, accumulator) + return accumulator.value + end + return red +end)() + +-- usage: multi_map({{...}, {...}, ...}, callback), where callback = function() end +-- provides a map function for an arbitrary number of lists and/or iterators +-- @param lists_or_iters, a list of lists and/or iterators following the underscoreLua specs +-- @param func, a callback that takes the same amount of arguments as there are items in lists_or_iters +-- the function stops execution immediately upon finding a nil value in any of the items in each of the lists_or_iters +-- the use of iterators or lists with holes is therefore discouraged, a very useful side-effect of this behaviour is that +-- the function will cater itself towards the iterator or list with the least amout of items +-- returns a list +Underscore.funcs.multi_map = (function() + local inner + inner = function(iters, func, accumulator) + local args = {} + local arg + if Underscore.funcs.detect(iters, function(iter) + arg = iter() + table.insert(args, arg) + return not arg end) then return end + table.insert(accumulator, func(unpack(args))) + inner(iters, func, accumulator) + end + local multi_map = function(lists_or_iters, func) + local accumulator = {} + local iters = Underscore.funcs.map(lists_or_iters, Underscore.iter) + inner(iters, func, accumulator) + return accumulator + end + return multi_map +end)() + -- arrays function Underscore.funcs.first(array, n) From 7ece171fc67292abda865cadc1993c00342a5c71 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 3 Feb 2015 16:53:19 +0100 Subject: [PATCH 02/21] Made more idiomatic. --- lib/underscore.lua | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 7aac133..be9a9bf 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -227,46 +227,46 @@ end -- usage: simple_reduce({...}, callback), where callback = function(x, y) end -- simplifies a reduce function by ditching the memo base case --- @param list_or_iter, following the underscoreLua specs --- @param func, a callback of the form x -> y -> z --- returns a list +-- @param : list_or_iter, following the underscoreLua specs +-- @param : func, a callback of the form x -> y -> z +-- @return : a list Underscore.funcs.simple_reduce = (function() local inner inner = function(iter, func, accumulator) - local value = iter() - if value then - accumulator.value = func(accumulator.value, value) + local _ = iter() + if _ then + accumulator.value = func(accumulator.value, _) inner(iter, func, accumulator) end end - local red = function(list_or_iter, func) + local simple_reduce = function(list_or_iter, func) local accumulator = {} local iter = Underscore.iter(list_or_iter) accumulator.value = iter() inner(iter, func, accumulator) return accumulator.value end - return red + return simple_reduce end)() -- usage: multi_map({{...}, {...}, ...}, callback), where callback = function() end -- provides a map function for an arbitrary number of lists and/or iterators --- @param lists_or_iters, a list of lists and/or iterators following the underscoreLua specs --- @param func, a callback that takes the same amount of arguments as there are items in lists_or_iters +-- @param : lists_or_iters, a list of lists and/or iterators following the underscoreLua specs +-- @param : func, a callback that takes the same amount of arguments as there are items in lists_or_iters -- the function stops execution immediately upon finding a nil value in any of the items in each of the lists_or_iters -- the use of iterators or lists with holes is therefore discouraged, a very useful side-effect of this behaviour is that -- the function will cater itself towards the iterator or list with the least amout of items --- returns a list +-- @return : a list Underscore.funcs.multi_map = (function() local inner inner = function(iters, func, accumulator) - local args = {} - local arg + local _ + local _s = {} if Underscore.funcs.detect(iters, function(iter) - arg = iter() - table.insert(args, arg) - return not arg end) then return end - table.insert(accumulator, func(unpack(args))) + _ = iter() + table.insert(_s, _) + return not _ end) then return end + table.insert(accumulator, func(unpack(_s))) inner(iters, func, accumulator) end local multi_map = function(lists_or_iters, func) From 4d0a00a03cac3122492f75b2337e2bc8f46b5152 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 3 Feb 2015 17:01:04 +0100 Subject: [PATCH 03/21] Fixed a typo. --- lib/underscore.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index be9a9bf..956e8e6 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -228,7 +228,7 @@ end -- usage: simple_reduce({...}, callback), where callback = function(x, y) end -- simplifies a reduce function by ditching the memo base case -- @param : list_or_iter, following the underscoreLua specs --- @param : func, a callback of the form x -> y -> z +-- @param : func, a callback of the form x -> y -> list of z -- @return : a list Underscore.funcs.simple_reduce = (function() local inner @@ -255,7 +255,7 @@ end)() -- @param : func, a callback that takes the same amount of arguments as there are items in lists_or_iters -- the function stops execution immediately upon finding a nil value in any of the items in each of the lists_or_iters -- the use of iterators or lists with holes is therefore discouraged, a very useful side-effect of this behaviour is that --- the function will cater itself towards the iterator or list with the least amout of items +-- the function will cater itself towards the iterator or list with the least amount of items -- @return : a list Underscore.funcs.multi_map = (function() local inner From c155bc015d0f7f0f9f7bcdf7d51b79c060916072 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Sat, 7 Feb 2015 19:47:40 +0100 Subject: [PATCH 04/21] Added a universal table iterator. Replaced a detect call with all call in multi_map. --- lib/underscore.lua | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 956e8e6..34246f0 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -59,6 +59,14 @@ function Underscore.range(start_i, end_i, step) return Underscore:new(range_iter) end +-- adds a universal table iterator +Underscore.table_iterator = function(table) + return coroutine.wrap(function() + for key, value in pairs(table) do + coroutine.yield({key = key, value = value}) end + end) +end + --- Identity function. This function looks useless, but is used throughout Underscore as a default. -- @name _.identity -- @param value any object @@ -262,12 +270,12 @@ Underscore.funcs.multi_map = (function() inner = function(iters, func, accumulator) local _ local _s = {} - if Underscore.funcs.detect(iters, function(iter) + if Underscore.funcs.all(iters, function(iter) _ = iter() table.insert(_s, _) - return not _ end) then return end + return _ end) then table.insert(accumulator, func(unpack(_s))) - inner(iters, func, accumulator) + inner(iters, func, accumulator) end end local multi_map = function(lists_or_iters, func) local accumulator = {} From b38fbcb2bc3d8836569b612cccb398b5be4beabc Mon Sep 17 00:00:00 2001 From: alex-dolinsky Date: Sat, 7 Feb 2015 19:55:33 +0100 Subject: [PATCH 05/21] A quck summary of changes. Explanation for the simple_reduce, multi_map and table_iterator. --- readme.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 0d71e2a..6bf8e13 100644 --- a/readme.txt +++ b/readme.txt @@ -1 +1,11 @@ -A Lua version of http://documentcloud.github.com/underscore/, see http://mirven.github.com/underscore.lua/ for more information. \ No newline at end of file +A Lua version of http://documentcloud.github.com/underscore/, see http://mirven.github.com/underscore.lua/ for more information. + +Contains three additions to the core underscore.lua: simple_reduce, multi_map and table_iterator. + +simple_reduce doesn't require a base case, it uses the first yield of an iterator passed to it instead. + +multi_map can be used on a list of lists of indefinite length, with a callback given having +a number of arguments equal to the number of iterators in the list of iterators. This function +caters to the iterator with the least amount of yields. + +table_iterator is a simple iterator to run through a table, it yields a key-value pair as a table. From e5f3ebf4de5ae83c2cdcf8cc538a44a6d5fb1930 Mon Sep 17 00:00:00 2001 From: alex-dolinsky Date: Sat, 7 Feb 2015 19:57:19 +0100 Subject: [PATCH 06/21] Fixed the formatting It looked ugly... --- readme.txt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/readme.txt b/readme.txt index 6bf8e13..16f2e15 100644 --- a/readme.txt +++ b/readme.txt @@ -2,10 +2,13 @@ A Lua version of http://documentcloud.github.com/underscore/, see http://mirven. Contains three additions to the core underscore.lua: simple_reduce, multi_map and table_iterator. -simple_reduce doesn't require a base case, it uses the first yield of an iterator passed to it instead. +simple_reduce doesn't require a base case, +it uses the first yield of an iterator passed to it instead. -multi_map can be used on a list of lists of indefinite length, with a callback given having -a number of arguments equal to the number of iterators in the list of iterators. This function -caters to the iterator with the least amount of yields. +multi_map can be used on a list of lists of indefinite length, +with a callback given having a number of arguments equal +to the number of iterators in the list of iterators. +This function caters to the iterator with the least amount of yields. -table_iterator is a simple iterator to run through a table, it yields a key-value pair as a table. +table_iterator is a simple iterator to run through a table, +it yields a key-value pair as a table. From 9ad09e02493425636ab5083870ec4c74180c7482 Mon Sep 17 00:00:00 2001 From: alex-dolinsky Date: Sat, 7 Feb 2015 19:58:15 +0100 Subject: [PATCH 07/21] Fixed the formatting again... Still looked ugly... --- readme.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 16f2e15..27d4a89 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,7 @@ A Lua version of http://documentcloud.github.com/underscore/, see http://mirven.github.com/underscore.lua/ for more information. -Contains three additions to the core underscore.lua: simple_reduce, multi_map and table_iterator. +This fork contains three additions to the core underscore.lua: +simple_reduce, multi_map and table_iterator. simple_reduce doesn't require a base case, it uses the first yield of an iterator passed to it instead. From 1bd76e09ff63f2b389b73c47ea4967297ef14f65 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Sun, 8 Feb 2015 13:50:20 +0100 Subject: [PATCH 08/21] Adjusted the recursion to incorporate proper tail calls. --- lib/underscore.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 34246f0..20f0938 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -244,7 +244,7 @@ Underscore.funcs.simple_reduce = (function() local _ = iter() if _ then accumulator.value = func(accumulator.value, _) - inner(iter, func, accumulator) + return inner(iter, func, accumulator) end end local simple_reduce = function(list_or_iter, func) @@ -275,7 +275,7 @@ Underscore.funcs.multi_map = (function() table.insert(_s, _) return _ end) then table.insert(accumulator, func(unpack(_s))) - inner(iters, func, accumulator) end + return inner(iters, func, accumulator) end end local multi_map = function(lists_or_iters, func) local accumulator = {} From 0ffa8c153f3876e167197e887e9a33f77a936360 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Sun, 22 Mar 2015 17:47:44 +0100 Subject: [PATCH 09/21] Added each_while and each_untill. --- lib/underscore.lua | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 20f0938..f6694ae 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -244,16 +244,14 @@ Underscore.funcs.simple_reduce = (function() local _ = iter() if _ then accumulator.value = func(accumulator.value, _) - return inner(iter, func, accumulator) - end + return inner(iter, func, accumulator) end end local simple_reduce = function(list_or_iter, func) local accumulator = {} local iter = Underscore.iter(list_or_iter) accumulator.value = iter() inner(iter, func, accumulator) - return accumulator.value - end + return accumulator.value end return simple_reduce end)() @@ -281,11 +279,27 @@ Underscore.funcs.multi_map = (function() local accumulator = {} local iters = Underscore.funcs.map(lists_or_iters, Underscore.iter) inner(iters, func, accumulator) - return accumulator - end + return accumulator end return multi_map end)() +Underscore.funcs.each_while = (function() + local each_while = function (lists_or_iters, func, predicate) + func = Underscore.funcs.wrap(func, function(callback, ...) + local go = predicate(...) + if go then callback(...) end + return go end) + Underscore.funcs.all(lists_or_iters, func) end + return each_while +end)() + +Underscore.funcs.each_untill = (function() + local each_untill = function (lists_or_iters, func, predicate) + predicate = Underscore.funcs.negate(predicate) + Underscore.funcs.each_while(lists_or_iters, func, predicate) end + return each_untill +end)() + -- arrays function Underscore.funcs.first(array, n) @@ -441,6 +455,14 @@ function Underscore.funcs.curry(func, argument) end end +Underscore.funcs.negate = (function() + local negate = function (predicate) + predicate = Underscore.funcs.wrap(predicate, function(callback, ...) + return not callback(...) end) + return predicate end + return negate +end)() + function Underscore.functions() return Underscore.keys(Underscore.funcs) end From 47239ce88d05834b4e502d48b493cbc5f241c80c Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Sun, 22 Mar 2015 17:50:49 +0100 Subject: [PATCH 10/21] Simplified simple_reduce. --- lib/underscore.lua | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index f6694ae..536592b 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -239,19 +239,10 @@ end -- @param : func, a callback of the form x -> y -> list of z -- @return : a list Underscore.funcs.simple_reduce = (function() - local inner - inner = function(iter, func, accumulator) - local _ = iter() - if _ then - accumulator.value = func(accumulator.value, _) - return inner(iter, func, accumulator) end - end local simple_reduce = function(list_or_iter, func) - local accumulator = {} local iter = Underscore.iter(list_or_iter) - accumulator.value = iter() - inner(iter, func, accumulator) - return accumulator.value end + local _ = iter() + return Underscore.funcs.reduce(iter, _, func) end return simple_reduce end)() From aae806b415b1f73014948ff750bf4b8a546eb267 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Sun, 22 Mar 2015 18:36:56 +0100 Subject: [PATCH 11/21] An effort to convert underscore to properly recursive library, ditching the for-loops. Also use internal functions where appropriate, embracing reuse. --- lib/underscore.lua | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 536592b..702ab43 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -90,12 +90,19 @@ end -- iter -function Underscore.funcs.each(list, func) - for i in Underscore.iter(list) do - func(i) +Underscore.funcs.each = (function() + local inner + inner = function(iter, func) + local _ = iter() + if _ then + func(_) + return inner(iter, func) end end - return list -end + local each = function(list_or_iter, func) + inner(Underscore.iter(list_or_iter), func) + return list_or_iter end + return each +end)() function Underscore.funcs.map(list, func) local mapped = {} @@ -218,9 +225,7 @@ end function Underscore.funcs.reverse(list) local reversed = {} - for i in Underscore.iter(list) do - table.insert(reversed, 1, i) - end + Underscore.funcs.each(list, function(item) table.insert(reversed, 1, item) end) return reversed end From 27da7cbb72aac06b105ca12cf6ad54428cd62266 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Mon, 23 Mar 2015 20:02:46 +0100 Subject: [PATCH 12/21] Added detect_predicate and compacted the code a little. --- lib/underscore.lua | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 702ab43..b980554 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -126,6 +126,16 @@ function Underscore.funcs.detect(list, func) return nil end +Underscore.funcs.detect_predicate = (function() + local detect_predicate = function(list, func) + local condition + Underscore.funcs.any(list, Underscore.funcs.wrap(func, function(callback, item) + condition = callback(item) + return condition end)) + return condition + end + return detect_predicate end)() + function Underscore.funcs.select(list, func) local selected = {} for i in Underscore.iter(list) do @@ -248,8 +258,7 @@ Underscore.funcs.simple_reduce = (function() local iter = Underscore.iter(list_or_iter) local _ = iter() return Underscore.funcs.reduce(iter, _, func) end - return simple_reduce -end)() + return simple_reduce end)() -- usage: multi_map({{...}, {...}, ...}, callback), where callback = function() end -- provides a map function for an arbitrary number of lists and/or iterators @@ -276,8 +285,7 @@ Underscore.funcs.multi_map = (function() local iters = Underscore.funcs.map(lists_or_iters, Underscore.iter) inner(iters, func, accumulator) return accumulator end - return multi_map -end)() + return multi_map end)() Underscore.funcs.each_while = (function() local each_while = function (lists_or_iters, func, predicate) @@ -286,15 +294,13 @@ Underscore.funcs.each_while = (function() if go then callback(...) end return go end) Underscore.funcs.all(lists_or_iters, func) end - return each_while -end)() + return each_while end)() Underscore.funcs.each_untill = (function() local each_untill = function (lists_or_iters, func, predicate) predicate = Underscore.funcs.negate(predicate) Underscore.funcs.each_while(lists_or_iters, func, predicate) end - return each_untill -end)() + return each_untill end)() -- arrays @@ -456,8 +462,7 @@ Underscore.funcs.negate = (function() predicate = Underscore.funcs.wrap(predicate, function(callback, ...) return not callback(...) end) return predicate end - return negate -end)() + return negate end)() function Underscore.functions() return Underscore.keys(Underscore.funcs) From 553a8ca00654fb251a9d459f3dda60c7d8d7bae0 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Thu, 26 Mar 2015 11:41:05 +0100 Subject: [PATCH 13/21] Added zip and the temporary rangeV2, that serves as a work-around for the broken original. Will fix it properly in due time and replace the latter. --- lib/underscore.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/underscore.lua b/lib/underscore.lua index b980554..8b69dc5 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -59,6 +59,19 @@ function Underscore.range(start_i, end_i, step) return Underscore:new(range_iter) end +function Underscore.rangeV2(start_i, end_i, step) + if end_i == nil then + end_i = start_i + start_i = 1 + end + step = step or 1 + return coroutine.wrap(function() + for i=start_i, end_i, step do + coroutine.yield(i) + end + end) +end + -- adds a universal table iterator Underscore.table_iterator = function(table) return coroutine.wrap(function() @@ -287,6 +300,14 @@ Underscore.funcs.multi_map = (function() return accumulator end return multi_map end)() +-- our classic zip function, has almost the same signature as multi-map, but omits the callback +Underscore.funcs.zip = (function() + local zip = function (lists_or_iters) + return Underscore.funcs.multi_map(lists_or_iters, function(...) return {...} end) + end + return zip +end)() + Underscore.funcs.each_while = (function() local each_while = function (lists_or_iters, func, predicate) func = Underscore.funcs.wrap(func, function(callback, ...) From 4a16cab5fe52717651997c36e4b818759a1094c6 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Mon, 30 Mar 2015 14:19:50 +0200 Subject: [PATCH 14/21] Added multi_curry. --- lib/underscore.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/underscore.lua b/lib/underscore.lua index 8b69dc5..157374d 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -478,6 +478,14 @@ function Underscore.funcs.curry(func, argument) end end +Underscore.funcs.multi_curry = (function() + local multi_curry = function (func, ...) + Underscore.funcs.each ({...}, function (arg) func = Underscore.funcs.curry(func, arg) end) + return function(...) return func(...) end + end + return multi_curry +end)() + Underscore.funcs.negate = (function() local negate = function (predicate) predicate = Underscore.funcs.wrap(predicate, function(callback, ...) From a758dcb2f382c3ab3dcbfc14de9e1b7d5644c03b Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 31 Mar 2015 18:12:51 +0200 Subject: [PATCH 15/21] A more elegant to_array, --- lib/underscore.lua | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 157374d..28cdf84 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -238,13 +238,11 @@ function Underscore.funcs.max(list, func) end).item end -function Underscore.funcs.to_array(list) - local array = {} - for i in Underscore.iter(list) do - array[#array+1] = i - end - return array -end +Underscore.funcs.to_array = (function () + return function (iter) + return Underscore.funcs.map (iter, function (item) return item end) + end +end)() function Underscore.funcs.reverse(list) local reversed = {} From 26d4ec7ba704d68ef85364caa42b22bb21d9e1e8 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 31 Mar 2015 18:29:20 +0200 Subject: [PATCH 16/21] Formatting. --- lib/underscore.lua | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 28cdf84..9932810 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -147,7 +147,8 @@ Underscore.funcs.detect_predicate = (function() return condition end)) return condition end - return detect_predicate end)() + return detect_predicate +end)() function Underscore.funcs.select(list, func) local selected = {} @@ -269,7 +270,8 @@ Underscore.funcs.simple_reduce = (function() local iter = Underscore.iter(list_or_iter) local _ = iter() return Underscore.funcs.reduce(iter, _, func) end - return simple_reduce end)() + return simple_reduce +end)() -- usage: multi_map({{...}, {...}, ...}, callback), where callback = function() end -- provides a map function for an arbitrary number of lists and/or iterators @@ -296,7 +298,8 @@ Underscore.funcs.multi_map = (function() local iters = Underscore.funcs.map(lists_or_iters, Underscore.iter) inner(iters, func, accumulator) return accumulator end - return multi_map end)() + return multi_map +end)() -- our classic zip function, has almost the same signature as multi-map, but omits the callback Underscore.funcs.zip = (function() @@ -313,13 +316,15 @@ Underscore.funcs.each_while = (function() if go then callback(...) end return go end) Underscore.funcs.all(lists_or_iters, func) end - return each_while end)() + return each_while +end)() Underscore.funcs.each_untill = (function() local each_untill = function (lists_or_iters, func, predicate) predicate = Underscore.funcs.negate(predicate) Underscore.funcs.each_while(lists_or_iters, func, predicate) end - return each_untill end)() + return each_untill +end)() -- arrays @@ -489,7 +494,8 @@ Underscore.funcs.negate = (function() predicate = Underscore.funcs.wrap(predicate, function(callback, ...) return not callback(...) end) return predicate end - return negate end)() + return negate +end)() function Underscore.functions() return Underscore.keys(Underscore.funcs) From e9e4d930d29c2613f8a763a0748f44d0ab71f0ed Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 31 Mar 2015 18:43:38 +0200 Subject: [PATCH 17/21] Added append function. --- lib/underscore.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 9932810..21d0775 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -384,6 +384,14 @@ function Underscore.funcs.pop(array) return table.remove(array) end +Underscore.funcs.append = (function () + return function (array, ...) + local acc = {unpack (array)} + Underscore.funcs.each ({...}, function (item) Underscore.funcs.push (acc, item) end) + return acc + end +end)() + function Underscore.funcs.shift(array) return table.remove(array, 1) end @@ -533,7 +541,7 @@ local function wrap_functions_for_oo_support() Underscore[fn] = function(obj_or_self, ...) local obj, chained = value_and_chained(obj_or_self) return value_or_wrap(func(obj, ...), chained) - end + end end end From 23a65a59168cb01ac65d6f7820e5a52399ee2410 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 31 Mar 2015 18:46:03 +0200 Subject: [PATCH 18/21] Fixed compose. --- lib/underscore.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 21d0775..9077704 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -128,7 +128,7 @@ end function Underscore.funcs.reduce(list, memo, func) for i in Underscore.iter(list) do memo = func(memo, i) - end + end return memo end @@ -465,7 +465,7 @@ end function Underscore.funcs.compose(...) local function call_funcs(funcs, ...) if #funcs > 1 then - return funcs[1](call_funcs(_.rest(funcs), ...)) + return funcs[1](call_funcs(Underscore.funcs.rest(funcs), ...)) else return funcs[1](...) end @@ -505,7 +505,7 @@ Underscore.funcs.negate = (function() return negate end)() -function Underscore.functions() +function Underscore.functions() return Underscore.keys(Underscore.funcs) end @@ -541,7 +541,7 @@ local function wrap_functions_for_oo_support() Underscore[fn] = function(obj_or_self, ...) local obj, chained = value_and_chained(obj_or_self) return value_or_wrap(func(obj, ...), chained) - end + end end end From 83980f29c0a1f5d363a5fbde3342966ad436b433 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Tue, 7 Apr 2015 09:48:08 +0200 Subject: [PATCH 19/21] Added destructive_append (for performance reasons in append_all) and flatten_once. --- lib/underscore.lua | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/underscore.lua b/lib/underscore.lua index 9077704..fab98d6 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -386,12 +386,35 @@ end Underscore.funcs.append = (function () return function (array, ...) - local acc = {unpack (array)} + local acc = {unpack (array)} -- identity, abstract away later Underscore.funcs.each ({...}, function (item) Underscore.funcs.push (acc, item) end) return acc end end)() +Underscore.funcs.destructive_append = (function () + return function (array, ...) + Underscore.funcs.each ({...}, function (item) Underscore.funcs.push (array, item) end) + return array + end +end)() + +Underscore.funcs.append_all = (function () + return function (array, ...) + local acc = {unpack (array)} -- identity, abstract away later + Underscore.funcs.each ({...}, function (item) Underscore.funcs.destructive_append (acc, unpack (item)) end) + return acc + end +end)() + +Underscore.funcs.flatten_once = (function () + return function (array) + if Underscore.funcs.is_empty (array) then return array end + local _ = Underscore.funcs.first (array) + if #array == 1 then return _ end + return Underscore.funcs.append_all (_, unpack (Underscore.funcs.rest (array))) end +end)() + function Underscore.funcs.shift(array) return table.remove(array, 1) end From 3153a09dee746e803e51a491d7abe39235a95b8d Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Thu, 9 Apr 2015 14:27:28 +0200 Subject: [PATCH 20/21] Added safe_each. --- lib/underscore.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/underscore.lua b/lib/underscore.lua index fab98d6..ab02057 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -415,6 +415,10 @@ Underscore.funcs.flatten_once = (function () return Underscore.funcs.append_all (_, unpack (Underscore.funcs.rest (array))) end end)() +Underscore.funcs.safe_each = (function () + return function (list, func) return Underscore.funcs.each (Underscore.rangeV2 (1, #list), func) end +end)() + function Underscore.funcs.shift(array) return table.remove(array, 1) end From 6755e4ba7b5ec0d3c839081bbacad591785b7dd9 Mon Sep 17 00:00:00 2001 From: Alex Dolinsky Date: Sat, 11 Apr 2015 14:06:12 +0200 Subject: [PATCH 21/21] Added clear, grab and shuffle. --- lib/underscore.lua | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/underscore.lua b/lib/underscore.lua index ab02057..46db233 100644 --- a/lib/underscore.lua +++ b/lib/underscore.lua @@ -384,6 +384,12 @@ function Underscore.funcs.pop(array) return table.remove(array) end +Underscore.funcs.clear = (function () + return function (array) + Underscore.funcs.safe_each (array, function () Underscore.funcs.pop (array) end) + end +end)() + Underscore.funcs.append = (function () return function (array, ...) local acc = {unpack (array)} -- identity, abstract away later @@ -428,10 +434,24 @@ function Underscore.funcs.unshift(array, item) return array end +Underscore.funcs.grab = (function () + return function (list, idx) return table.remove(list, idx) end +end)() + function Underscore.funcs.join(array, separator) return table.concat(array, separator) end +Underscore.funcs.shuffle = (function () + return function (list) + math.randomseed (os.time ()) + list = {unpack (list)} + local acc = {} + Underscore.funcs.safe_each (list, function () Underscore.funcs.push (acc, Underscore.funcs.grab(list, math.random (#list))) end) + return acc + end +end)() + -- objects function Underscore.funcs.keys(obj)