Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Yonaba/Moses.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYonaba <roland.yonaba@gmail.com>2018-08-22 21:55:48 +0300
committerYonaba <roland.yonaba@gmail.com>2018-08-22 21:55:48 +0300
commit9bf85201bf6a8655829af702aa7a1b1ab5755aba (patch)
tree196f7ff2e4a63c39064fd465dfaa26e333ae62a6
parentd5185d50ef87602373e932a2bc96fc5eaf4962e3 (diff)
Improved support for chaining (#Fixes 45)
Changed style from _ to M (Fixes #47) Added functions Broughts improvements Updated documentation and tutorial Added support for operators Prepare for 2.0.0 release
-rw-r--r--CHANGELOG.md65
-rw-r--r--README.md2
-rw-r--r--doc/index.html4197
-rw-r--r--doc/ldoc.css303
-rw-r--r--doc/manual/tutorial.md.html (renamed from doc/topics/tutorial.md.html)1729
-rw-r--r--doc/tutorial.md1360
-rw-r--r--moses.lua1720
-rw-r--r--moses_min.lua910
-rw-r--r--spec/array_spec.lua587
-rw-r--r--spec/chaining_spec.lua2
-rw-r--r--spec/func_spec.lua360
-rw-r--r--spec/import_spec.lua18
-rw-r--r--spec/object_spec.lua488
-rw-r--r--spec/op_spec.lua162
-rw-r--r--spec/table_spec.lua374
15 files changed, 7740 insertions, 4537 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63d31e9..39d75b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,70 @@
# Version history
+## 2.0.0 (08/22/2018)
+### Breaking changes
+* library functions now accept iterators prototyped as `f(v, k, ...)` instead of `f(k, v, ...)`.
+It improves the benefits of chaning and helps writting a clear functional-style code.
+Library functions affected with this breaking change are :
+`each`, `eachi`,`countf`, `map`, `reduceby`, `select`, `reject`, `all`, `groupBy`, `countBy`,
+`selectWhile`, `dropWhile`, `findIndex`, `findLastIndex`, `chunk`.
+* `reduceby` is now prototyped as `reduceby(t, f, pred, state)` instead of `reduceby(t, f, state, pred)`.
+* `times` is now prototyped as `times(iter, n, ...)` instead of `times(iter, n, ...)`.
+* `bindAll` was renamed to `bindall`
+* `functions` no longer accept optional `sort` third arguments
+* `sliding` was renamed to `overlapping`
+* Improved `range` to handle negative progressions and start the count from 1.
+
+###Other changes
+* Made `shift` a default library function, and `pop` its alias.
+* Moved `shuffle` from table function to array functions
+* Made `iterator` to accept an extra optional arg `n`
+
+### Additions
+
+#### Added support for operators
+* Arithmetic operators : `add`, `sub`, `mul`, `div`, `mod`, `exp`, `pow` (alias to `exp`), `unm`, `neg` (alias to `unm`), `floordiv`, `intdiv`
+* Relational operators : `eq`, `neq`, `lt`, `gt`, `le`, `ge`
+* Logical operators : `land`, `lor`, `lnot`
+* Concatenation operator : `concat`
+* Length operator : `length`, `len` (alias to `length`)
+
+#### Added functions
+* Added `adjust` in table functions
+* Added `xprod` in array functions
+* Added `prepend` in array functions
+* Added `zeros` in array functions
+* Added `ones` in array functions
+* Added `vector` in array functions
+* Added `aperture` in array functions
+* Added `sum` in array functions
+* Added `product` in array functions
+* Added `mean` in array functions
+* Added `median` in array functions
+* Added `powerset` in array functions
+* Added `zipWith` in array functions
+* Added `pairwise` in array functions
+* Added `applySpec` in utility functions
+* Added `nthArg` in utility functions
+* Added `cond` in utility functions
+* Added `castArray` in utility functions
+* Added `unary` in utility functions
+* Added `ary` in utility functions
+* Added `rearg` in utility functions
+* Added `unfold` in utility functions
+* Added `converge` in utility functions
+* Added `path` in object functions
+
+#### Added function aliases
+* Added `update` as alias to `adjust`
+* Added `always` as alias to `constant`
+* Added `intersperse` as alias to `interpose`
+* Added `sliding` as alias to `aperture`
+* Added `tabulate` as alias to `array`
+* Added `matches` as alias to `isEqual`
+* Added `average` as alias to `mean`
+* Added `nAry` as alias to `ary`
+* Added `transposeWith` as alias to `zipWith`
+
## 1.6.1 (04/27/17)
* Added `_.array`
diff --git a/README.md b/README.md
index 912c01c..f17be65 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ moonrocks install moses
local _ = require "moses"
````
-*Note:* the full source [moses.lua](https://github.com/Yonaba/Moses/blob/master/moses.lua) is quite heavy (~70 kiB). You can alternatively use the [minified version](https://github.com/Yonaba/Moses/blob/master/moses_min.lua) (~22 kiB).
+*Note:* the full source [moses.lua](https://github.com/Yonaba/Moses/blob/master/moses.lua) is quite heavy (~80 kiB, 2611 LOC). You can alternatively use the [minified version](https://github.com/Yonaba/Moses/blob/master/moses_min.lua) (~30 kiB, 475 LOC).
## Tutorial
diff --git a/doc/index.html b/doc/index.html
index bace80a..6d0263e 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Moses documentation</title>
- <link rel="stylesheet" href="ldoc.css" type="text/css" />
+ <link rel="stylesheet" href="ldoc_fixed.css" type="text/css" />
</head>
<body>
@@ -29,6 +29,7 @@
<h2>Contents</h2>
<ul>
+<li><a href="#Operator_functions">Operator functions </a></li>
<li><a href="#Table_functions">Table functions </a></li>
<li><a href="#Array_functions">Array functions </a></li>
<li><a href="#Utility_functions">Utility functions </a></li>
@@ -40,9 +41,9 @@
<ul class="nowrap">
<li><strong>moses</strong></li>
</ul>
-<h2>Topics</h2>
-<ul class="">
- <li><a href="topics/tutorial.md.html">tutorial</a></li>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="manual/tutorial.md.html">tutorial</a></li>
</ul>
</div>
@@ -52,105 +53,177 @@
<h1>Module <code>moses</code></h1>
<p>Utility-belt library for functional programming in Lua (<a href="http://github.com/Yonaba/Moses">source</a>)</p>
<p>
+
</p>
<h3>Info:</h3>
<ul>
- <li><strong>Copyright</strong>: 2012-2017</li>
- <li><strong>Release</strong>: 1.6.1</li>
+ <li><strong>Copyright</strong>: 2012-2018</li>
+ <li><strong>Release</strong>: 2.0.0</li>
<li><strong>License</strong>: <a href="http://www.opensource.org/licenses/mit-license.php">MIT</a></li>
<li><strong>Author</strong>: <a href="http://github.com/Yonaba">Roland Yonaba</a></li>
</ul>
-<h2><a href="#Table_functions">Table functions </a></h2>
+<h2><a href="#Operator_functions">Operator functions </a></h2>
<table class="function_list">
<tr>
- <td class="name" nowrap><a href="#clear">clear (t)</a></td>
- <td class="summary">Clears a table.</td>
+ <td class="name" nowrap><a href="#operator.add">operator.add (a, b)</a></td>
+ <td class="summary">Returns a + b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#each">each (t, f[, ...])</a></td>
- <td class="summary">Iterates on key-value pairs, calling <code>f (k, v)</code> at every step.</td>
+ <td class="name" nowrap><a href="#operator.concat">operator.concat (a, b)</a></td>
+ <td class="summary">Returns concatenation of a and b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#eachi">eachi (t, f[, ...])</a></td>
- <td class="summary">Iterates on integer key-value pairs, calling <code>f(k, v)</code> every step.</td>
+ <td class="name" nowrap><a href="#operator.div">operator.div (a, b)</a></td>
+ <td class="summary">Returns a / b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#at">at (t, ...)</a></td>
- <td class="summary">Collects values at given keys and return them wrapped in an array.</td>
+ <td class="name" nowrap><a href="#operator.eq">operator.eq (a, b)</a></td>
+ <td class="summary">Checks if a equals b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#count">count (t[, value])</a></td>
- <td class="summary">Counts occurrences of a given value in a table.</td>
+ <td class="name" nowrap><a href="#operator.exp">operator.exp (a, b)</a></td>
+ <td class="summary">Returns a ^ b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#countf">countf (t, f[, ...])</a></td>
- <td class="summary">Counts occurrences validating a predicate.</td>
+ <td class="name" nowrap><a href="#operator.floordiv">operator.floordiv (a, b)</a></td>
+ <td class="summary">Performs floor division (//) between <code>a</code> and <code>b</code>.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#cycle">cycle (t, n)</a></td>
- <td class="summary">Loops <code>n</code> times through a table.</td>
+ <td class="name" nowrap><a href="#operator.ge">operator.ge (a, b)</a></td>
+ <td class="summary">Returns logical a and b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#map">map (t, f[, ...])</a></td>
- <td class="summary">Maps <code>f (k, v)</code> on key-value pairs, collects and returns the results.</td>
+ <td class="name" nowrap><a href="#operator.ge">operator.ge (a, b)</a></td>
+ <td class="summary">Checks if a is greater or equal to b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#reduce">reduce (t, f[, state])</a></td>
- <td class="summary">Reduces a table, left-to-right.</td>
+ <td class="name" nowrap><a href="#operator.gt">operator.gt (a, b)</a></td>
+ <td class="summary">Checks if a is strictly greater than b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#reduceby">reduceby (t, f, state, pred[, ...])</a></td>
- <td class="summary">Reduces values in a table passing a given predicate.</td>
+ <td class="name" nowrap><a href="#operator.intdiv">operator.intdiv (a, b)</a></td>
+ <td class="summary">Performs integer division between <code>a</code> and <code>b</code>.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#reduceRight">reduceRight (t, f[, state])</a></td>
- <td class="summary">Reduces a table, right-to-left.</td>
+ <td class="name" nowrap><a href="#operator.le">operator.le (a, b)</a></td>
+ <td class="summary">Checks if a is less or equal to b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#mapReduce">mapReduce (t, f[, state])</a></td>
- <td class="summary">Reduces a table while saving intermediate states.</td>
+ <td class="name" nowrap><a href="#operator.length">operator.length (a)</a></td>
+ <td class="summary">Returns the length of a.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#mapReduceRight">mapReduceRight (t, f[, state])</a></td>
- <td class="summary">Reduces a table while saving intermediate states.</td>
+ <td class="name" nowrap><a href="#operator.lnot">operator.lnot (a)</a></td>
+ <td class="summary">Returns logical not a.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#include">include (t, value)</a></td>
- <td class="summary">Performs a linear search for a value in a table.</td>
+ <td class="name" nowrap><a href="#operator.lor">operator.lor (a, b)</a></td>
+ <td class="summary">Returns logical a or b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#detect">detect (t, value)</a></td>
- <td class="summary">Performs a linear search for a value in a table.</td>
+ <td class="name" nowrap><a href="#operator.lt">operator.lt (a, b)</a></td>
+ <td class="summary">Checks if a is strictly less than b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#where">where (t, props)</a></td>
- <td class="summary">Returns all values having specified keys <code>props</code>.</td>
+ <td class="name" nowrap><a href="#operator.mod">operator.mod (a, b)</a></td>
+ <td class="summary">Returns a % b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#findWhere">findWhere (t, props)</a></td>
- <td class="summary">Returns the first value having specified keys <code>props</code>.</td>
+ <td class="name" nowrap><a href="#operator.mul">operator.mul (a, b)</a></td>
+ <td class="summary">Returns a * b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#select">select (t, f[, ...])</a></td>
- <td class="summary">Selects and returns values passing an iterator test.</td>
+ <td class="name" nowrap><a href="#operator.neq">operator.neq (a, b)</a></td>
+ <td class="summary">Checks if a not equals b.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#reject">reject (t, f[, ...])</a></td>
- <td class="summary">Clones a table while dropping values passing an iterator test.</td>
+ <td class="name" nowrap><a href="#operator.sub">operator.sub (a, b)</a></td>
+ <td class="summary">Returns a - b.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#operator.unm">operator.unm (a)</a></td>
+ <td class="summary">Returns -a.</td>
+ </tr>
+</table>
+<h2><a href="#Table_functions">Table functions </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#adjust">adjust (t, key, f[, ...])</a></td>
+ <td class="summary">Adjusts the value at a given key using a function or a value.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#all">all (t, f[, ...])</a></td>
<td class="summary">Checks if all values in a table are passing an iterator test.</td>
</tr>
<tr>
+ <td class="name" nowrap><a href="#at">at (t, ...)</a></td>
+ <td class="summary">Collects values at given keys and return them wrapped in an array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#clear">clear (t)</a></td>
+ <td class="summary">Clears a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#containsKeys">containsKeys (t, other)</a></td>
+ <td class="summary">Checks if all the keys of <code>other</code> table exists in table <code>t</code>.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#count">count (t[, val])</a></td>
+ <td class="summary">Counts occurrences of a given value in a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#countBy">countBy (t, iter[, ...])</a></td>
+ <td class="summary">Groups values in a collection and counts them.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#countf">countf (t, f[, ...])</a></td>
+ <td class="summary">Counts the number of values passing a predicate test.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#cycle">cycle (t[, n])</a></td>
+ <td class="summary">Loops <code>n</code> times through a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#detect">detect (t, value)</a></td>
+ <td class="summary">Performs a linear search for a value in a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#each">each (t, f[, ...])</a></td>
+ <td class="summary">Iterates on key-value pairs, calling <code>f (v, k)</code> at every step.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#eachi">eachi (t, f[, ...])</a></td>
+ <td class="summary">Iterates on integer key-value pairs, calling <code>f(v, k)</code> every step.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#findWhere">findWhere (t, props)</a></td>
+ <td class="summary">Returns the first value having specified keys <code>props</code>.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#groupBy">groupBy (t, iter[, ...])</a></td>
+ <td class="summary">Splits a table into subsets groups.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#include">include (t, value)</a></td>
+ <td class="summary">Performs a linear search for a value in a table.</td>
+ </tr>
+ <tr>
<td class="name" nowrap><a href="#invoke">invoke (t, method[, ...])</a></td>
<td class="summary">Invokes a method on each value in a table.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#pluck">pluck (t, key)</a></td>
- <td class="summary">Extracts values in a table having a given key.</td>
+ <td class="name" nowrap><a href="#map">map (t, f[, ...])</a></td>
+ <td class="summary">Maps <code>f (v, k)</code> on value-key pairs, collects and returns the results.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#mapReduce">mapReduce (t, f[, state])</a></td>
+ <td class="summary">Reduces a table while saving intermediate states.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#mapReduceRight">mapReduceRight (t, f[, state])</a></td>
+ <td class="summary">Reduces a table while saving intermediate states.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#max">max (t[, transform[, ...]])</a></td>
@@ -161,87 +234,95 @@
<td class="summary">Returns the min value in a collection.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#shuffle">shuffle (t[, seed])</a></td>
- <td class="summary">Returns a shuffled copy of a given collection.</td>
+ <td class="name" nowrap><a href="#pluck">pluck (t, key)</a></td>
+ <td class="summary">Extracts values in a table having a given key.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#same">same (a, b)</a></td>
- <td class="summary">Checks if two tables are the same.</td>
+ <td class="name" nowrap><a href="#reduce">reduce (t, f[, state])</a></td>
+ <td class="summary">Reduces a table, left-to-right.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#sort">sort (t[, comp])</a></td>
- <td class="summary">Sorts a table, in-place.</td>
+ <td class="name" nowrap><a href="#reduceRight">reduceRight (t, f[, state])</a></td>
+ <td class="summary">Reduces a table, right-to-left.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#sortBy">sortBy (t[, transform[, comp]])</a></td>
- <td class="summary">Sorts a table in-place using a transform.</td>
+ <td class="name" nowrap><a href="#reduceby">reduceby (t, f, pred[, state[, ...]])</a></td>
+ <td class="summary">Reduces values in a table passing a given predicate.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#groupBy">groupBy (t, iter[, ...])</a></td>
- <td class="summary">Splits a table into subsets groups.</td>
+ <td class="name" nowrap><a href="#reject">reject (t, f[, ...])</a></td>
+ <td class="summary">Clones a table while dropping values passing an iterator test.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#countBy">countBy (t, iter[, ...])</a></td>
- <td class="summary">Groups values in a collection and counts them.</td>
+ <td class="name" nowrap><a href="#same">same (a, b)</a></td>
+ <td class="summary">Checks if two tables are the same.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sameKeys">sameKeys (tA, tB)</a></td>
+ <td class="summary">Checks if both given tables have the same keys.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#select">select (t, f[, ...])</a></td>
+ <td class="summary">Selects and returns values passing an iterator test.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#size">size ([...])</a></td>
<td class="summary">Counts the number of values in a collection.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#containsKeys">containsKeys (t, other)</a></td>
- <td class="summary">Checks if all the keys of <code>other</code> table exists in table <code>t</code>.</td>
+ <td class="name" nowrap><a href="#sort">sort (t[, comp])</a></td>
+ <td class="summary">Sorts a table, in-place.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#sameKeys">sameKeys (tA, tB)</a></td>
- <td class="summary">Checks if both given tables have the same keys.</td>
+ <td class="name" nowrap><a href="#sortBy">sortBy (t[, transform[, comp]])</a></td>
+ <td class="summary">Sorts a table in-place using a transform.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#where">where (t, props)</a></td>
+ <td class="summary">Returns all values having specified keys <code>props</code>.</td>
</tr>
</table>
<h2><a href="#Array_functions">Array functions </a></h2>
<table class="function_list">
<tr>
- <td class="name" nowrap><a href="#sample">sample (array[, n[, seed]])</a></td>
- <td class="summary">Samples <code>n</code> random values from an array.</td>
+ <td class="name" nowrap><a href="#addTop">addTop (array, ...)</a></td>
+ <td class="summary">Adds all passed-in values at the top of an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#sampleProb">sampleProb (array, prob[, seed])</a></td>
- <td class="summary">Return elements from a sequence with a given probability.</td>
+ <td class="name" nowrap><a href="#aperture">aperture (array[, n])</a></td>
+ <td class="summary">Iterator returning sliding partitions of an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#toArray">toArray (...)</a></td>
- <td class="summary">Converts a list of arguments to an array.</td>
+ <td class="name" nowrap><a href="#append">append (array, other)</a></td>
+ <td class="summary">Clones array and appends values from another array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#find">find (array, value[, from])</a></td>
- <td class="summary">Looks for the first occurrence of a given value in an array.</td>
+ <td class="name" nowrap><a href="#chunk">chunk (array, f[, ...])</a></td>
+ <td class="summary">Chunks together consecutive values.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#reverse">reverse (array)</a></td>
- <td class="summary">Returns an array where values are in reverse order.</td>
+ <td class="name" nowrap><a href="#compact">compact (array)</a></td>
+ <td class="summary">Returns all truthy values (removes <code>falses</code> and <code>nils</code>).</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#fill">fill (array, value[, i[, j]])</a></td>
- <td class="summary">Replaces elements in a given array with a given value.</td>
+ <td class="name" nowrap><a href="#concat">concat (array[, sep[, i[, j]]])</a></td>
+ <td class="summary">Concatenates values in a given array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#selectWhile">selectWhile (array, f[, ...])</a></td>
- <td class="summary">Collects values from a given array.</td>
+ <td class="name" nowrap><a href="#difference">difference (array, another)</a></td>
+ <td class="summary">Returns values from an array not present in all passed-in args.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#dropWhile">dropWhile (array, f[, ...])</a></td>
<td class="summary">Collects values from a given array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#sortedIndex">sortedIndex (array, the[, comp[, sort]])</a></td>
- <td class="summary">Returns the index at which a value should be inserted.</td>
- </tr>
- <tr>
- <td class="name" nowrap><a href="#indexOf">indexOf (array, value)</a></td>
- <td class="summary">Returns the index of the first occurence of value in an array.</td>
+ <td class="name" nowrap><a href="#fill">fill (array, value[, i[, j]])</a></td>
+ <td class="summary">Replaces elements in a given array with a given value.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#lastIndexOf">lastIndexOf (array, value)</a></td>
- <td class="summary">Returns the index of the last occurrence of value in an array.</td>
+ <td class="name" nowrap><a href="#find">find (array, value[, from])</a></td>
+ <td class="summary">Looks for the first occurrence of a given value in an array.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#findIndex">findIndex (array, predicate[, ...])</a></td>
@@ -252,187 +333,215 @@
<td class="summary">Returns the last index at which a predicate returns true.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#addTop">addTop (array, ...)</a></td>
- <td class="summary">Adds all passed-in values at the top of an array.</td>
- </tr>
- <tr>
- <td class="name" nowrap><a href="#push">push (array, ...)</a></td>
- <td class="summary">Pushes all passed-in values at the end of an array.</td>
+ <td class="name" nowrap><a href="#first">first (array[, n])</a></td>
+ <td class="summary">Returns the first N values in an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#pop">pop (array[, n])</a></td>
- <td class="summary">Removes and returns the values at the top of a given array.</td>
+ <td class="name" nowrap><a href="#flatten">flatten (array[, shallow])</a></td>
+ <td class="summary">Flattens a nested array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#unshift">unshift (array[, n])</a></td>
- <td class="summary">Removes and returns the values at the end of a given array.</td>
+ <td class="name" nowrap><a href="#indexOf">indexOf (array, value)</a></td>
+ <td class="summary">Returns the index of the first occurrence of value in an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#pull">pull (array, ...)</a></td>
- <td class="summary">Removes all provided values in a given array.</td>
+ <td class="name" nowrap><a href="#initial">initial (array[, n])</a></td>
+ <td class="summary">Returns all values in an array excluding the last N values.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#removeRange">removeRange (array[, start[, finish]])</a></td>
- <td class="summary">Removes values at index within the range <code>[start, finish]</code>.</td>
+ <td class="name" nowrap><a href="#interleave">interleave (...)</a></td>
+ <td class="summary">Interleaves arrays.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#chunk">chunk (array, f[, ...])</a></td>
- <td class="summary">Chunks together consecutive values.</td>
+ <td class="name" nowrap><a href="#interpose">interpose (array, value)</a></td>
+ <td class="summary">Interposes value in-between consecutive pair of values in array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#slice">slice (array[, start[, finish]])</a></td>
- <td class="summary">Slices values indexed within <code>[start, finish]</code> range.</td>
+ <td class="name" nowrap><a href="#intersection">intersection (array, ...)</a></td>
+ <td class="summary">Returns the intersection of all passed-in arrays.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#first">first (array[, n])</a></td>
- <td class="summary">Returns the first N values in an array.</td>
+ <td class="name" nowrap><a href="#invert">invert (array)</a></td>
+ <td class="summary">Swaps keys with values.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#initial">initial (array[, n])</a></td>
- <td class="summary">Returns all values in an array excluding the last N values.</td>
+ <td class="name" nowrap><a href="#isunique">isunique (array)</a></td>
+ <td class="summary">Checks if a given array contains distinct values.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#last">last (array[, n])</a></td>
<td class="summary">Returns the last N values in an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#rest">rest (array[, index])</a></td>
- <td class="summary">Removes all values before index.</td>
+ <td class="name" nowrap><a href="#lastIndexOf">lastIndexOf (array, value)</a></td>
+ <td class="summary">Returns the index of the last occurrence of value in an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#nth">nth (array, index)</a></td>
- <td class="summary">Returns the value at a given index.</td>
+ <td class="name" nowrap><a href="#mean">mean (array)</a></td>
+ <td class="summary">Returns the mean of an array of numbers.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#compact">compact (array)</a></td>
- <td class="summary">Removes all falsy (false and nil) values.</td>
+ <td class="name" nowrap><a href="#median">median (array)</a></td>
+ <td class="summary">Returns the median of an array of numbers.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#flatten">flatten (array[, shallow])</a></td>
- <td class="summary">Flattens a nested array.</td>
+ <td class="name" nowrap><a href="#nth">nth (array, index)</a></td>
+ <td class="summary">Returns the value at a given index.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#difference">difference (array, another)</a></td>
- <td class="summary">Returns values from an array not present in all passed-in args.</td>
+ <td class="name" nowrap><a href="#ones">ones (n)</a></td>
+ <td class="summary">Returns an array of <code>n</code> 1's.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#union">union (...)</a></td>
- <td class="summary">Returns the duplicate-free union of all passed in arrays.</td>
+ <td class="name" nowrap><a href="#overlapping">overlapping (array[, n[, pads]])</a></td>
+ <td class="summary">Iterator returning overlapping partitions of an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#intersection">intersection (array, ...)</a></td>
- <td class="summary">Returns the intersection of all passed-in arrays.</td>
+ <td class="name" nowrap><a href="#pairwise">pairwise (array)</a></td>
+ <td class="summary">Iterator returning sliding pairs of an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#symmetricDifference">symmetricDifference (array, array2)</a></td>
- <td class="summary">Performs a symmetric difference.</td>
+ <td class="name" nowrap><a href="#partition">partition (array[, n[, pads]])</a></td>
+ <td class="summary">Iterator returning partitions of an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#unique">unique (array)</a></td>
- <td class="summary">Produces a duplicate-free version of a given array.</td>
+ <td class="name" nowrap><a href="#permutation">permutation (array)</a></td>
+ <td class="summary">Iterator returning the permutations of an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isunique">isunique (array)</a></td>
- <td class="summary">Checks if a given array contains distinct values.</td>
+ <td class="name" nowrap><a href="#powerset">powerset (array)</a></td>
+ <td class="summary">Returns the powerset of array values.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#zip">zip (...)</a></td>
- <td class="summary">Merges values of each of the passed-in arrays in subsets.</td>
+ <td class="name" nowrap><a href="#prepend">prepend (array, ...)</a></td>
+ <td class="summary">Adds all passed-in values at the top of an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#append">append (array, other)</a></td>
- <td class="summary">Clones <a href="index.html#array">array</a> and appends <code>other</code> values.</td>
+ <td class="name" nowrap><a href="#product">product (array)</a></td>
+ <td class="summary">Returns the product of array values.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#interleave">interleave (...)</a></td>
- <td class="summary">Interleaves arrays.</td>
+ <td class="name" nowrap><a href="#pull">pull (array, ...)</a></td>
+ <td class="summary">Removes all provided values in a given array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#interpose">interpose (value, array)</a></td>
- <td class="summary">Interposes value in-between consecutive pair of values in <a href="index.html#array">array</a>.</td>
+ <td class="name" nowrap><a href="#push">push (array, ...)</a></td>
+ <td class="summary">Pushes all passed-in values at the end of an array.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#range">range ([from[, to[, step]]])</a></td>
<td class="summary">Produces a flexible list of numbers.</td>
</tr>
<tr>
+ <td class="name" nowrap><a href="#removeRange">removeRange (array[, start[, finish]])</a></td>
+ <td class="summary">Removes values at an index within the range <code>[start, finish]</code>.</td>
+ </tr>
+ <tr>
<td class="name" nowrap><a href="#rep">rep (value, n)</a></td>
<td class="summary">Creates an array list of <code>n</code> values, repeated.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#partition">partition (array[, n[, pad]])</a></td>
- <td class="summary">Iterator returning partitions of an array.</td>
+ <td class="name" nowrap><a href="#rest">rest (array[, index])</a></td>
+ <td class="summary">Returns all values after index.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#sliding.">sliding. (array[, n[, pad]])</a></td>
- <td class="summary">Iterator returning sliding partitions of an array.</td>
+ <td class="name" nowrap><a href="#reverse">reverse (array)</a></td>
+ <td class="summary">Returns an array where values are in reverse order.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#permutation">permutation (array)</a></td>
- <td class="summary">Iterator returning the permutations of an array.</td>
+ <td class="name" nowrap><a href="#sample">sample (array[, n[, seed]])</a></td>
+ <td class="summary">Samples <code>n</code> random values from an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#invert">invert (array)</a></td>
- <td class="summary">Swaps keys with values.</td>
+ <td class="name" nowrap><a href="#sampleProb">sampleProb (array, prob[, seed])</a></td>
+ <td class="summary">Return elements from a sequence with a given probability.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#concat">concat (array[, sep[, i[, j]]])</a></td>
- <td class="summary">Concatenates values in a given array.</td>
+ <td class="name" nowrap><a href="#selectWhile">selectWhile (array, f[, ...])</a></td>
+ <td class="summary">Collects values from a given array.</td>
</tr>
-</table>
-<h2><a href="#Utility_functions">Utility functions </a></h2>
-<table class="function_list">
<tr>
- <td class="name" nowrap><a href="#noop">noop ()</a></td>
- <td class="summary">The no-operation function.</td>
+ <td class="name" nowrap><a href="#shift">shift (array[, n])</a></td>
+ <td class="summary">Removes and returns the values at the top of a given array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#identity">identity (value)</a></td>
- <td class="summary">Returns the passed-in value.</td>
+ <td class="name" nowrap><a href="#shuffle">shuffle (array[, seed])</a></td>
+ <td class="summary">Returns a shuffled copy of a given array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#constant">constant (value)</a></td>
- <td class="summary">Creates a constant function which returns the same output on every call.</td>
+ <td class="name" nowrap><a href="#slice">slice (array[, start[, finish]])</a></td>
+ <td class="summary">Slices values indexed within <code>[start, finish]</code> range.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#memoize">memoize (f[, hash])</a></td>
- <td class="summary">Memoizes a given function by caching the computed result.</td>
+ <td class="name" nowrap><a href="#sortedIndex">sortedIndex (array, the[, comp[, sort]])</a></td>
+ <td class="summary">Returns the index at which a value should be inserted.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#once">once (f)</a></td>
- <td class="summary">Returns a version of <code>f</code> that runs only once.</td>
+ <td class="name" nowrap><a href="#sum">sum (array)</a></td>
+ <td class="summary">Returns the sum of array values.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#before">before (f, count)</a></td>
- <td class="summary">Returns a version of <code>f</code> that will run no more than <a href="index.html#count">count</a> times.</td>
+ <td class="name" nowrap><a href="#symmetricDifference">symmetricDifference (array, array2)</a></td>
+ <td class="summary">Performs a symmetric difference.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#after">after (f, count)</a></td>
- <td class="summary">Returns a version of <code>f</code> that runs on the <code>count-th</code> call.</td>
+ <td class="name" nowrap><a href="#toArray">toArray (...)</a></td>
+ <td class="summary">Converts a list of arguments to an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#compose">compose (...)</a></td>
- <td class="summary">Composes functions.</td>
+ <td class="name" nowrap><a href="#union">union (...)</a></td>
+ <td class="summary">Returns the duplicate-free union of all passed in arrays.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#pipe">pipe (value, ...)</a></td>
- <td class="summary">Pipes a value through a series of functions.</td>
+ <td class="name" nowrap><a href="#unique">unique (array)</a></td>
+ <td class="summary">Produces a duplicate-free version of a given array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#complement">complement (f)</a></td>
- <td class="summary">Returns the logical complement of a given function.</td>
+ <td class="name" nowrap><a href="#unshift">unshift (array[, n])</a></td>
+ <td class="summary">Removes and returns the values at the end of a given array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#juxtapose">juxtapose (value, ...)</a></td>
- <td class="summary">Calls a sequence of passed-in functions with the same argument.</td>
+ <td class="name" nowrap><a href="#vector">vector (value, n)</a></td>
+ <td class="summary">Returns an array of <code>n</code> times a given value.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#wrap">wrap (f, wrapper)</a></td>
- <td class="summary">Wraps <code>f</code> inside of the <code>wrapper</code> function.</td>
+ <td class="name" nowrap><a href="#xprod">xprod (array, array2)</a></td>
+ <td class="summary">Returns all possible pairs built from given arrays.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#times">times (n, iter, ...)</a></td>
- <td class="summary">Runs <code>iter</code> function <code>n</code> times.</td>
+ <td class="name" nowrap><a href="#zeros">zeros (n)</a></td>
+ <td class="summary">Returns an array of <code>n</code> zeros.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#zip">zip (...)</a></td>
+ <td class="summary">Merges values of each of the passed-in arrays in subsets.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#zipWith">zipWith (f, ...)</a></td>
+ <td class="summary">Merges values using a given function.</td>
+ </tr>
+</table>
+<h2><a href="#Utility_functions">Utility functions </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#after">after (f, count)</a></td>
+ <td class="summary">Returns a version of <code>f</code> that runs on the <code>count-th</code> call.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#applySpec">applySpec (specs)</a></td>
+ <td class="summary">Returns a function which applies <code>specs</code> on args.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#array">array (...)</a></td>
+ <td class="summary">Iterates over an iterator and returns its values in an array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#ary">ary (f[, n])</a></td>
+ <td class="summary">Returns a function which accepts up to <code>n</code> args.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#before">before (f, count)</a></td>
+ <td class="summary">Returns a version of <code>f</code> that will run no more than <em>count</em> times.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#bind">bind (f, v)</a></td>
@@ -443,34 +552,82 @@
<td class="summary">Binds <code>v</code> to be the second argument to <code>f</code>.</td>
</tr>
<tr>
+ <td class="name" nowrap><a href="#bindall">bindall (obj, ...)</a></td>
+ <td class="summary">Binds methods to object.</td>
+ </tr>
+ <tr>
<td class="name" nowrap><a href="#bindn">bindn (f, ...)</a></td>
- <td class="summary">Binds <code>&hellip;</code> to be the N-first arguments to function <code>f</code>.</td>
+ <td class="summary">Binds <code>...</code> to be the N-first arguments to function <code>f</code>.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#bindAll">bindAll (obj, ...)</a></td>
- <td class="summary">Binds methods to object.</td>
+ <td class="name" nowrap><a href="#castArray">castArray (value)</a></td>
+ <td class="summary">Casts vaue as an array if it is not one.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#uniqueId">uniqueId ([template[, ...]])</a></td>
- <td class="summary">Generates an unique ID for the current session.</td>
+ <td class="name" nowrap><a href="#complement">complement (f)</a></td>
+ <td class="summary">Returns the logical complement of a given function.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#iterator">iterator (f, x)</a></td>
- <td class="summary">Produces an iterator which repeatedly apply a function <code>f</code> onto an input.</td>
+ <td class="name" nowrap><a href="#compose">compose (...)</a></td>
+ <td class="summary">Composes functions.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#array">array (...)</a></td>
- <td class="summary">Iterates an iterator and returns its values in an array.</td>
+ <td class="name" nowrap><a href="#cond">cond (conds)</a></td>
+ <td class="summary">Returns a function which iterate over a set of conditions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#constant">constant (value)</a></td>
+ <td class="summary">Creates a constant function which returns the same output on every call.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#converge">converge (f, g, h)</a></td>
+ <td class="summary">Converges two functions into one.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#curry">curry (f[, n_args])</a></td>
+ <td class="summary">Curries a function.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#flip">flip (f)</a></td>
<td class="summary">Creates a function of <code>f</code> with arguments flipped in reverse order.</td>
</tr>
<tr>
+ <td class="name" nowrap><a href="#identity">identity (value)</a></td>
+ <td class="summary">Returns the passed-in value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#iterator">iterator (f, value[, n])</a></td>
+ <td class="summary">Produces an iterator which repeatedly apply a function <code>f</code> onto an input.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#juxtapose">juxtapose (value, ...)</a></td>
+ <td class="summary">Calls a sequence of passed-in functions with the same argument.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#memoize">memoize (f[, hash])</a></td>
+ <td class="summary">Memoizes a given function by caching the computed result.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#noop">noop ()</a></td>
+ <td class="summary">The no operation function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#nthArg">nthArg (n)</a></td>
+ <td class="summary">Returns a function that gets the nth argument.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#once">once (f)</a></td>
+ <td class="summary">Returns a version of <code>f</code> that runs only once.</td>
+ </tr>
+ <tr>
<td class="name" nowrap><a href="#over">over (...)</a></td>
<td class="summary">Creates a function that runs transforms on all arguments it receives.</td>
</tr>
<tr>
+ <td class="name" nowrap><a href="#overArgs">overArgs (f, ...)</a></td>
+ <td class="summary">Creates a function that invokes <code>f</code> with its arguments transformed.</td>
+ </tr>
+ <tr>
<td class="name" nowrap><a href="#overEvery">overEvery (...)</a></td>
<td class="summary">Creates a validation function.</td>
</tr>
@@ -479,10 +636,6 @@
<td class="summary">Creates a validation function.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#overArgs">overArgs (f, ...)</a></td>
- <td class="summary">Creates a function that invokes <code>f</code> with its arguments transformed.</td>
- </tr>
- <tr>
<td class="name" nowrap><a href="#partial">partial (f, ...)</a></td>
<td class="summary">Partially apply a function by filling in any number of its arguments.</td>
</tr>
@@ -491,43 +644,47 @@
<td class="summary">Similar to <a href="index.html#partial">partial</a>, but from the right.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#curry">curry (f[, n_args])</a></td>
- <td class="summary">Curries a function.</td>
+ <td class="name" nowrap><a href="#pipe">pipe (value, ...)</a></td>
+ <td class="summary">Pipes a value through a series of functions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rearg">rearg (f, indexes)</a></td>
+ <td class="summary">Returns a function which runs with arguments rearranged.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#time">time (f[, ...])</a></td>
- <td class="summary">Returns the execution time of <code>f (&hellip;)</code> and its returned values.</td>
+ <td class="summary">Returns the execution time of <code>f (...)</code> and its returned values.</td>
</tr>
-</table>
-<h2><a href="#Object_functions">Object functions </a></h2>
-<table class="function_list">
<tr>
- <td class="name" nowrap><a href="#keys">keys (obj)</a></td>
- <td class="summary">Returns the keys of the object properties.</td>
+ <td class="name" nowrap><a href="#times">times (iter[, n[, ...]])</a></td>
+ <td class="summary">Runs <code>iter</code> function <code>n</code> times.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#values">values (obj)</a></td>
- <td class="summary">Returns the values of the object properties.</td>
+ <td class="name" nowrap><a href="#unary">unary (f)</a></td>
+ <td class="summary">Returns a function which accepts up to one arg.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#kvpairs">kvpairs (obj)</a></td>
- <td class="summary">Converts keys and values a an array-list of [k, v].</td>
+ <td class="name" nowrap><a href="#unfold">unfold (f, seed)</a></td>
+ <td class="summary">Builds a list from a seed value.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#toObj">toObj (kvpairs)</a></td>
- <td class="summary">Converts an array list of <a href="index.html#kvpairs">kvpairs</a> to an object.</td>
+ <td class="name" nowrap><a href="#uniqueId">uniqueId ([template[, ...]])</a></td>
+ <td class="summary">Generates an unique ID for the current session.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#property">property (key)</a></td>
- <td class="summary">Returns a function that will return the key property of any passed-in object.</td>
+ <td class="name" nowrap><a href="#wrap">wrap (f, wrapper)</a></td>
+ <td class="summary">Wraps <code>f</code> inside of the <code>wrapper</code> function.</td>
</tr>
+</table>
+<h2><a href="#Object_functions">Object functions </a></h2>
+<table class="function_list">
<tr>
- <td class="name" nowrap><a href="#propertyOf">propertyOf (obj)</a></td>
- <td class="summary">Returns a function which will return the value of an object property.</td>
+ <td class="name" nowrap><a href="#chain">chain (value)</a></td>
+ <td class="summary">Returns a wrapped object.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#toBoolean">toBoolean (value)</a></td>
- <td class="summary">Converts any given value to a boolean</td>
+ <td class="name" nowrap><a href="#clone">clone (obj[, shallow])</a></td>
+ <td class="summary">Clones a given object properties.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#extend">extend (destObj, ...)</a></td>
@@ -538,100 +695,124 @@
<td class="summary">Returns a sorted list of all methods names found in an object.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#clone">clone (obj[, shallow])</a></td>
- <td class="summary">Clones a given object properties.</td>
+ <td class="name" nowrap><a href="#has">has (obj, key)</a></td>
+ <td class="summary">Checks if a given object implements a property.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#tap">tap (obj, f[, ...])</a></td>
- <td class="summary">Invokes interceptor with the object, and then returns object.</td>
+ <td class="name" nowrap><a href="#import">import ([context[, noConflict]])</a></td>
+ <td class="summary">Imports all library functions into a context.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#has">has (obj, key)</a></td>
- <td class="summary">Checks if a given object implements a property.</td>
+ <td class="name" nowrap><a href="#isArray">isArray (obj)</a></td>
+ <td class="summary">Checks if the given argument is an array.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#pick">pick (obj, ...)</a></td>
- <td class="summary">Returns an object copy having white-listed properties.</td>
+ <td class="name" nowrap><a href="#isBoolean">isBoolean (obj)</a></td>
+ <td class="summary">Checks if the given argument is a boolean.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#omit">omit (obj, ...)</a></td>
- <td class="summary">Returns an object copy without black-listed properties.</td>
+ <td class="name" nowrap><a href="#isCallable">isCallable (obj)</a></td>
+ <td class="summary">Checks if the given argument is callable.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#template">template (obj[, template])</a></td>
- <td class="summary">Applies a template to an object, preserving non-nil properties.</td>
+ <td class="name" nowrap><a href="#isEmpty">isEmpty ([obj])</a></td>
+ <td class="summary">Checks if the given pbject is empty.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#isEqual">isEqual (objA, objB[, useMt])</a></td>
<td class="summary">Performs a deep comparison test between two objects.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#result">result (obj, method[, ...])</a></td>
- <td class="summary">Invokes an object method.</td>
- </tr>
- <tr>
- <td class="name" nowrap><a href="#isTable">isTable (t)</a></td>
- <td class="summary">Checks if the given arg is a table.</td>
+ <td class="name" nowrap><a href="#isFinite">isFinite (obj)</a></td>
+ <td class="summary">Checks if the given argument is a finite number.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isCallable">isCallable (obj)</a></td>
- <td class="summary">Checks if the given argument is callable.</td>
+ <td class="name" nowrap><a href="#isFunction">isFunction (obj)</a></td>
+ <td class="summary">Checks if the given argument is a function.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isArray">isArray (obj)</a></td>
- <td class="summary">Checks if the given argument is an array.</td>
+ <td class="name" nowrap><a href="#isInteger">isInteger (obj)</a></td>
+ <td class="summary">Checks if the given argument is an integer.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#isIterable">isIterable (obj)</a></td>
<td class="summary">Checks if the given object is iterable with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a> (or <a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a>).</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isEmpty">isEmpty ([obj])</a></td>
- <td class="summary">Checks if the given pbject is empty.</td>
+ <td class="name" nowrap><a href="#isNaN">isNaN (obj)</a></td>
+ <td class="summary">Checks if the given argument is NaN (see <a href="http://en.wikipedia.org/wiki/NaN">Not-A-Number</a>).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isNil">isNil (obj)</a></td>
+ <td class="summary">Checks if the given argument is nil.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isNumber">isNumber (obj)</a></td>
+ <td class="summary">Checks if the given argument is a number.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#isString">isString (obj)</a></td>
<td class="summary">Checks if the given argument is a string.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isFunction">isFunction (obj)</a></td>
- <td class="summary">Checks if the given argument is a function.</td>
+ <td class="name" nowrap><a href="#isTable">isTable (t)</a></td>
+ <td class="summary">Checks if the given arg is a table.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isNil">isNil (obj)</a></td>
- <td class="summary">Checks if the given argument is nil.</td>
+ <td class="name" nowrap><a href="#keys">keys (obj)</a></td>
+ <td class="summary">Returns the keys of the object properties.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isNumber">isNumber (obj)</a></td>
- <td class="summary">Checks if the given argument is a number.</td>
+ <td class="name" nowrap><a href="#kvpairs">kvpairs (obj)</a></td>
+ <td class="summary">Converts key-value pairs to an array-list of <code>[k, v]</code> pairs.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isNaN">isNaN (obj)</a></td>
- <td class="summary">Checks if the given argument is NaN (see <a href="http://en.wikipedia.org/wiki/NaN">Not-A-Number</a>).</td>
+ <td class="name" nowrap><a href="#obj:value">obj:value ()</a></td>
+ <td class="summary">Extracts the value of a wrapped object.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isFinite">isFinite (obj)</a></td>
- <td class="summary">Checks if the given argument is a finite number.</td>
+ <td class="name" nowrap><a href="#omit">omit (obj, ...)</a></td>
+ <td class="summary">Returns an object copy without black-listed properties.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isBoolean">isBoolean (obj)</a></td>
- <td class="summary">Checks if the given argument is a boolean.</td>
+ <td class="name" nowrap><a href="#path">path (obj, ...)</a></td>
+ <td class="summary">Returns the value at a given path in an object.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#isInteger">isInteger (obj)</a></td>
- <td class="summary">Checks if the given argument is an integer.</td>
+ <td class="name" nowrap><a href="#pick">pick (obj, ...)</a></td>
+ <td class="summary">Returns an object copy having white-listed properties.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#chain">chain (value)</a></td>
- <td class="summary">Returns a wrapped object.</td>
+ <td class="name" nowrap><a href="#property">property (key)</a></td>
+ <td class="summary">Returns a function that will return the key property of any passed-in object.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#obj:value">obj:value ()</a></td>
- <td class="summary">Extracts the value of a wrapped object.</td>
+ <td class="name" nowrap><a href="#propertyOf">propertyOf (obj)</a></td>
+ <td class="summary">Returns a function which will return the value of an object property.</td>
</tr>
<tr>
- <td class="name" nowrap><a href="#import">import ([context[, noConflict]])</a></td>
- <td class="summary">Imports all library functions into a context.</td>
+ <td class="name" nowrap><a href="#result">result (obj, method[, ...])</a></td>
+ <td class="summary">Invokes an object method.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#tap">tap (obj, f[, ...])</a></td>
+ <td class="summary">Invokes interceptor with the object, and then returns object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#template">template (obj[, template])</a></td>
+ <td class="summary">Applies a template to an object, preserving non-nil properties.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#toBoolean">toBoolean (value)</a></td>
+ <td class="summary">Converts any given value to a boolean</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#toObj">toObj (kvpairs)</a></td>
+ <td class="summary">Converts an array list of <code>[k,v]</code> pairs to an object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#values">values (obj)</a></td>
+ <td class="summary">Returns the values of the object properties.</td>
</tr>
</table>
@@ -639,28 +820,31 @@
<br/>
- <h2 class="section-header "><a name="Table_functions"></a>Table functions </h2>
+ <h2 class="section-header "><a name="Operator_functions"></a>Operator functions </h2>
<dl class="function">
<dt>
- <a name = "clear"></a>
- <strong>clear (t)</strong>
+ <a name = "operator.add"></a>
+ <strong>operator.add (a, b)</strong>
</dt>
<dd>
- Clears a table. All its values become nil.
+ Returns a + b. <em>Aliased as <code>op.add</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the given table, cleared.
+ a + b
</ol>
@@ -668,93 +852,196 @@
</dd>
<dt>
- <a name = "each"></a>
- <strong>each (t, f[, ...])</strong>
+ <a name = "operator.concat"></a>
+ <strong>operator.concat (a, b)</strong>
</dt>
<dd>
- Iterates on key-value pairs, calling <code>f (k, v)</code> at every step.
- <br/><em>Aliased as <code>forEach</code></em>.
+ Returns concatenation of a and b. <em>Aliased as <code>op.concat</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">f</span>
- a function, prototyped as <code>f (k, v, &hellip;)</code>
+ <li><span class="parameter">b</span>
+ a value
</li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
- (<em>optional</em>)
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a .. b
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "operator.div"></a>
+ <strong>operator.div (a, b)</strong>
+ </dt>
+ <dd>
+ Returns a / b. <em>Aliased as <code>op.div</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+ a / b
+ </ol>
- <h3>See also:</h3>
+
+
+
+</dd>
+ <dt>
+ <a name = "operator.eq"></a>
+ <strong>operator.eq (a, b)</strong>
+ </dt>
+ <dd>
+ Checks if a equals b. <em>Aliased as <code>op.eq</code></em>.
+
+
+ <h3>Parameters:</h3>
<ul>
- <a href="index.html#eachi">eachi</a>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ a == b
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "eachi"></a>
- <strong>eachi (t, f[, ...])</strong>
+ <a name = "operator.exp"></a>
+ <strong>operator.exp (a, b)</strong>
</dt>
<dd>
- Iterates on integer key-value pairs, calling <code>f(k, v)</code> every step.<br/>
- Only applies to values located at integer keys. The table can be a sparse array.
- Iteration will start from the lowest integer key found to the highest one.
- <br/><em>Aliased as <code>forEachi</code></em>.
+ Returns a ^ b. <em>Aliased as <code>op.exp</code>, <code>op.pow</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">f</span>
- a function, prototyped as <code>f (k, v, &hellip;)</code>
+ <li><span class="parameter">b</span>
+ a value
</li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
- (<em>optional</em>)
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a ^ b
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "operator.floordiv"></a>
+ <strong>operator.floordiv (a, b)</strong>
+ </dt>
+ <dd>
+ Performs floor division (//) between <code>a</code> and <code>b</code>. It rounds the quotient towards minus infinity.
+ <em>Aliased as <code>op.floordiv</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+ a // b
+ </ol>
- <h3>See also:</h3>
+
+
+
+</dd>
+ <dt>
+ <a name = "operator.ge"></a>
+ <strong>operator.ge (a, b)</strong>
+ </dt>
+ <dd>
+ Returns logical a and b. <em>Aliased as <code>op.land</code></em>.
+
+
+ <h3>Parameters:</h3>
<ul>
- <a href="index.html#each">each</a>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ a and b
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "at"></a>
- <strong>at (t, ...)</strong>
+ <a name = "operator.ge"></a>
+ <strong>operator.ge (a, b)</strong>
</dt>
<dd>
- Collects values at given keys and return them wrapped in an array.
+ Checks if a is greater or equal to b. <em>Aliased as <code>op.ge</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">...</span>
- A variable number of keys to collect values
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array-list of values
+ a >= b
</ol>
@@ -762,101 +1049,163 @@
</dd>
<dt>
- <a name = "count"></a>
- <strong>count (t[, value])</strong>
+ <a name = "operator.gt"></a>
+ <strong>operator.gt (a, b)</strong>
</dt>
<dd>
- Counts occurrences of a given value in a table. Uses <a href="index.html#isEqual">isEqual</a> to compare values.
+ Checks if a is strictly greater than b. <em>Aliased as <code>op.gt</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">value</span>
- a value to be searched in the table. If not given, the <a href="index.html#size">size</a> of the table will be returned
- (<em>optional</em>)
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the count of occurrences of the given value
+ a > b
</ol>
- <h3>See also:</h3>
+
+
+</dd>
+ <dt>
+ <a name = "operator.intdiv"></a>
+ <strong>operator.intdiv (a, b)</strong>
+ </dt>
+ <dd>
+ Performs integer division between <code>a</code> and <code>b</code>. <em>Aliased as <code>op.intdiv</code></em>.
+
+
+ <h3>Parameters:</h3>
<ul>
- <li><a href="index.html#countf">countf</a></li>
- <li><a href="index.html#size">size</a></li>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ a / b
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "countf"></a>
- <strong>countf (t, f[, ...])</strong>
+ <a name = "operator.le"></a>
+ <strong>operator.le (a, b)</strong>
</dt>
<dd>
- Counts occurrences validating a predicate. Same as <a href="index.html#count">count</a>, but uses an iterator.
- Returns the count for values passing the test <code>f (k, v, &hellip;)</code>
+ Checks if a is less or equal to b. <em>Aliased as <code>op.le</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (k, v, &hellip;)</code>
+ <li><span class="parameter">b</span>
+ a value
</li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
- (<em>optional</em>)
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a &lt;= b
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "operator.length"></a>
+ <strong>operator.length (a)</strong>
+ </dt>
+ <dd>
+ Returns the length of a. <em>Aliased as <code>op.len</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the count of values validating the predicate
+
+<h1>a</h1>
+
</ol>
- <h3>See also:</h3>
+
+
+</dd>
+ <dt>
+ <a name = "operator.lnot"></a>
+ <strong>operator.lnot (a)</strong>
+ </dt>
+ <dd>
+ Returns logical not a. <em>Aliased as <code>op.lnot</code></em>.
+
+
+ <h3>Parameters:</h3>
<ul>
- <li><a href="index.html#count">count</a></li>
- <li><a href="index.html#size">size</a></li>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ not a
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "cycle"></a>
- <strong>cycle (t, n)</strong>
+ <a name = "operator.lor"></a>
+ <strong>operator.lor (a, b)</strong>
</dt>
<dd>
- Loops <code>n</code> times through a table. In case <code>n</code> is omitted, it will loop forever.
- In case <code>n</code> is lower or equal to 0, it returns an empty function.
- <br/><em>Aliased as <code>loop</code></em>.
+ Returns logical a or b. <em>Aliased as <code>op.lor</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">n</span>
- the number of loops
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an iterator function yielding key-value pairs from the passed-in table.
+ a or b
</ol>
@@ -864,32 +1213,55 @@
</dd>
<dt>
- <a name = "map"></a>
- <strong>map (t, f[, ...])</strong>
+ <a name = "operator.lt"></a>
+ <strong>operator.lt (a, b)</strong>
</dt>
<dd>
- Maps <code>f (k, v)</code> on key-value pairs, collects and returns the results.
- <br/><em>Aliased as <code>collect</code></em>.
+ Checks if a is strictly less than b. <em>Aliased as <code>op.lt</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (k, v, &hellip;)</code>
+ <li><span class="parameter">b</span>
+ a value
</li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
- (<em>optional</em>)
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a &lt; b
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "operator.mod"></a>
+ <strong>operator.mod (a, b)</strong>
+ </dt>
+ <dd>
+ Returns a % b. <em>Aliased as <code>op.mod</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a table of results
+ a % b
</ol>
@@ -897,52 +1269,126 @@
</dd>
<dt>
- <a name = "reduce"></a>
- <strong>reduce (t, f[, state])</strong>
+ <a name = "operator.mul"></a>
+ <strong>operator.mul (a, b)</strong>
</dt>
<dd>
- Reduces a table, left-to-right. Folds the table from the first element to the last element
- to a single value, using a given iterator and an initial state.
- The iterator takes a state and a value and returns a new state.
- <br/><em>Aliased as <code>inject</code>, <code>foldl</code></em>.
+ Returns a * b. <em>Aliased as <code>op.mul</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a table
+ <li><span class="parameter">a</span>
+ a value
</li>
- <li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (state, value)</code>
+ <li><span class="parameter">b</span>
+ a value
</li>
- <li><span class="parameter">state</span>
- an initial state of reduction. Defaults to the first value in the table.
- (<em>optional</em>)
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a * b
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "operator.neq"></a>
+ <strong>operator.neq (a, b)</strong>
+ </dt>
+ <dd>
+ Checks if a not equals b. <em>Aliased as <code>op.neq</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the final state of reduction
+ a ~= b
</ol>
- <h3>See also:</h3>
+
+
+</dd>
+ <dt>
+ <a name = "operator.sub"></a>
+ <strong>operator.sub (a, b)</strong>
+ </dt>
+ <dd>
+ Returns a - b. <em>Aliased as <code>op.sub</code></em>.
+
+
+ <h3>Parameters:</h3>
<ul>
- <li><a href="index.html#reduceRight">reduceRight</a></li>
- <li><a href="index.html#reduceby">reduceby</a></li>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ <li><span class="parameter">b</span>
+ a value
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ a - b
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "reduceby"></a>
- <strong>reduceby (t, f, state, pred[, ...])</strong>
+ <a name = "operator.unm"></a>
+ <strong>operator.unm (a)</strong>
</dt>
<dd>
- Reduces values in a table passing a given predicate. Folds the table left-to-right, considering
- only values validating a given predicate.
+ Returns -a. <em>Aliased as <code>op.unm</code>, <code>op.neg</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ -a
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Table_functions"></a>Table functions </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "adjust"></a>
+ <strong>adjust (t, key, f[, ...])</strong>
+ </dt>
+ <dd>
+ Adjusts the value at a given key using a function or a value. In case <code>f</code> is a function,
+ it should be prototyped <code>f(v, ...)</code>. It does not mutate the given table, but rather
+ returns a new array. In case the given <code>key</code> does not exist in <code>t</code>, it throws an error.
<h3>Parameters:</h3>
@@ -950,17 +1396,42 @@
<li><span class="parameter">t</span>
a table
</li>
+ <li><span class="parameter">key</span>
+ a key
+ </li>
<li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (state, value)</code>
+ a function, prototyped as <code>f(v, ...)</code> or a value
</li>
- <li><span class="parameter">state</span>
- an initial state of reduction.
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>f</code>
+ (<em>optional</em>)
</li>
- <li><span class="parameter">pred</span>
- a predicate function <code>pred (k, v, &hellip;)</code> to select values to be considered for reduction
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "all"></a>
+ <strong>all (t, f[, ...])</strong>
+ </dt>
+ <dd>
+ Checks if all values in a table are passing an iterator test.
+ <br/><em>Aliased as <code>every</code></em>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table
+ </li>
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (v, k, ...)</code>
</li>
<li><span class="parameter">...</span>
- optional args to be passed to <code>pred</code>
+ Optional args to be passed to <code>f</code>
(<em>optional</em>)
</li>
</ul>
@@ -968,26 +1439,47 @@
<h3>Returns:</h3>
<ol>
- the final state of reduction
+ <code>true</code> if all values passes the predicate, <code>false</code> otherwise
</ol>
- <h3>See also:</h3>
+
+
+</dd>
+ <dt>
+ <a name = "at"></a>
+ <strong>at (t, ...)</strong>
+ </dt>
+ <dd>
+ Collects values at given keys and return them wrapped in an array.
+
+
+ <h3>Parameters:</h3>
<ul>
- <a href="index.html#reduce">reduce</a>
+ <li><span class="parameter">t</span>
+ a table
+ </li>
+ <li><span class="parameter">...</span>
+ A variable number of keys to collect values
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ an array-list of values
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "reduceRight"></a>
- <strong>reduceRight (t, f[, state])</strong>
+ <a name = "clear"></a>
+ <strong>clear (t)</strong>
</dt>
<dd>
- Reduces a table, right-to-left. Folds the table from the last element to the first element
- to single value, using a given iterator and an initial state.
- The iterator takes a state and a value, and returns a new state.
- <br/><em>Aliased as <code>injectr</code>, <code>foldr</code></em>.
+ Clears a table. All its values become nil.
<h3>Parameters:</h3>
@@ -995,38 +1487,58 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (state, value)</code>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the given table, cleared.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "containsKeys"></a>
+ <strong>containsKeys (t, other)</strong>
+ </dt>
+ <dd>
+ Checks if all the keys of <code>other</code> table exists in table <code>t</code>. It does not
+ compares values. The test is not commutative, i.e table <code>t</code> may contains keys
+ not existing in <code>other</code>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table
</li>
- <li><span class="parameter">state</span>
- an initial state of reduction. Defaults to the last value in the table.
- (<em>optional</em>)
+ <li><span class="parameter">other</span>
+ another table
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the final state of reduction
+ <code>true</code> or <code>false</code>
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#reduce">reduce</a>
+ <a href="index.html#sameKeys">sameKeys</a>
</ul>
</dd>
<dt>
- <a name = "mapReduce"></a>
- <strong>mapReduce (t, f[, state])</strong>
+ <a name = "count"></a>
+ <strong>count (t[, val])</strong>
</dt>
<dd>
- Reduces a table while saving intermediate states. Folds the table left-to-right
- using a given iterator and an initial state. The iterator takes a state and a value,
- and returns a new state. The result is an array of intermediate states.
- <br/><em>Aliased as <code>mapr</code></em>
+ Counts occurrences of a given value in a table. Uses <a href="index.html#isEqual">isEqual</a> to compare values.
<h3>Parameters:</h3>
@@ -1034,11 +1546,8 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (state, value)</code>
- </li>
- <li><span class="parameter">state</span>
- an initial state of reduction. Defaults to the first value in the table.
+ <li><span class="parameter">val</span>
+ a value to be searched in the table. If not given, the <a href="index.html#size">size</a> of the table will be returned
(<em>optional</em>)
</li>
</ul>
@@ -1046,26 +1555,57 @@
<h3>Returns:</h3>
<ol>
- an array of states
+ the count of occurrences of the given value
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#mapReduceRight">mapReduceRight</a>
+ <li><a href="index.html#countf">countf</a></li>
+ <li><a href="index.html#size">size</a></li>
</ul>
</dd>
<dt>
- <a name = "mapReduceRight"></a>
- <strong>mapReduceRight (t, f[, state])</strong>
+ <a name = "countBy"></a>
+ <strong>countBy (t, iter[, ...])</strong>
</dt>
<dd>
- Reduces a table while saving intermediate states. Folds the table right-to-left
- using a given iterator and an initial state. The iterator takes a state and a value,
- and returns a new state. The result is an array of intermediate states.
- <br/><em>Aliased as <code>maprr</code></em>
+ Groups values in a collection and counts them.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table
+ </li>
+ <li><span class="parameter">iter</span>
+ an iterator function, prototyped as <code>iter (v, k, ...)</code>
+ </li>
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>iter</code>
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table of subsets groups names paired with their count
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "countf"></a>
+ <strong>countf (t, f[, ...])</strong>
+ </dt>
+ <dd>
+ Counts the number of values passing a predicate test. Same as <a href="index.html#count">count</a>, but uses an iterator.
+ Returns the count for values passing the test <code>f (v, k, ...)</code>
<h3>Parameters:</h3>
@@ -1074,10 +1614,10 @@
a table
</li>
<li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (state, value)</code>
+ an iterator function, prototyped as <code>f (v, k, ...)</code>
</li>
- <li><span class="parameter">state</span>
- an initial state of reduction. Defaults to the last value in the table.
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>f</code>
(<em>optional</em>)
</li>
</ul>
@@ -1085,26 +1625,26 @@
<h3>Returns:</h3>
<ol>
- an array of states
+ the count of values validating the predicate
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#mapReduce">mapReduce</a>
+ <li><a href="index.html#count">count</a></li>
+ <li><a href="index.html#size">size</a></li>
</ul>
</dd>
<dt>
- <a name = "include"></a>
- <strong>include (t, value)</strong>
+ <a name = "cycle"></a>
+ <strong>cycle (t[, n])</strong>
</dt>
<dd>
- Performs a linear search for a value in a table. It does not work for nested tables.
- The given value can be a function prototyped as <code>f (v, value)</code> which should return true when
- any v in the table equals the value being searched.
- <br/><em>Aliased as <code>any</code>, <code>some</code>, <code>contains</code></em>
+ Loops <code>n</code> times through a table. In case <code>n</code> is omitted, it will loop forever.
+ In case <code>n</code> is lower or equal to 0, it returns an empty function.
+ <br/><em>Aliased as <code>loop</code></em>.
<h3>Parameters:</h3>
@@ -1112,22 +1652,19 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">value</span>
- a value to search for
+ <li><span class="parameter">n</span>
+ the number of loops
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a boolean : <code>true</code> when found, <code>false</code> otherwise
+ an iterator function yielding value-key pairs from the passed-in table.
</ol>
- <h3>See also:</h3>
- <ul>
- <a href="index.html#detect">detect</a>
- </ul>
</dd>
@@ -1138,7 +1675,8 @@
<dd>
Performs a linear search for a value in a table. Returns the key of the value if found.
The given value can be a function prototyped as <code>f (v, value)</code> which should return true when
- any v in the table equals the value being searched.
+ any v in the table equals the value being searched. This function is similar to <a href="index.html#find">find</a>,
+ which is mostly meant to work with array.
<h3>Parameters:</h3>
@@ -1160,17 +1698,19 @@
<h3>See also:</h3>
<ul>
- <a href="index.html#include">include</a>
+ <li><a href="index.html#include">include</a></li>
+ <li><a href="index.html#find">find</a></li>
</ul>
</dd>
<dt>
- <a name = "where"></a>
- <strong>where (t, props)</strong>
+ <a name = "each"></a>
+ <strong>each (t, f[, ...])</strong>
</dt>
<dd>
- Returns all values having specified keys <code>props</code>.
+ Iterates on key-value pairs, calling <code>f (v, k)</code> at every step.
+ <br/><em>Aliased as <code>forEach</code></em>.
<h3>Parameters:</h3>
@@ -1178,21 +1718,54 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">props</span>
- a set of keys
+ <li><span class="parameter">f</span>
+ a function, prototyped as <code>f (v, k, ...)</code>
+ </li>
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>f</code>
+ (<em>optional</em>)
</li>
</ul>
- <h3>Returns:</h3>
- <ol>
- an array of values from the passed-in table
- </ol>
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#eachi">eachi</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "eachi"></a>
+ <strong>eachi (t, f[, ...])</strong>
+ </dt>
+ <dd>
+ Iterates on integer key-value pairs, calling <code>f(v, k)</code> every step. <br/>
+ Only applies to values located at integer keys. The table can be a sparse array.
+ Iteration will start from the lowest integer key found to the highest one.
+ <br/><em>Aliased as <code>forEachi</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table
+ </li>
+ <li><span class="parameter">f</span>
+ a function, prototyped as <code>f (v, k, ...)</code>
+ </li>
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>f</code>
+ (<em>optional</em>)
+ </li>
+ </ul>
+
<h3>See also:</h3>
<ul>
- <a href="index.html#findWhere">findWhere</a>
+ <a href="index.html#each">each</a>
</ul>
@@ -1230,12 +1803,11 @@
</dd>
<dt>
- <a name = "select"></a>
- <strong>select (t, f[, ...])</strong>
+ <a name = "groupBy"></a>
+ <strong>groupBy (t, iter[, ...])</strong>
</dt>
<dd>
- Selects and returns values passing an iterator test.
- <br/><em>Aliased as <code>filter</code></em>.
+ Splits a table into subsets groups.
<h3>Parameters:</h3>
@@ -1243,11 +1815,11 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (k, v, &hellip;)</code>
+ <li><span class="parameter">iter</span>
+ an iterator function, prototyped as <code>iter (v, k, ...)</code>
</li>
<li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
+ Optional args to be passed to <code>iter</code>
(<em>optional</em>)
</li>
</ul>
@@ -1255,24 +1827,54 @@
<h3>Returns:</h3>
<ol>
- the selected values
+ a table of subsets groups
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "include"></a>
+ <strong>include (t, value)</strong>
+ </dt>
+ <dd>
+ Performs a linear search for a value in a table. It does not work for nested tables.
+ The given value can be a function prototyped as <code>f (v, value)</code> which should return true when
+ any v in the table equals the value being searched.
+ <br/><em>Aliased as <code>any</code>, <code>some</code>, <code>contains</code></em>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table
+ </li>
+ <li><span class="parameter">value</span>
+ a value to search for
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a boolean : <code>true</code> when found, <code>false</code> otherwise
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#reject">reject</a>
+ <a href="index.html#detect">detect</a>
</ul>
</dd>
<dt>
- <a name = "reject"></a>
- <strong>reject (t, f[, ...])</strong>
+ <a name = "invoke"></a>
+ <strong>invoke (t, method[, ...])</strong>
</dt>
<dd>
- Clones a table while dropping values passing an iterator test.
- <br/><em>Aliased as <code>discard</code></em>
+ Invokes a method on each value in a table.
<h3>Parameters:</h3>
@@ -1280,11 +1882,11 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (k, v, &hellip;)</code>
+ <li><span class="parameter">method</span>
+ a function, prototyped as <code>f (v, ...)</code>
</li>
<li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
+ Optional args to be passed to <code>method</code>
(<em>optional</em>)
</li>
</ul>
@@ -1292,24 +1894,24 @@
<h3>Returns:</h3>
<ol>
- the remaining values
+ the result of the call <code>f (v, ...)</code>
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#select">select</a>
+ <a href="index.html#pluck">pluck</a>
</ul>
</dd>
<dt>
- <a name = "all"></a>
- <strong>all (t, f[, ...])</strong>
+ <a name = "map"></a>
+ <strong>map (t, f[, ...])</strong>
</dt>
<dd>
- Checks if all values in a table are passing an iterator test.
- <br/><em>Aliased as <code>every</code></em>
+ Maps <code>f (v, k)</code> on value-key pairs, collects and returns the results.
+ <br/><em>Aliased as <code>collect</code></em>.
<h3>Parameters:</h3>
@@ -1318,7 +1920,7 @@
a table
</li>
<li><span class="parameter">f</span>
- an iterator function, prototyped as <code>f (k, v, &hellip;)</code>
+ an iterator function, prototyped as <code>f (v, k, ...)</code>
</li>
<li><span class="parameter">...</span>
Optional args to be passed to <code>f</code>
@@ -1329,7 +1931,7 @@
<h3>Returns:</h3>
<ol>
- <code>true</code> if all values passes the predicate, <code>false</code> otherwise
+ a table of results
</ol>
@@ -1337,11 +1939,14 @@
</dd>
<dt>
- <a name = "invoke"></a>
- <strong>invoke (t, method[, ...])</strong>
+ <a name = "mapReduce"></a>
+ <strong>mapReduce (t, f[, state])</strong>
</dt>
<dd>
- Invokes a method on each value in a table.
+ Reduces a table while saving intermediate states. Folds the table left-to-right
+ using a given iterator and an initial state. The iterator takes a state and a value,
+ and returns a new state. The result is an array of intermediate states.
+ <br/><em>Aliased as <code>mapr</code></em>
<h3>Parameters:</h3>
@@ -1349,11 +1954,11 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">method</span>
- a function, prototyped as <code>f (v, &hellip;)</code>
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (state, value)</code>
</li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>method</code>
+ <li><span class="parameter">state</span>
+ an initial state of reduction. Defaults to the first value in the table.
(<em>optional</em>)
</li>
</ul>
@@ -1361,23 +1966,26 @@
<h3>Returns:</h3>
<ol>
- the result of the call <code>f (v, &hellip;)</code>
+ an array of states
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#pluck">pluck</a>
+ <a href="index.html#mapReduceRight">mapReduceRight</a>
</ul>
</dd>
<dt>
- <a name = "pluck"></a>
- <strong>pluck (t, key)</strong>
+ <a name = "mapReduceRight"></a>
+ <strong>mapReduceRight (t, f[, state])</strong>
</dt>
<dd>
- Extracts values in a table having a given key.
+ Reduces a table while saving intermediate states. Folds the table right-to-left
+ using a given iterator and an initial state. The iterator takes a state and a value,
+ and returns a new state. The result is an array of intermediate states.
+ <br/><em>Aliased as <code>maprr</code></em>
<h3>Parameters:</h3>
@@ -1385,18 +1993,26 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">key</span>
- a key, will be used to index in each value: <code>value[key]</code>
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (state, value)</code>
+ </li>
+ <li><span class="parameter">state</span>
+ an initial state of reduction. Defaults to the last value in the table.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array of values having the given key
+ an array of states
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#mapReduce">mapReduce</a>
+ </ul>
</dd>
@@ -1405,7 +2021,7 @@
<strong>max (t[, transform[, ...]])</strong>
</dt>
<dd>
- Returns the max value in a collection. If an transformation function is passed, it will
+ Returns the max value in a collection. If a <code>transform</code> function is passed, it will
be used to evaluate values by which all objects will be sorted.
@@ -1415,7 +2031,7 @@
a table
</li>
<li><span class="parameter">transform</span>
- a transformation function, prototyped as <code>transform (v, &hellip;)</code>, defaults to <a href="index.html#identity">identity</a>
+ a transformation function, prototyped as <code>transform (v, ...)</code>, defaults to <a href="index.html#identity">identity</a>
(<em>optional</em>)
</li>
<li><span class="parameter">...</span>
@@ -1443,7 +2059,7 @@
<strong>min (t[, transform[, ...]])</strong>
</dt>
<dd>
- Returns the min value in a collection. If an transformation function is passed, it will
+ Returns the min value in a collection. If a <code>transform</code> function is passed, it will
be used to evaluate values by which all objects will be sorted.
@@ -1453,7 +2069,7 @@
a table
</li>
<li><span class="parameter">transform</span>
- a transformation function, prototyped as <code>transform (v, &hellip;)</code>, defaults to <a href="index.html#identity">identity</a>
+ a transformation function, prototyped as <code>transform (v, ...)</code>, defaults to <a href="index.html#identity">identity</a>
(<em>optional</em>)
</li>
<li><span class="parameter">...</span>
@@ -1477,12 +2093,11 @@
</dd>
<dt>
- <a name = "shuffle"></a>
- <strong>shuffle (t[, seed])</strong>
+ <a name = "pluck"></a>
+ <strong>pluck (t, key)</strong>
</dt>
<dd>
- Returns a shuffled copy of a given collection. If a seed is provided, it will
- be used to init the pseudo random number generator (using <a href="https://www.lua.org/manual/5.1/manual.html#pdf-math.randomseed">math.randomseed</a>).
+ Extracts values in a table having a given key.
<h3>Parameters:</h3>
@@ -1490,16 +2105,15 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">seed</span>
- a seed
- (<em>optional</em>)
+ <li><span class="parameter">key</span>
+ a key, will be used to index in each value: <code>value[key]</code>
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a shuffled copy of the given table
+ an array of values having the given key
</ol>
@@ -1507,40 +2121,54 @@
</dd>
<dt>
- <a name = "same"></a>
- <strong>same (a, b)</strong>
+ <a name = "reduce"></a>
+ <strong>reduce (t, f[, state])</strong>
</dt>
<dd>
- Checks if two tables are the same. It compares if both tables features the same values,
- but not necessarily at the same keys.
+ Reduces a table, left-to-right. Folds the table from the first element to the last element
+ to a single value, using a given iterator and an initial state.
+ The iterator takes a state and a value and returns a new state.
+ <br/><em>Aliased as <code>inject</code>, <code>foldl</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">a</span>
+ <li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">b</span>
- another table
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (state, value)</code>
+ </li>
+ <li><span class="parameter">state</span>
+ an initial state of reduction. Defaults to the first value in the table.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ the final state of reduction
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#reduceRight">reduceRight</a></li>
+ <li><a href="index.html#reduceby">reduceby</a></li>
+ </ul>
</dd>
<dt>
- <a name = "sort"></a>
- <strong>sort (t[, comp])</strong>
+ <a name = "reduceRight"></a>
+ <strong>reduceRight (t, f[, state])</strong>
</dt>
<dd>
- Sorts a table, in-place. If a comparison function is given, it will be used to sort values.
+ Reduces a table, right-to-left. Folds the table from the last element to the first element
+ to single value, using a given iterator and an initial state.
+ The iterator takes a state and a value, and returns a new state.
+ <br/><em>Aliased as <code>injectr</code>, <code>foldr</code></em>.
<h3>Parameters:</h3>
@@ -1548,8 +2176,11 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">comp</span>
- a comparison function prototyped as <code>comp (a, b)</code>, defaults to <tt>&lt;</tt> operator.
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (state, value)</code>
+ </li>
+ <li><span class="parameter">state</span>
+ an initial state of reduction. Defaults to the last value in the table.
(<em>optional</em>)
</li>
</ul>
@@ -1557,25 +2188,24 @@
<h3>Returns:</h3>
<ol>
- the initial table, sorted.
+ the final state of reduction
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#sortBy">sortBy</a>
+ <a href="index.html#reduce">reduce</a>
</ul>
</dd>
<dt>
- <a name = "sortBy"></a>
- <strong>sortBy (t[, transform[, comp]])</strong>
+ <a name = "reduceby"></a>
+ <strong>reduceby (t, f, pred[, state[, ...]])</strong>
</dt>
<dd>
- Sorts a table in-place using a transform. Values are ranked in a custom order of the results of
- running <code>transform (v)</code> on all values. <code>transform</code> may also be a string name property sort by.
- <code>comp</code> is a comparison function.
+ Reduces values in a table passing a given predicate. Folds the table left-to-right, considering
+ only values validating a given predicate.
<h3>Parameters:</h3>
@@ -1583,12 +2213,18 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">transform</span>
- a <code>transform</code> function to sort elements prototyped as <code>transform (v)</code>. Defaults to <a href="index.html#identity">identity</a>
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (state, value)</code>
+ </li>
+ <li><span class="parameter">pred</span>
+ a predicate function <code>pred (v, k, ...)</code> to select values to be considered for reduction
+ </li>
+ <li><span class="parameter">state</span>
+ an initial state of reduction. Defaults to the first value in the table of selected values.
(<em>optional</em>)
</li>
- <li><span class="parameter">comp</span>
- a comparision function, defaults to the <code>&lt;</code> operator
+ <li><span class="parameter">...</span>
+ optional args to be passed to <code>pred</code>
(<em>optional</em>)
</li>
</ul>
@@ -1596,23 +2232,24 @@
<h3>Returns:</h3>
<ol>
- a new array of sorted values
+ the final state of reduction
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#sort">sort</a>
+ <a href="index.html#reduce">reduce</a>
</ul>
</dd>
<dt>
- <a name = "groupBy"></a>
- <strong>groupBy (t, iter[, ...])</strong>
+ <a name = "reject"></a>
+ <strong>reject (t, f[, ...])</strong>
</dt>
<dd>
- Splits a table into subsets groups.
+ Clones a table while dropping values passing an iterator test.
+ <br/><em>Aliased as <code>discard</code></em>
<h3>Parameters:</h3>
@@ -1620,11 +2257,11 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">iter</span>
- an iterator function, prototyped as <code>iter (k, v, &hellip;)</code>
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (v, k, ...)</code>
</li>
<li><span class="parameter">...</span>
- Optional args to be passed to <code>iter</code>
+ Optional args to be passed to <code>f</code>
(<em>optional</em>)
</li>
</ul>
@@ -1632,19 +2269,85 @@
<h3>Returns:</h3>
<ol>
- a table of subsets groups
+ the remaining values
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#select">select</a>
+ </ul>
</dd>
<dt>
- <a name = "countBy"></a>
- <strong>countBy (t, iter[, ...])</strong>
+ <a name = "same"></a>
+ <strong>same (a, b)</strong>
</dt>
<dd>
- Groups values in a collection and counts them.
+ Checks if two tables are the same. It compares if both tables features the same values,
+ but not necessarily at the same keys.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a table
+ </li>
+ <li><span class="parameter">b</span>
+ another table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>true</code> or <code>false</code>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sameKeys"></a>
+ <strong>sameKeys (tA, tB)</strong>
+ </dt>
+ <dd>
+ Checks if both given tables have the same keys. It does not compares values.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tA</span>
+ a table
+ </li>
+ <li><span class="parameter">tB</span>
+ another table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>true</code> or <code>false</code>
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#containsKeys">containsKeys</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "select"></a>
+ <strong>select (t, f[, ...])</strong>
+ </dt>
+ <dd>
+ Selects and returns values passing an iterator test.
+ <br/><em>Aliased as <code>filter</code></em>.
<h3>Parameters:</h3>
@@ -1652,11 +2355,11 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">iter</span>
- an iterator function, prototyped as <code>iter (k, v, &hellip;)</code>
+ <li><span class="parameter">f</span>
+ an iterator function, prototyped as <code>f (v, k, ...)</code>
</li>
<li><span class="parameter">...</span>
- Optional args to be passed to <code>iter</code>
+ Optional args to be passed to <code>f</code>
(<em>optional</em>)
</li>
</ul>
@@ -1664,10 +2367,14 @@
<h3>Returns:</h3>
<ol>
- a table of subsets groups names paired with their count
+ the selected values
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#reject">reject</a>
+ </ul>
</dd>
@@ -1704,13 +2411,11 @@
</dd>
<dt>
- <a name = "containsKeys"></a>
- <strong>containsKeys (t, other)</strong>
+ <a name = "sort"></a>
+ <strong>sort (t[, comp])</strong>
</dt>
<dd>
- Checks if all the keys of <code>other</code> table exists in table <code>t</code>. It does not
- compares values. The test is not commutative, i.e table <code>t</code> may contains keys
- not existing in <code>other</code>.
+ Sorts a table, in-place. If a comparison function is given, it will be used to sort values.
<h3>Parameters:</h3>
@@ -1718,53 +2423,93 @@
<li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">other</span>
- another table
+ <li><span class="parameter">comp</span>
+ a comparison function prototyped as <code>comp (a, b)</code>, defaults to <tt>&lt;</tt> operator.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ the given table, sorted.
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#sameKeys">sameKeys</a>
+ <a href="index.html#sortBy">sortBy</a>
</ul>
</dd>
<dt>
- <a name = "sameKeys"></a>
- <strong>sameKeys (tA, tB)</strong>
+ <a name = "sortBy"></a>
+ <strong>sortBy (t[, transform[, comp]])</strong>
</dt>
<dd>
- Checks if both given tables have the same keys. It does not compares values.
+ Sorts a table in-place using a transform. Values are ranked in a custom order of the results of
+ running <code>transform (v)</code> on all values. <code>transform</code> may also be a string name property sort by.
+ <code>comp</code> is a comparison function.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">tA</span>
+ <li><span class="parameter">t</span>
a table
</li>
- <li><span class="parameter">tB</span>
- another table
+ <li><span class="parameter">transform</span>
+ a <code>transform</code> function to sort elements prototyped as <code>transform (v)</code>. Defaults to <a href="index.html#identity">identity</a>
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">comp</span>
+ a comparison function, defaults to the <code>&lt;</code> operator
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ a new array of sorted values
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#containsKeys">containsKeys</a>
+ <a href="index.html#sort">sort</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "where"></a>
+ <strong>where (t, props)</strong>
+ </dt>
+ <dd>
+ Returns all values having specified keys <code>props</code>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table
+ </li>
+ <li><span class="parameter">props</span>
+ a set of keys
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an array of values from the passed-in table
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#findWhere">findWhere</a>
</ul>
@@ -1774,13 +2519,12 @@
<dl class="function">
<dt>
- <a name = "sample"></a>
- <strong>sample (array[, n[, seed]])</strong>
+ <a name = "addTop"></a>
+ <strong>addTop (array, ...)</strong>
</dt>
<dd>
- Samples <code>n</code> random values from an array. If <code>n</code> is not specified, returns a single element.
- It uses internally <a href="index.html#shuffle">shuffle</a> to shuffle the array before sampling values. If <code>seed</code> is passed,
- it will be used for shuffling.
+ Adds all passed-in values at the top of an array. The last elements will bubble to the
+ top of the given array.
<h3>Parameters:</h3>
@@ -1788,38 +2532,33 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">n</span>
- a number of elements to be sampled. Defaults to 1.
- (<em>optional</em>)
- </li>
- <li><span class="parameter">seed</span>
- an optional seed for shuffling
- (<em>optional</em>)
+ <li><span class="parameter">...</span>
+ a variable number of arguments
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array of selected values or a single value when <code>n</code> == 1
+ the passed-in array with new values added
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#sampleProb">sampleProb</a>
+ <li><a href="index.html#prepend">prepend</a></li>
+ <li><a href="index.html#push">push</a></li>
</ul>
</dd>
<dt>
- <a name = "sampleProb"></a>
- <strong>sampleProb (array, prob[, seed])</strong>
+ <a name = "aperture"></a>
+ <strong>aperture (array[, n])</strong>
</dt>
<dd>
- Return elements from a sequence with a given probability. It considers each value independently.
- Providing a seed will result in deterministic sampling. Given the same seed it will return the same sample
- every time.
+ Iterator returning sliding partitions of an array.
+ <br/><em>Aliased as <code>sliding</code></em>
<h3>Parameters:</h3>
@@ -1827,11 +2566,8 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">prob</span>
- a probability for each element in array to be selected
- </li>
- <li><span class="parameter">seed</span>
- an optional seed for deterministic sampling
+ <li><span class="parameter">n</span>
+ the size of partitions. Defaults to 2 (and then behaves like <a href="index.html#pairwise">pairwise</a>)
(<em>optional</em>)
</li>
</ul>
@@ -1839,36 +2575,41 @@
<h3>Returns:</h3>
<ol>
- an array of selected values
+ an iterator function
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#sample">sample</a>
+ <li><a href="index.html#partition">partition</a></li>
+ <li><a href="index.html#overlapping">overlapping</a></li>
+ <li><a href="index.html#pairwise">pairwise</a></li>
</ul>
</dd>
<dt>
- <a name = "toArray"></a>
- <strong>toArray (...)</strong>
+ <a name = "append"></a>
+ <strong>append (array, other)</strong>
</dt>
<dd>
- Converts a list of arguments to an array.
+ Clones array and appends values from another array.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">...</span>
- a list of arguments
+ <li><span class="parameter">array</span>
+ an array
+ </li>
+ <li><span class="parameter">other</span>
+ an array
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array of all passed-in args
+ a new array
</ol>
@@ -1876,24 +2617,25 @@
</dd>
<dt>
- <a name = "find"></a>
- <strong>find (array, value[, from])</strong>
+ <a name = "chunk"></a>
+ <strong>chunk (array, f[, ...])</strong>
</dt>
<dd>
- Looks for the first occurrence of a given value in an array. Returns the value index if found.
- Uses <a href="index.html#isEqual">isEqual</a> to compare values.
+ Chunks together consecutive values. Values are chunked on the basis of the return
+ value of a provided predicate <code>f (k, v, ...)</code>. Consecutive elements which return
+ the same value are chunked together. Leaves the first argument untouched if it is not an array.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- an array of values
+ an array
</li>
- <li><span class="parameter">value</span>
- a value to lookup for
+ <li><span class="parameter">f</span>
+ an iterator function prototyped as <code>f (v, k, ...)</code>
</li>
- <li><span class="parameter">from</span>
- the index from where the search will start. Defaults to 1.
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>f</code>
(<em>optional</em>)
</li>
</ul>
@@ -1901,19 +2643,23 @@
<h3>Returns:</h3>
<ol>
- the index of the value if found in the array, <code>nil</code> otherwise.
+ a table of chunks (arrays)
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#zip">zip</a>
+ </ul>
</dd>
<dt>
- <a name = "reverse"></a>
- <strong>reverse (array)</strong>
+ <a name = "compact"></a>
+ <strong>compact (array)</strong>
</dt>
<dd>
- Returns an array where values are in reverse order. The passed-in array should not be sparse.
+ Returns all truthy values (removes <code>falses</code> and <code>nils</code>).
<h3>Parameters:</h3>
@@ -1926,7 +2672,7 @@
<h3>Returns:</h3>
<ol>
- a reversed array
+ a new array
</ol>
@@ -1934,29 +2680,31 @@
</dd>
<dt>
- <a name = "fill"></a>
- <strong>fill (array, value[, i[, j]])</strong>
+ <a name = "concat"></a>
+ <strong>concat (array[, sep[, i[, j]]])</strong>
</dt>
<dd>
- Replaces elements in a given array with a given value. In case <code>i</code> and <code>j</code> are given
- it will only replaces values at indexes between <code>[i,j]</code>. In case <code>j</code> is greather than the array
- size, it will append new values, increasing the array.
+ Concatenates values in a given array. Handles booleans as well. If <code>sep</code> string is
+ passed, it will be used as a separator. Passing <code>i</code> and <code>j</code> will result in concatenating
+ only values within <code>[i, j]</code> range.
+ <br/><em>Aliased as <code>join</code></em>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- an array
+ a given array
</li>
- <li><span class="parameter">value</span>
- a value
+ <li><span class="parameter">sep</span>
+ a separator string, defaults to the empty string <code>&apos;&apos;</code>.
+ (<em>optional</em>)
</li>
<li><span class="parameter">i</span>
- the index from which to start replacing values. Defaults to 1.
+ the starting index, defaults to 1.
(<em>optional</em>)
</li>
<li><span class="parameter">j</span>
- the index where to stop replacing values. Defaults to the array size.
+ the final index, defaults to the array length.
(<em>optional</em>)
</li>
</ul>
@@ -1964,7 +2712,7 @@
<h3>Returns:</h3>
<ol>
- the original array with values changed
+ a string
</ol>
@@ -1972,13 +2720,12 @@
</dd>
<dt>
- <a name = "selectWhile"></a>
- <strong>selectWhile (array, f[, ...])</strong>
+ <a name = "difference"></a>
+ <strong>difference (array, another)</strong>
</dt>
<dd>
- Collects values from a given array. The passed-in array should not be sparse.
- This function collects values as long as they satisfy a given predicate and returns on the first falsy test.
- <br/><em>Aliased as <code>takeWhile</code></em>
+ Returns values from an array not present in all passed-in args.
+ <br/><em>Aliased as <code>without</code> and <code>diff</code></em>
<h3>Parameters:</h3>
@@ -1986,25 +2733,23 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">f</span>
- an iterator function prototyped as <code>f (k, v, &hellip;)</code>
- </li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
- (<em>optional</em>)
+ <li><span class="parameter">another</span>
+ array
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new table containing all values collected
+ a new array
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#dropWhile">dropWhile</a>
+ <li><a href="index.html#union">union</a></li>
+ <li><a href="index.html#intersection">intersection</a></li>
+ <li><a href="index.html#symmetricDifference">symmetricDifference</a></li>
</ul>
@@ -2025,7 +2770,7 @@
an array
</li>
<li><span class="parameter">f</span>
- an iterator function prototyped as <code>f (k,v, &hellip;)</code>
+ an iterator function prototyped as <code>f (v, k, ...)</code>
</li>
<li><span class="parameter">...</span>
Optional args to be passed to <code>f</code>
@@ -2040,17 +2785,21 @@
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#selectWhile">selectWhile</a>
+ </ul>
</dd>
<dt>
- <a name = "sortedIndex"></a>
- <strong>sortedIndex (array, the[, comp[, sort]])</strong>
+ <a name = "fill"></a>
+ <strong>fill (array, value[, i[, j]])</strong>
</dt>
<dd>
- Returns the index at which a value should be inserted. This index is evaluated so
- that it maintains the sort. If a comparison function is passed, it will be used to sort
- values.
+ Replaces elements in a given array with a given value. In case <code>i</code> and <code>j</code> are given
+ it will only replaces values at indexes between <code>[i,j]</code>. In case <code>j</code> is greater than the array
+ size, it will append new values, increasing the array size.
<h3>Parameters:</h3>
@@ -2058,15 +2807,15 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">the</span>
- value to be inserted
+ <li><span class="parameter">value</span>
+ a value
</li>
- <li><span class="parameter">comp</span>
- an comparison function prototyped as <code>f (a, b)</code>, defaults to <tt>&lt;</tt> operator.
+ <li><span class="parameter">i</span>
+ the index from which to start replacing values. Defaults to 1.
(<em>optional</em>)
</li>
- <li><span class="parameter">sort</span>
- whether or not the passed-in array should be sorted
+ <li><span class="parameter">j</span>
+ the index where to stop replacing values. Defaults to the array size.
(<em>optional</em>)
</li>
</ul>
@@ -2074,7 +2823,7 @@
<h3>Returns:</h3>
<ol>
- number the index at which the passed-in value should be inserted
+ the original array with values changed
</ol>
@@ -2082,43 +2831,48 @@
</dd>
<dt>
- <a name = "indexOf"></a>
- <strong>indexOf (array, value)</strong>
+ <a name = "find"></a>
+ <strong>find (array, value[, from])</strong>
</dt>
<dd>
- Returns the index of the first occurence of value in an array.
+ Looks for the first occurrence of a given value in an array. Returns the value index if found.
+ Uses <a href="index.html#isEqual">isEqual</a> to compare values.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- an array
+ an array of values
</li>
<li><span class="parameter">value</span>
- the value to search for
+ a value to lookup for
+ </li>
+ <li><span class="parameter">from</span>
+ the index from where the search will start. Defaults to 1.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the index of the passed-in value
+ the index of the value if found in the array, <code>nil</code> otherwise.
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#lastIndexOf">lastIndexOf</a>
+ <a href="index.html#detect">detect</a>
</ul>
</dd>
<dt>
- <a name = "lastIndexOf"></a>
- <strong>lastIndexOf (array, value)</strong>
+ <a name = "findIndex"></a>
+ <strong>findIndex (array, predicate[, ...])</strong>
</dt>
<dd>
- Returns the index of the last occurrence of value in an array.
+ Returns the first index at which a predicate returns true.
<h3>Parameters:</h3>
@@ -2126,31 +2880,35 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">value</span>
- the value to search for
+ <li><span class="parameter">predicate</span>
+ a predicate function prototyped as <code>predicate (v, k, ...)</code>
+ </li>
+ <li><span class="parameter">...</span>
+ optional arguments to <code>pred</code>
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the index of the last occurrence of the passed-in value or <strong>nil</strong>
+ the index found or <strong>nil</strong>
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#indexOf">indexOf</a>
+ <a href="index.html#findLastIndex">findLastIndex</a>
</ul>
</dd>
<dt>
- <a name = "findIndex"></a>
- <strong>findIndex (array, predicate[, ...])</strong>
+ <a name = "findLastIndex"></a>
+ <strong>findLastIndex (array, predicate[, ...])</strong>
</dt>
<dd>
- Returns the first index at which a predicate returns true.
+ Returns the last index at which a predicate returns true.
<h3>Parameters:</h3>
@@ -2159,7 +2917,7 @@
an array
</li>
<li><span class="parameter">predicate</span>
- a predicate function prototyped as <code>predicate (k, v, &hellip;)</code>
+ a predicate function prototyped as <code>predicate (k, v, ...)</code>
</li>
<li><span class="parameter">...</span>
optional arguments to <code>pred</code>
@@ -2176,17 +2934,18 @@
<h3>See also:</h3>
<ul>
- <a href="index.html#findLastIndex">findLastIndex</a>
+ <a href="index.html#findIndex">findIndex</a>
</ul>
</dd>
<dt>
- <a name = "findLastIndex"></a>
- <strong>findLastIndex (array, predicate[, ...])</strong>
+ <a name = "first"></a>
+ <strong>first (array[, n])</strong>
</dt>
<dd>
- Returns the last index at which a predicate returns true.
+ Returns the first N values in an array.
+ <br/><em>Aliased as <code>head</code>, <code>take</code> </em>
<h3>Parameters:</h3>
@@ -2194,11 +2953,8 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">predicate</span>
- a predicate function prototyped as <code>predicate (k, v, &hellip;)</code>
- </li>
- <li><span class="parameter">...</span>
- optional arguments to <code>pred</code>
+ <li><span class="parameter">n</span>
+ the number of values to be collected, defaults to 1.
(<em>optional</em>)
</li>
</ul>
@@ -2206,24 +2962,25 @@
<h3>Returns:</h3>
<ol>
- the index found or <strong>nil</strong>
+ a new array
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#findIndex">findIndex</a>
+ <li><a href="index.html#initial">initial</a></li>
+ <li><a href="index.html#last">last</a></li>
+ <li><a href="index.html#rest">rest</a></li>
</ul>
</dd>
<dt>
- <a name = "addTop"></a>
- <strong>addTop (array, ...)</strong>
+ <a name = "flatten"></a>
+ <strong>flatten (array[, shallow])</strong>
</dt>
<dd>
- Adds all passed-in values at the top of an array. The last elements will bubble to the
- top of the given array.
+ Flattens a nested array. Passing <code>shallow</code> will only flatten at the first level.
<h3>Parameters:</h3>
@@ -2231,31 +2988,28 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">...</span>
- a variable number of arguments
+ <li><span class="parameter">shallow</span>
+ specifies the flattening depth. Defaults to <code>false</code>.`
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the passed-in array with new values added
+ a flattened array
</ol>
- <h3>See also:</h3>
- <ul>
- <a href="index.html#push">push</a>
- </ul>
</dd>
<dt>
- <a name = "push"></a>
- <strong>push (array, ...)</strong>
+ <a name = "indexOf"></a>
+ <strong>indexOf (array, value)</strong>
</dt>
<dd>
- Pushes all passed-in values at the end of an array.
+ Returns the index of the first occurrence of value in an array.
<h3>Parameters:</h3>
@@ -2263,32 +3017,31 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">...</span>
- a variable number of arguments
+ <li><span class="parameter">value</span>
+ the value to search for
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the passed-in array with new added values
+ the index of the passed-in value
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#addTop">addTop</a>
+ <a href="index.html#lastIndexOf">lastIndexOf</a>
</ul>
</dd>
<dt>
- <a name = "pop"></a>
- <strong>pop (array[, n])</strong>
+ <a name = "initial"></a>
+ <strong>initial (array[, n])</strong>
</dt>
<dd>
- Removes and returns the values at the top of a given array.
- <br/><em>Aliased as <code>shift</code></em>
+ Returns all values in an array excluding the last N values.
<h3>Parameters:</h3>
@@ -2297,7 +3050,7 @@
an array
</li>
<li><span class="parameter">n</span>
- the number of values to be popped. Defaults to 1.
+ the number of values to be left, defaults to the array length.
(<em>optional</em>)
</li>
</ul>
@@ -2305,57 +3058,56 @@
<h3>Returns:</h3>
<ol>
- the popped values
+ a new array
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#unshift">unshift</a>
+ <li><a href="index.html#first">first</a></li>
+ <li><a href="index.html#last">last</a></li>
+ <li><a href="index.html#rest">rest</a></li>
</ul>
</dd>
<dt>
- <a name = "unshift"></a>
- <strong>unshift (array[, n])</strong>
+ <a name = "interleave"></a>
+ <strong>interleave (...)</strong>
</dt>
<dd>
- Removes and returns the values at the end of a given array.
+ Interleaves arrays. It returns a single array made of values from all
+ passed in arrays in their given order, interleaved.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">array</span>
- an array
- </li>
- <li><span class="parameter">n</span>
- the number of values to be unshifted. Defaults to 1.
- (<em>optional</em>)
+ <li><span class="parameter">...</span>
+ a variable list of arrays
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the values
+ a new array
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#pop">pop</a>
+ <a href="index.html#interpose">interpose</a>
</ul>
</dd>
<dt>
- <a name = "pull"></a>
- <strong>pull (array, ...)</strong>
+ <a name = "interpose"></a>
+ <strong>interpose (array, value)</strong>
</dt>
<dd>
- Removes all provided values in a given array.
- <br/><em>Aliased as <code>remove</code></em>
+ Interposes value in-between consecutive pair of values in array.
+ <br/><em>Aliased as <code>intersperse</code></em>
<h3>Parameters:</h3>
@@ -2363,28 +3115,32 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">...</span>
- a variable number of values to be removed from the array
+ <li><span class="parameter">value</span>
+ a value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the passed-in array with values removed
+ a new array
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#interleave">interleave</a>
+ </ul>
</dd>
<dt>
- <a name = "removeRange"></a>
- <strong>removeRange (array[, start[, finish]])</strong>
+ <a name = "intersection"></a>
+ <strong>intersection (array, ...)</strong>
</dt>
<dd>
- Removes values at index within the range <code>[start, finish]</code>.
- <br/><em>Aliased as <code>rmRange</code>, <code>chop</code></em>
+ Returns the intersection of all passed-in arrays.
+ Each value in the result is present in each of the passed-in arrays.
<h3>Parameters:</h3>
@@ -2392,71 +3148,62 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">start</span>
- the lower bound index, defaults to the first index in the array.
- (<em>optional</em>)
- </li>
- <li><span class="parameter">finish</span>
- the upper bound index, defaults to the array length.
- (<em>optional</em>)
+ <li><span class="parameter">...</span>
+ a variable number of array arguments
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the passed-in array with values removed
+ a new array
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#difference">difference</a></li>
+ <li><a href="index.html#union">union</a></li>
+ <li><a href="index.html#symmetricDifference">symmetricDifference</a></li>
+ </ul>
</dd>
<dt>
- <a name = "chunk"></a>
- <strong>chunk (array, f[, ...])</strong>
+ <a name = "invert"></a>
+ <strong>invert (array)</strong>
</dt>
<dd>
- Chunks together consecutive values. Values are chunked on the basis of the return
- value of a provided predicate <code>f (k, v, &hellip;)</code>. Consecutive elements which return
- the same value are chunked together. Leaves the first argument untouched if it is not an array.
+ Swaps keys with values. Produces a new array where previous keys are now values,
+ while previous values are now keys.
+ <br/><em>Aliased as <code>mirror</code></em>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- an array
- </li>
- <li><span class="parameter">f</span>
- an iterator function prototyped as <code>f (k, v, &hellip;)</code>
- </li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>f</code>
- (<em>optional</em>)
+ a given array
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a table of chunks (arrays)
+ a new array
</ol>
- <h3>See also:</h3>
- <ul>
- <a href="index.html#zip">zip</a>
- </ul>
</dd>
<dt>
- <a name = "slice"></a>
- <strong>slice (array[, start[, finish]])</strong>
+ <a name = "isunique"></a>
+ <strong>isunique (array)</strong>
</dt>
<dd>
- Slices values indexed within <code>[start, finish]</code> range.
- <br/><em>Aliased as <code>_.sub</code></em>
+ Checks if a given array contains distinct values. Such an array is made of distinct elements,
+ which only occur once in this array.
+ <br/><em>Aliased as <code>isuniq</code></em>
<h3>Parameters:</h3>
@@ -2464,33 +3211,28 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">start</span>
- the lower bound index, defaults to the first index in the array.
- (<em>optional</em>)
- </li>
- <li><span class="parameter">finish</span>
- the upper bound index, defaults to the array length.
- (<em>optional</em>)
- </li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array of sliced values
+ <code>true</code> if the given array is unique, <code>false</code> otherwise.
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#unique">unique</a>
+ </ul>
</dd>
<dt>
- <a name = "first"></a>
- <strong>first (array[, n])</strong>
+ <a name = "last"></a>
+ <strong>last (array[, n])</strong>
</dt>
<dd>
- Returns the first N values in an array.
- <br/><em>Aliased as <code>head</code>, <code>take</code></em>
+ Returns the last N values in an array.
<h3>Parameters:</h3>
@@ -2499,7 +3241,7 @@
an array
</li>
<li><span class="parameter">n</span>
- the number of values to be collected, defaults to 1.
+ the number of values to be collected, defaults to the array length.
(<em>optional</em>)
</li>
</ul>
@@ -2513,19 +3255,19 @@
<h3>See also:</h3>
<ul>
+ <li><a href="index.html#first">first</a></li>
<li><a href="index.html#initial">initial</a></li>
- <li><a href="index.html#last">last</a></li>
<li><a href="index.html#rest">rest</a></li>
</ul>
</dd>
<dt>
- <a name = "initial"></a>
- <strong>initial (array[, n])</strong>
+ <a name = "lastIndexOf"></a>
+ <strong>lastIndexOf (array, value)</strong>
</dt>
<dd>
- Returns all values in an array excluding the last N values.
+ Returns the index of the last occurrence of value in an array.
<h3>Parameters:</h3>
@@ -2533,95 +3275,84 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">n</span>
- the number of values to be left, defaults to the array length.
- (<em>optional</em>)
+ <li><span class="parameter">value</span>
+ the value to search for
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ the index of the last occurrence of the passed-in value or <strong>nil</strong>
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#first">first</a></li>
- <li><a href="index.html#last">last</a></li>
- <li><a href="index.html#rest">rest</a></li>
+ <a href="index.html#indexOf">indexOf</a>
</ul>
</dd>
<dt>
- <a name = "last"></a>
- <strong>last (array[, n])</strong>
+ <a name = "mean"></a>
+ <strong>mean (array)</strong>
</dt>
<dd>
- Returns the last N values in an array.
+ Returns the mean of an array of numbers.
+ <br/><em>Aliased as <code>average</code></em>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- an array
- </li>
- <li><span class="parameter">n</span>
- the number of values to be collected, defaults to the array length.
- (<em>optional</em>)
+ an array of numbers
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ a number
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#first">first</a></li>
- <li><a href="index.html#initial">initial</a></li>
- <li><a href="index.html#rest">rest</a></li>
+ <li><a href="index.html#sum">sum</a></li>
+ <li><a href="index.html#product">product</a></li>
+ <li><a href="index.html#median">median</a></li>
</ul>
</dd>
<dt>
- <a name = "rest"></a>
- <strong>rest (array[, index])</strong>
+ <a name = "median"></a>
+ <strong>median (array)</strong>
</dt>
<dd>
- Removes all values before index.
- <br/><em>Aliased as <code>tail</code></em>
+ Returns the median of an array of numbers.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- an array
- </li>
- <li><span class="parameter">index</span>
- an index, defaults to 1
- (<em>optional</em>)
+ an array of numbers
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ a number
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#first">first</a></li>
- <li><a href="index.html#initial">initial</a></li>
- <li><a href="index.html#last">last</a></li>
+ <li><a href="index.html#sum">sum</a></li>
+ <li><a href="index.html#product">product</a></li>
+ <li><a href="index.html#mean">mean</a></li>
</ul>
@@ -2655,36 +3386,43 @@
</dd>
<dt>
- <a name = "compact"></a>
- <strong>compact (array)</strong>
+ <a name = "ones"></a>
+ <strong>ones (n)</strong>
</dt>
<dd>
- Removes all falsy (false and nil) values.
+ Returns an array of <code>n</code> 1's.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">array</span>
- an array
+ <li><span class="parameter">n</span>
+ a number
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ an array
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#zeros">zeros</a></li>
+ <li><a href="index.html#vector">vector</a></li>
+ </ul>
</dd>
<dt>
- <a name = "flatten"></a>
- <strong>flatten (array[, shallow])</strong>
+ <a name = "overlapping"></a>
+ <strong>overlapping (array[, n[, pads]])</strong>
</dt>
<dd>
- Flattens a nested array. Passing <code>shallow</code> will only flatten at the first level.
+ Iterator returning overlapping partitions of an array. <br/>
+ If the last subsequence has lower elements than <code>n</code> and <code>pad</code> is
+ supplied, it will be adjusted to <code>n</code> elements with <code>pad</code> value.
<h3>Parameters:</h3>
@@ -2692,8 +3430,12 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">shallow</span>
- specifies the flattening depth
+ <li><span class="parameter">n</span>
+ the size of partitions. Defaults to 2.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">pads</span>
+ a value to adjust the last subsequence to the <code>n</code> elements
(<em>optional</em>)
</li>
</ul>
@@ -2701,20 +3443,24 @@
<h3>Returns:</h3>
<ol>
- a new array, flattened
+ an iterator function
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#partition">partition</a></li>
+ <li><a href="index.html#aperture">aperture</a></li>
+ </ul>
</dd>
<dt>
- <a name = "difference"></a>
- <strong>difference (array, another)</strong>
+ <a name = "pairwise"></a>
+ <strong>pairwise (array)</strong>
</dt>
<dd>
- Returns values from an array not present in all passed-in args.
- <br/><em>Aliased as <code>without</code> and <code>diff</code></em>
+ Iterator returning sliding pairs of an array.
<h3>Parameters:</h3>
@@ -2722,65 +3468,69 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">another</span>
- array
- </li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ an iterator function
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#union">union</a></li>
- <li><a href="index.html#intersection">intersection</a></li>
- <li><a href="index.html#symmetricDifference">symmetricDifference</a></li>
+ <a href="index.html#overlapping">overlapping</a>
</ul>
</dd>
<dt>
- <a name = "union"></a>
- <strong>union (...)</strong>
+ <a name = "partition"></a>
+ <strong>partition (array[, n[, pads]])</strong>
</dt>
<dd>
- Returns the duplicate-free union of all passed in arrays.
+ Iterator returning partitions of an array. It returns arrays of length <code>n</code>
+ made of values from the given array. If the last partition has lower elements than <code>n</code> and
+ <code>pad</code> is supplied, it will be adjusted to <code>n</code> of elements with <code>pad</code> value.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">...</span>
- a variable number of arrays arguments
+ <li><span class="parameter">array</span>
+ an array
+ </li>
+ <li><span class="parameter">n</span>
+ the size of partitions. Defaults to 1.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">pads</span>
+ a value to adjust the last subsequence to the <code>n</code> elements
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ an iterator function
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#difference">difference</a></li>
- <li><a href="index.html#intersection">intersection</a></li>
- <li><a href="index.html#symmetricDifference">symmetricDifference</a></li>
+ <li><a href="index.html#overlapping">overlapping</a></li>
+ <li><a href="index.html#aperture">aperture</a></li>
</ul>
</dd>
<dt>
- <a name = "intersection"></a>
- <strong>intersection (array, ...)</strong>
+ <a name = "permutation"></a>
+ <strong>permutation (array)</strong>
</dt>
<dd>
- Returns the intersection of all passed-in arrays.
- Each value in the result is present in each of the passed-in arrays.
+ Iterator returning the permutations of an array. It returns arrays made of all values
+ from the passed-in array, with values permuted.
<h3>Parameters:</h3>
@@ -2788,35 +3538,51 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">...</span>
- a variable number of array arguments
- </li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ an iterator function
</ol>
- <h3>See also:</h3>
+
+
+</dd>
+ <dt>
+ <a name = "powerset"></a>
+ <strong>powerset (array)</strong>
+ </dt>
+ <dd>
+ Returns the powerset of array values. For instance, when given the set {1,2,3},
+ returns <code>{{1},{2},{3},{1,2},{2,3},{1,2,3}}</code>.
+
+
+ <h3>Parameters:</h3>
<ul>
- <li><a href="index.html#difference">difference</a></li>
- <li><a href="index.html#union">union</a></li>
- <li><a href="index.html#symmetricDifference">symmetricDifference</a></li>
+ <li><span class="parameter">array</span>
+ an array
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ an array
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "symmetricDifference"></a>
- <strong>symmetricDifference (array, array2)</strong>
+ <a name = "prepend"></a>
+ <strong>prepend (array, ...)</strong>
</dt>
<dd>
- Performs a symmetric difference. Returns values from <a href="index.html#array">array</a> not present in <code>array2</code> and also values
- from <code>array2</code> not present in <a href="index.html#array">array</a>.
- <br/><em>Aliased as <code>symdiff</code></em>
+ Adds all passed-in values at the top of an array. As opposed to <a href="index.html#addTop">addTop</a>, it preserves the order
+ of the passed in elements.
<h3>Parameters:</h3>
@@ -2824,65 +3590,86 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">array2</span>
- another array
+ <li><span class="parameter">...</span>
+ a variable number of arguments
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ the passed-in array with new values added
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#difference">difference</a></li>
- <li><a href="index.html#union">union</a></li>
- <li><a href="index.html#intersection">intersection</a></li>
+ <li><a href="index.html#addTop">addTop</a></li>
+ <li><a href="index.html#push">push</a></li>
</ul>
</dd>
<dt>
- <a name = "unique"></a>
- <strong>unique (array)</strong>
+ <a name = "product"></a>
+ <strong>product (array)</strong>
</dt>
<dd>
- Produces a duplicate-free version of a given array.
- <br/><em>Aliased as <code>uniq</code></em>
+ Returns the product of array values.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- an array
+ a given array
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array, duplicate-free
+ the product of array values
</ol>
- <h3>See also:</h3>
+
+
+</dd>
+ <dt>
+ <a name = "pull"></a>
+ <strong>pull (array, ...)</strong>
+ </dt>
+ <dd>
+ Removes all provided values in a given array.
+ <br/><em>Aliased as <code>remove</code></em>
+
+
+ <h3>Parameters:</h3>
<ul>
- <a href="index.html#isunique">isunique</a>
+ <li><span class="parameter">array</span>
+ an array
+ </li>
+ <li><span class="parameter">...</span>
+ a variable number of values to be removed from the array
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ the passed-in array with values removed
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "isunique"></a>
- <strong>isunique (array)</strong>
+ <a name = "push"></a>
+ <strong>push (array, ...)</strong>
</dt>
<dd>
- Checks if a given array contains distinct values. Such an array is made of distinct elements,
- which only occur once in this array.
- <br/><em>Aliased as <code>isuniq</code></em>
+ Pushes all passed-in values at the end of an array.
<h3>Parameters:</h3>
@@ -2890,43 +3677,56 @@
<li><span class="parameter">array</span>
an array
</li>
+ <li><span class="parameter">...</span>
+ a variable number of arguments
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> if the given array is unique, <code>false</code> otherwise.
+ the passed-in array with new added values
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#unique">unique</a>
+ <li><a href="index.html#addTop">addTop</a></li>
+ <li><a href="index.html#prepend">prepend</a></li>
</ul>
</dd>
<dt>
- <a name = "zip"></a>
- <strong>zip (...)</strong>
+ <a name = "range"></a>
+ <strong>range ([from[, to[, step]]])</strong>
</dt>
<dd>
- Merges values of each of the passed-in arrays in subsets.
- Only values indexed with the same key in the given arrays are merged in the same subset.
- <br/><em>Aliased as <code>transpose</code></em>
+ Produces a flexible list of numbers. If one value is passed, will count from 1 to that value,
+ with a default step of 1 (or -1). If two values are passed, will count from the first one to the second one,
+ using a default step of 1 (or -1). A third value passed will be considered a step value.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">...</span>
- a variable number of array arguments
+ <li><span class="parameter">from</span>
+ the initial value of the range
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">to</span>
+ the final value of the range
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">step</span>
+ the step of count. Defaults to 1 or -1.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ a new array of numbers
</ol>
@@ -2934,11 +3734,12 @@
</dd>
<dt>
- <a name = "append"></a>
- <strong>append (array, other)</strong>
+ <a name = "removeRange"></a>
+ <strong>removeRange (array[, start[, finish]])</strong>
</dt>
<dd>
- Clones <a href="index.html#array">array</a> and appends <code>other</code> values.
+ Removes values at an index within the range <code>[start, finish]</code>.
+ <br/><em>Aliased as <code>rmRange</code>, <code>chop</code></em>
<h3>Parameters:</h3>
@@ -2946,15 +3747,20 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">other</span>
- an array
+ <li><span class="parameter">start</span>
+ the lower bound index, defaults to the first index in the array.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">finish</span>
+ the upper bound index, defaults to the array length.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ the passed-in array with values removed
</ol>
@@ -2962,51 +3768,51 @@
</dd>
<dt>
- <a name = "interleave"></a>
- <strong>interleave (...)</strong>
+ <a name = "rep"></a>
+ <strong>rep (value, n)</strong>
</dt>
<dd>
- Interleaves arrays. It returns a single array made of values from all
- passed in arrays in their given order, interleaved.
+ Creates an array list of <code>n</code> values, repeated.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">...</span>
- a variable list of arrays
+ <li><span class="parameter">value</span>
+ a value to be repeated
+ </li>
+ <li><span class="parameter">n</span>
+ the number of repetitions of value.
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ a new array of <code>n</code> values
</ol>
- <h3>See also:</h3>
- <ul>
- <a href="index.html#interpose">interpose</a>
- </ul>
</dd>
<dt>
- <a name = "interpose"></a>
- <strong>interpose (value, array)</strong>
+ <a name = "rest"></a>
+ <strong>rest (array[, index])</strong>
</dt>
<dd>
- Interposes value in-between consecutive pair of values in <a href="index.html#array">array</a>.
+ Returns all values after index.
+ <br/><em>Aliased as <code>tail</code></em>
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">value</span>
- a value
- </li>
<li><span class="parameter">array</span>
an array
</li>
+ <li><span class="parameter">index</span>
+ an index, defaults to 1
+ (<em>optional</em>)
+ </li>
</ul>
<h3>Returns:</h3>
@@ -3018,33 +3824,59 @@
<h3>See also:</h3>
<ul>
- <a href="index.html#interleave">interleave</a>
+ <li><a href="index.html#first">first</a></li>
+ <li><a href="index.html#initial">initial</a></li>
+ <li><a href="index.html#last">last</a></li>
</ul>
</dd>
<dt>
- <a name = "range"></a>
- <strong>range ([from[, to[, step]]])</strong>
+ <a name = "reverse"></a>
+ <strong>reverse (array)</strong>
</dt>
<dd>
- Produces a flexible list of numbers. If one positive value is passed, will count from 0 to that value,
- with a default step of 1. If two values are passed, will count from the first one to the second one, with the
- same default step of 1. A third value passed will be considered a step value.
+ Returns an array where values are in reverse order. The passed-in array should not be sparse.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">from</span>
- the initial value of the range
- (<em>optional</em>)
+ <li><span class="parameter">array</span>
+ an array
</li>
- <li><span class="parameter">to</span>
- the final value of the range
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a reversed array
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sample"></a>
+ <strong>sample (array[, n[, seed]])</strong>
+ </dt>
+ <dd>
+ Samples <code>n</code> random values from an array. If <code>n</code> is not specified, returns a single element.
+ It uses internally <a href="index.html#shuffle">shuffle</a> to shuffle the array before sampling values. If <code>seed</code> is passed,
+ it will be used for shuffling.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">array</span>
+ an array
+ </li>
+ <li><span class="parameter">n</span>
+ a number of elements to be sampled. Defaults to 1.
(<em>optional</em>)
</li>
- <li><span class="parameter">step</span>
- the step of count
+ <li><span class="parameter">seed</span>
+ an optional seed for shuffling
(<em>optional</em>)
</li>
</ul>
@@ -3052,49 +3884,63 @@
<h3>Returns:</h3>
<ol>
- a new array of numbers
+ an array of selected values
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#sampleProb">sampleProb</a>
+ </ul>
</dd>
<dt>
- <a name = "rep"></a>
- <strong>rep (value, n)</strong>
+ <a name = "sampleProb"></a>
+ <strong>sampleProb (array, prob[, seed])</strong>
</dt>
<dd>
- Creates an array list of <code>n</code> values, repeated.
+ Return elements from a sequence with a given probability. It considers each value independently.
+ Providing a seed will result in deterministic sampling. Given the same seed it will return the same sample
+ every time.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">value</span>
- a value to be repeated
+ <li><span class="parameter">array</span>
+ an array
</li>
- <li><span class="parameter">n</span>
- the number of repetitions of value.
+ <li><span class="parameter">prob</span>
+ a probability for each element in array to be selected
+ </li>
+ <li><span class="parameter">seed</span>
+ an optional seed for deterministic sampling
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array of <code>n</code> values
+ an array of selected values
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#sample">sample</a>
+ </ul>
</dd>
<dt>
- <a name = "partition"></a>
- <strong>partition (array[, n[, pad]])</strong>
+ <a name = "selectWhile"></a>
+ <strong>selectWhile (array, f[, ...])</strong>
</dt>
<dd>
- Iterator returning partitions of an array. It returns arrays of length <code>n</code>
- made of values from the given array. If the last partition has lower elements than <code>n</code> and
- <code>pad</code> is supplied, it will be adjusted to <code>n</code> of elements with <code>pad</code> value.
+ Collects values from a given array. The passed-in array should not be sparse.
+ This function collects values as long as they satisfy a given predicate and returns on the first falsy test.
+ <br/><em>Aliased as <code>takeWhile</code></em>
<h3>Parameters:</h3>
@@ -3102,12 +3948,11 @@
<li><span class="parameter">array</span>
an array
</li>
- <li><span class="parameter">n</span>
- the size of partitions. Should be greater than 0. Defaults to 1.
- (<em>optional</em>)
+ <li><span class="parameter">f</span>
+ an iterator function prototyped as <code>f (v, k, ...)</code>
</li>
- <li><span class="parameter">pad</span>
- a value to adjust the last subsequence to the <code>n</code> elements
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>f</code>
(<em>optional</em>)
</li>
</ul>
@@ -3115,21 +3960,24 @@
<h3>Returns:</h3>
<ol>
- an iterator function
+ a new table containing all values collected
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#dropWhile">dropWhile</a>
+ </ul>
</dd>
<dt>
- <a name = "sliding."></a>
- <strong>sliding. (array[, n[, pad]])</strong>
+ <a name = "shift"></a>
+ <strong>shift (array[, n])</strong>
</dt>
<dd>
- Iterator returning sliding partitions of an array. It returns overlapping subsequences
- of length <code>n</code>. If the last subsequence has lower elements than <code>n</code> and <code>pad</code> is
- supplied, it will be adjusted to <code>n</code> elements with <code>pad</code> value.
+ Removes and returns the values at the top of a given array.
+ <br/><em>Aliased as <code>pop</code></em>
<h3>Parameters:</h3>
@@ -3138,11 +3986,7 @@
an array
</li>
<li><span class="parameter">n</span>
- the size of partitions. Should be greater than 1. Defaults to 2.
- (<em>optional</em>)
- </li>
- <li><span class="parameter">pad</span>
- a value to adjust the last subsequence to the <code>n</code> elements
+ the number of values to be popped. Defaults to 1.
(<em>optional</em>)
</li>
</ul>
@@ -3150,20 +3994,24 @@
<h3>Returns:</h3>
<ol>
- an iterator function
+ the popped values
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#unshift">unshift</a>
+ </ul>
</dd>
<dt>
- <a name = "permutation"></a>
- <strong>permutation (array)</strong>
+ <a name = "shuffle"></a>
+ <strong>shuffle (array[, seed])</strong>
</dt>
<dd>
- Iterator returning the permutations of an array. It returns arrays made of all values
- from the passed-in array, with values permuted.
+ Returns a shuffled copy of a given array. If a seed is provided, it will
+ be used to init the built-in pseudo random number generator (using <a href="https://www.lua.org/manual/5.1/manual.html#pdf-math.randomseed">math.randomseed</a>).
<h3>Parameters:</h3>
@@ -3171,12 +4019,16 @@
<li><span class="parameter">array</span>
an array
</li>
+ <li><span class="parameter">seed</span>
+ a seed
+ (<em>optional</em>)
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- an iterator function
+ a shuffled copy of the given array
</ol>
@@ -3184,26 +4036,33 @@
</dd>
<dt>
- <a name = "invert"></a>
- <strong>invert (array)</strong>
+ <a name = "slice"></a>
+ <strong>slice (array[, start[, finish]])</strong>
</dt>
<dd>
- Swaps keys with values. Produces a new array where previous keys are now values,
- while previous values are now keys.
- <br/><em>Aliased as <code>mirror</code></em>
+ Slices values indexed within <code>[start, finish]</code> range.
+ <br/><em>Aliased as <code>M.sub</code></em>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- a given array
+ an array
+ </li>
+ <li><span class="parameter">start</span>
+ the lower bound index, defaults to the first index in the array.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">finish</span>
+ the upper bound index, defaults to the array length.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new array
+ a new array of sliced values
</ol>
@@ -3211,31 +4070,29 @@
</dd>
<dt>
- <a name = "concat"></a>
- <strong>concat (array[, sep[, i[, j]]])</strong>
+ <a name = "sortedIndex"></a>
+ <strong>sortedIndex (array, the[, comp[, sort]])</strong>
</dt>
<dd>
- Concatenates values in a given array. Handles booleans as well. If <code>sep</code> string is
- passed, it will be used as a separator. Passing <code>i</code> and <code>j</code> will result in concatenating
- only values within <code>[i, j]</code> range.
- <br/><em>Aliased as <code>join</code></em>
+ Returns the index at which a value should be inserted. This index is evaluated so
+ that it maintains the sort. If a comparison function is passed, it will be used to sort
+ values.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">array</span>
- a given array
+ an array
</li>
- <li><span class="parameter">sep</span>
- a separator string, defaults to the empty string <code>&apos;&apos;</code>.
- (<em>optional</em>)
+ <li><span class="parameter">the</span>
+ value to be inserted
</li>
- <li><span class="parameter">i</span>
- the starting index, defaults to 1.
+ <li><span class="parameter">comp</span>
+ an comparison function prototyped as <code>f (a, b)</code>, defaults to <tt>&lt;</tt> operator.
(<em>optional</em>)
</li>
- <li><span class="parameter">j</span>
- the final index, defaults to the array length.
+ <li><span class="parameter">sort</span>
+ whether or not the passed-in array should be sorted
(<em>optional</em>)
</li>
</ul>
@@ -3243,30 +4100,32 @@
<h3>Returns:</h3>
<ol>
- a string
+ number the index at which the passed-in value should be inserted
</ol>
</dd>
-</dl>
- <h2 class="section-header "><a name="Utility_functions"></a>Utility functions </h2>
-
- <dl class="function">
<dt>
- <a name = "noop"></a>
- <strong>noop ()</strong>
+ <a name = "sum"></a>
+ <strong>sum (array)</strong>
</dt>
<dd>
- The no-operation function.
+ Returns the sum of array values.
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">array</span>
+ a given array
+ </li>
+ </ul>
<h3>Returns:</h3>
<ol>
- nothing
+ the sum of array values
</ol>
@@ -3274,50 +4133,60 @@
</dd>
<dt>
- <a name = "identity"></a>
- <strong>identity (value)</strong>
+ <a name = "symmetricDifference"></a>
+ <strong>symmetricDifference (array, array2)</strong>
</dt>
<dd>
- Returns the passed-in value. This function is used internally
- as a default iterator.
+ Performs a symmetric difference. Returns values from <a href="index.html#array">array</a> not present in <code>array2</code> and also values
+ from <code>array2</code> not present in <a href="index.html#array">array</a>.
+ <br/><em>Aliased as <code>symdiff</code></em>
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">value</span>
- a value
+ <li><span class="parameter">array</span>
+ an array
+ </li>
+ <li><span class="parameter">array2</span>
+ another array
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the passed-in value
+ a new array
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#difference">difference</a></li>
+ <li><a href="index.html#union">union</a></li>
+ <li><a href="index.html#intersection">intersection</a></li>
+ </ul>
</dd>
<dt>
- <a name = "constant"></a>
- <strong>constant (value)</strong>
+ <a name = "toArray"></a>
+ <strong>toArray (...)</strong>
</dt>
<dd>
- Creates a constant function which returns the same output on every call.
+ Converts a list of arguments to an array.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">value</span>
- a constant value
+ <li><span class="parameter">...</span>
+ a list of arguments
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a constant function
+ an array of all passed-in args
</ol>
@@ -3325,208 +4194,267 @@
</dd>
<dt>
- <a name = "memoize"></a>
- <strong>memoize (f[, hash])</strong>
+ <a name = "union"></a>
+ <strong>union (...)</strong>
</dt>
<dd>
- Memoizes a given function by caching the computed result.
- Useful for speeding-up slow-running functions. If a <code>hash</code> function is passed,
- it will be used to compute hash keys for a set of input values for caching.
- <br/><em>Aliased as <code>cache</code></em>
+ Returns the duplicate-free union of all passed in arrays.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">f</span>
- a function
+ <li><span class="parameter">...</span>
+ a variable number of arrays arguments
</li>
- <li><span class="parameter">hash</span>
- a hash function, defaults to <a href="index.html#identity">identity</a>
- (<em>optional</em>)
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new array
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#difference">difference</a></li>
+ <li><a href="index.html#intersection">intersection</a></li>
+ <li><a href="index.html#symmetricDifference">symmetricDifference</a></li>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "unique"></a>
+ <strong>unique (array)</strong>
+ </dt>
+ <dd>
+ Produces a duplicate-free version of a given array.
+ <br/><em>Aliased as <code>uniq</code></em>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">array</span>
+ an array
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new function
+ a new array, duplicate-free
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#isunique">isunique</a>
+ </ul>
</dd>
<dt>
- <a name = "once"></a>
- <strong>once (f)</strong>
+ <a name = "unshift"></a>
+ <strong>unshift (array[, n])</strong>
</dt>
<dd>
- Returns a version of <code>f</code> that runs only once. Successive calls to <code>f</code>
- will keep yielding the same output, no matter what the passed-in arguments are.
- It can be used to initialize variables.
+ Removes and returns the values at the end of a given array.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">f</span>
- a function
+ <li><span class="parameter">array</span>
+ an array
+ </li>
+ <li><span class="parameter">n</span>
+ the number of values to be unshifted. Defaults to 1.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new function
+ the values
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#before">before</a></li>
- <li><a href="index.html#after">after</a></li>
+ <a href="index.html#shift">shift</a>
</ul>
</dd>
<dt>
- <a name = "before"></a>
- <strong>before (f, count)</strong>
+ <a name = "vector"></a>
+ <strong>vector (value, n)</strong>
</dt>
<dd>
- Returns a version of <code>f</code> that will run no more than <a href="index.html#count">count</a> times. Next calls will
- keep yielding the results of the count-th call.
+ Returns an array of <code>n</code> times a given value.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">f</span>
- a function
+ <li><span class="parameter">value</span>
+ a value
</li>
- <li><span class="parameter">count</span>
- a count
+ <li><span class="parameter">n</span>
+ a number
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new function
+ an array
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#once">once</a></li>
- <li><a href="index.html#after">after</a></li>
+ <li><a href="index.html#zeros">zeros</a></li>
+ <li><a href="index.html#ones">ones</a></li>
</ul>
</dd>
<dt>
- <a name = "after"></a>
- <strong>after (f, count)</strong>
+ <a name = "xprod"></a>
+ <strong>xprod (array, array2)</strong>
</dt>
<dd>
- Returns a version of <code>f</code> that runs on the <code>count-th</code> call.
- Useful when dealing with asynchronous tasks.
+ Returns all possible pairs built from given arrays.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">f</span>
- a function
+ <li><span class="parameter">array</span>
+ a first array
</li>
- <li><span class="parameter">count</span>
- the number of calls before <code>f</code> will start running.
+ <li><span class="parameter">array2</span>
+ a second array
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new function
+ an array list of all pairs
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "zeros"></a>
+ <strong>zeros (n)</strong>
+ </dt>
+ <dd>
+ Returns an array of <code>n</code> zeros.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">n</span>
+ a number
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an array
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#once">once</a></li>
- <li><a href="index.html#before">before</a></li>
+ <li><a href="index.html#ones">ones</a></li>
+ <li><a href="index.html#vector">vector</a></li>
</ul>
</dd>
<dt>
- <a name = "compose"></a>
- <strong>compose (...)</strong>
+ <a name = "zip"></a>
+ <strong>zip (...)</strong>
</dt>
<dd>
- Composes functions. Each passed-in function consumes the return value of the function that follows.
- In math terms, composing the functions <code>f</code>, <code>g</code>, and <code>h</code> produces the function <code>f(g(h(&hellip;)))</code>.
+ Merges values of each of the passed-in arrays in subsets.
+ Only values indexed with the same key in the given arrays are merged in the same subset.
+ <br/><em>Aliased as <code>transpose</code></em>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">...</span>
- a variable number of functions
+ a variable number of array arguments
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new function
+ a new array
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#pipe">pipe</a>
+ <a href="index.html#zipWith">zipWith</a>
</ul>
</dd>
<dt>
- <a name = "pipe"></a>
- <strong>pipe (value, ...)</strong>
+ <a name = "zipWith"></a>
+ <strong>zipWith (f, ...)</strong>
</dt>
<dd>
- Pipes a value through a series of functions. In math terms,
- given some functions <code>f</code>, <code>g</code>, and <code>h</code> in that order, it returns <code>f(g(h(value)))</code>.
+ Merges values using a given function.
+ Only values indexed with the same key in the given arrays are merged in the same subset.
+ Function <code>f</code> is used to combine values.
+ <br/><em>Aliased as <code>transposeWith</code></em>
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">value</span>
- a value
+ <li><span class="parameter">f</span>
+ a function
</li>
<li><span class="parameter">...</span>
- a variable number of functions
+ a variable number of array arguments
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the result of the composition of function calls.
+ a flat array of results
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#compose">compose</a>
+ <a href="index.html#zip">zip</a>
</ul>
</dd>
+</dl>
+ <h2 class="section-header "><a name="Utility_functions"></a>Utility functions </h2>
+
+ <dl class="function">
<dt>
- <a name = "complement"></a>
- <strong>complement (f)</strong>
+ <a name = "after"></a>
+ <strong>after (f, count)</strong>
</dt>
<dd>
- Returns the logical complement of a given function. For a given input, the returned
- function will output <code>false</code> if the original function would have returned <code>true</code>,
- and vice-versa.
+ Returns a version of <code>f</code> that runs on the <code>count-th</code> call.
+ Useful when dealing with asynchronous tasks.
<h3>Parameters:</h3>
@@ -3534,42 +4462,73 @@
<li><span class="parameter">f</span>
a function
</li>
+ <li><span class="parameter">count</span>
+ the number of calls before <code>f</code> will start running.
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- the logical complement of the given function <code>f</code>.
+ a new function
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#once">once</a></li>
+ <li><a href="index.html#before">before</a></li>
+ </ul>
</dd>
<dt>
- <a name = "juxtapose"></a>
- <strong>juxtapose (value, ...)</strong>
+ <a name = "applySpec"></a>
+ <strong>applySpec (specs)</strong>
</dt>
<dd>
- Calls a sequence of passed-in functions with the same argument.
- Returns a sequence of results.
- <br/><em>Aliased as <code>juxt</code></em>
+ Returns a function which applies <code>specs</code> on args. This function produces an object having
+ the same structure than <code>specs</code> by mapping each property to the result of calling its
+ associated function with the supplied arguments
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">value</span>
- a value
+ <li><span class="parameter">specs</span>
+ a table
</li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "array"></a>
+ <strong>array (...)</strong>
+ </dt>
+ <dd>
+ Iterates over an iterator and returns its values in an array.
+ <br/><em>Aliased as <code>tabulate</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
<li><span class="parameter">...</span>
- a variable number of functions
+ an iterator function (returning a generator, a state and a value)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a list of results
+ an array of results
</ol>
@@ -3577,63 +4536,70 @@
</dd>
<dt>
- <a name = "wrap"></a>
- <strong>wrap (f, wrapper)</strong>
+ <a name = "ary"></a>
+ <strong>ary (f[, n])</strong>
</dt>
<dd>
- Wraps <code>f</code> inside of the <code>wrapper</code> function. It passes <code>f</code> as the first argument to <code>wrapper</code>.
- This allows the wrapper to execute code before and after <code>f</code> runs,
- adjust the arguments, and execute it conditionally.
+ Returns a function which accepts up to <code>n</code> args. It ignores any additional arguments.
+ <br/><em>Aliased as <code>nAry</code></em>.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">f</span>
- a function to be wrapped, prototyped as <code>f (&hellip;)</code>
+ a function
</li>
- <li><span class="parameter">wrapper</span>
- a wrapper function, prototyped as <code>wrapper (f, &hellip;)</code>
+ <li><span class="parameter">n</span>
+ a number. Defaults to 1.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the results
+ a function
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#unary">unary</a>
+ </ul>
</dd>
<dt>
- <a name = "times"></a>
- <strong>times (n, iter, ...)</strong>
+ <a name = "before"></a>
+ <strong>before (f, count)</strong>
</dt>
<dd>
- Runs <code>iter</code> function <code>n</code> times. Collects the results of each run and returns them in an array.
+ Returns a version of <code>f</code> that will run no more than <em>count</em> times. Next calls will
+ keep yielding the results of the count-th call.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">n</span>
- the number of times <code>iter</code> should be called
- </li>
- <li><span class="parameter">iter</span>
- an iterator function, prototyped as <code>iter (i, &hellip;)</code>
+ <li><span class="parameter">f</span>
+ a function
</li>
- <li><span class="parameter">...</span>
- args to be passed to <code>iter</code> function
+ <li><span class="parameter">count</span>
+ a count
</li>
</ul>
<h3>Returns:</h3>
<ol>
- table an array of results
+ a new function
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#once">once</a></li>
+ <li><a href="index.html#after">after</a></li>
+ </ul>
</dd>
@@ -3642,7 +4608,7 @@
<strong>bind (f, v)</strong>
</dt>
<dd>
- Binds <code>v</code> to be the first argument to <code>f</code>. Calling <code>f (&hellip;)</code> will result to <code>f (v, &hellip;)</code>.
+ Binds <code>v</code> to be the first argument to <code>f</code>. Calling <code>f (...)</code> will result to <code>f (v, ...)</code>.
<h3>Parameters:</h3>
@@ -3666,7 +4632,7 @@
<ul>
<li><a href="index.html#bind2">bind2</a></li>
<li><a href="index.html#bindn">bindn</a></li>
- <li><a href="index.html#bindAll">bindAll</a></li>
+ <li><a href="index.html#bindall">bindall</a></li>
</ul>
@@ -3676,7 +4642,7 @@
<strong>bind2 (f, v)</strong>
</dt>
<dd>
- Binds <code>v</code> to be the second argument to <code>f</code>. Calling <code>f (a, &hellip;)</code> will result to <code>f (a, v, &hellip;)</code>.
+ Binds <code>v</code> to be the second argument to <code>f</code>. Calling <code>f (a, ...)</code> will result to <code>f (a, v, ...)</code>.
<h3>Parameters:</h3>
@@ -3700,7 +4666,42 @@
<ul>
<li><a href="index.html#bind">bind</a></li>
<li><a href="index.html#bindn">bindn</a></li>
- <li><a href="index.html#bindAll">bindAll</a></li>
+ <li><a href="index.html#bindall">bindall</a></li>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "bindall"></a>
+ <strong>bindall (obj, ...)</strong>
+ </dt>
+ <dd>
+ Binds methods to object. As such, whenever any of these methods is invoked, it
+ always receives the object as its first argument.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ an abject
+ </li>
+ <li><span class="parameter">...</span>
+ a variable number of method names
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the passed-in object with all methods bound to the object itself.
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#bind">bind</a></li>
+ <li><a href="index.html#bind2">bind2</a></li>
+ <li><a href="index.html#bindn">bindn</a></li>
</ul>
@@ -3710,8 +4711,8 @@
<strong>bindn (f, ...)</strong>
</dt>
<dd>
- Binds <code>&hellip;</code> to be the N-first arguments to function <code>f</code>.<br/>
- Calling <code>f (a1, a2, &hellip;, aN)</code> will result to <code>f (&hellip;, a1, a2, &hellip;,aN)</code>.
+ Binds <code>...</code> to be the N-first arguments to function <code>f</code>. <br/>
+ Calling <code>f (a1, a2, ..., aN)</code> will result to <code>f (..., a1, a2, ...,aN)</code>.
<h3>Parameters:</h3>
@@ -3735,65 +4736,194 @@
<ul>
<li><a href="index.html#bind">bind</a></li>
<li><a href="index.html#bind2">bind2</a></li>
- <li><a href="index.html#bindAll">bindAll</a></li>
+ <li><a href="index.html#bindall">bindall</a></li>
</ul>
</dd>
<dt>
- <a name = "bindAll"></a>
- <strong>bindAll (obj, ...)</strong>
+ <a name = "castArray"></a>
+ <strong>castArray (value)</strong>
</dt>
<dd>
- Binds methods to object. As such, whenever any of these methods is invoked, it
- always receives the object as its first argument.
+ Casts vaue as an array if it is not one.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">obj</span>
- an abject
+ <li><span class="parameter">value</span>
+ a value
</li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an array containing the given value
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "complement"></a>
+ <strong>complement (f)</strong>
+ </dt>
+ <dd>
+ Returns the logical complement of a given function. For a given input, the returned
+ function will output <code>false</code> if the original function would have returned <code>true</code>,
+ and vice-versa.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the logical complement of the given function <code>f</code>.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "compose"></a>
+ <strong>compose (...)</strong>
+ </dt>
+ <dd>
+ Composes functions. Each passed-in function consumes the return value of the function that follows.
+ In math terms, composing the functions <code>f</code>, <code>g</code>, and <code>h</code> produces the function <code>f(g(h(...)))</code>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
<li><span class="parameter">...</span>
- a variable number of method names
+ a variable number of functions
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the passed-in object with all methods bound to the object itself.
+ a new function
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#bind">bind</a></li>
- <li><a href="index.html#bind2">bind2</a></li>
- <li><a href="index.html#bindn">bindn</a></li>
+ <a href="index.html#pipe">pipe</a>
</ul>
</dd>
<dt>
- <a name = "uniqueId"></a>
- <strong>uniqueId ([template[, ...]])</strong>
+ <a name = "cond"></a>
+ <strong>cond (conds)</strong>
</dt>
<dd>
- Generates an unique ID for the current session. If given a string <a href="index.html#template">template</a>, it
- will use this template for output formatting. Otherwise, if <a href="index.html#template">template</a> is a function, it
- will evaluate <code>template (id, &hellip;)</code>.
- <br/><em>Aliased as <code>uid</code></em>.
+ Returns a function which iterate over a set of conditions. It invokes each predicate,
+ passing it given values. It returns the value of the corresponding function of the first
+ predicate to return a non-nil value.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">template</span>
- either a string or a function template to format the ID
- (<em>optional</em>)
+ <li><span class="parameter">conds</span>
+ an array list of predicate-function pairs
</li>
- <li><span class="parameter">...</span>
- a variable number of arguments to be passed to <a href="index.html#template">template</a>, in case it is a function.
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the result of invoking <code>f(...)</code> of the first predicate to return a non-nil value
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "constant"></a>
+ <strong>constant (value)</strong>
+ </dt>
+ <dd>
+ Creates a constant function which returns the same output on every call.
+ <br/><em>Aliased as <code>always</code></em>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">value</span>
+ a constant value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a constant function
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "converge"></a>
+ <strong>converge (f, g, h)</strong>
+ </dt>
+ <dd>
+ Converges two functions into one.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function
+ </li>
+ <li><span class="parameter">g</span>
+ a function
+ </li>
+ <li><span class="parameter">h</span>
+ a function
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new version of function f
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "curry"></a>
+ <strong>curry (f[, n_args])</strong>
+ </dt>
+ <dd>
+ Curries a function. If the given function <code>f</code> takes multiple arguments, it returns another version of
+ <code>f</code> that takes a single argument (the first of the arguments to the original function) and returns a new
+ function that takes the remainder of the arguments and returns the result.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function
+ </li>
+ <li><span class="parameter">n_args</span>
+ the number of arguments expected for <code>f</code>. Defaults to 2.
(<em>optional</em>)
</li>
</ul>
@@ -3801,7 +4931,63 @@
<h3>Returns:</h3>
<ol>
- value an ID
+ a curried version of <code>f</code>
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#partial">partial</a></li>
+ <li><a href="index.html#partialRight">partialRight</a></li>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "flip"></a>
+ <strong>flip (f)</strong>
+ </dt>
+ <dd>
+ Creates a function of <code>f</code> with arguments flipped in reverse order.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "identity"></a>
+ <strong>identity (value)</strong>
+ </dt>
+ <dd>
+ Returns the passed-in value. This function is used internally
+ as a default iterator.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">value</span>
+ a value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the passed-in value
</ol>
@@ -3810,11 +4996,12 @@
</dd>
<dt>
<a name = "iterator"></a>
- <strong>iterator (f, x)</strong>
+ <strong>iterator (f, value[, n])</strong>
</dt>
<dd>
- Produces an iterator which repeatedly apply a function <code>f</code> onto an input.<br/>
- Yields x, then f(x), then f(f(x)), continuously.
+ Produces an iterator which repeatedly apply a function <code>f</code> onto an input. <br/>
+ Yields <a href="index.html#obj:value">value</a>, then <code>f(value)</code>, then <code>f(f(value))</code>, continuously.
+ <br/><em>Aliased as <code>iter</code></em>.
<h3>Parameters:</h3>
@@ -3822,16 +5009,19 @@
<li><span class="parameter">f</span>
a function
</li>
- <li><span class="parameter">x</span>
+ <li><span class="parameter">value</span>
an initial input to <code>f</code>
</li>
+ <li><span class="parameter">n</span>
+ the number of times the iterator should run
+ (<em>optional</em>)
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- an iterator fnction
- <br/><em>Aliased as <code>iter</code></em>.
+ an iterator function
</ol>
@@ -3839,24 +5029,29 @@
</dd>
<dt>
- <a name = "array"></a>
- <strong>array (...)</strong>
+ <a name = "juxtapose"></a>
+ <strong>juxtapose (value, ...)</strong>
</dt>
<dd>
- Iterates an iterator and returns its values in an array.
+ Calls a sequence of passed-in functions with the same argument.
+ Returns a sequence of results.
+ <br/><em>Aliased as <code>juxt</code></em>
<h3>Parameters:</h3>
<ul>
+ <li><span class="parameter">value</span>
+ a value
+ </li>
<li><span class="parameter">...</span>
- an iterator (a function, a table and a value)
+ a variable number of functions
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array of results
+ a list of results
</ol>
@@ -3864,11 +5059,14 @@
</dd>
<dt>
- <a name = "flip"></a>
- <strong>flip (f)</strong>
+ <a name = "memoize"></a>
+ <strong>memoize (f[, hash])</strong>
</dt>
<dd>
- Creates a function of <code>f</code> with arguments flipped in reverse order.
+ Memoizes a given function by caching the computed result.
+ Useful for speeding-up slow-running functions. If a <code>hash</code> function is passed,
+ it will be used to compute hash keys for a set of input values for caching.
+ <br/><em>Aliased as <code>cache</code></em>
<h3>Parameters:</h3>
@@ -3876,6 +5074,55 @@
<li><span class="parameter">f</span>
a function
</li>
+ <li><span class="parameter">hash</span>
+ a hash function, defaults to <a href="index.html#identity">identity</a>
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new function
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "noop"></a>
+ <strong>noop ()</strong>
+ </dt>
+ <dd>
+ The no operation function.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ nothing
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "nthArg"></a>
+ <strong>nthArg (n)</strong>
+ </dt>
+ <dd>
+ Returns a function that gets the nth argument. <br/>
+ If n is negative, the nth argument from the end is returned.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">n</span>
+ a number
+ </li>
</ul>
<h3>Returns:</h3>
@@ -3889,6 +5136,38 @@
</dd>
<dt>
+ <a name = "once"></a>
+ <strong>once (f)</strong>
+ </dt>
+ <dd>
+ Returns a version of <code>f</code> that runs only once. Successive calls to <code>f</code>
+ will keep yielding the same output, no matter what the passed-in arguments are.
+ It can be used to initialize variables.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new function
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="index.html#before">before</a></li>
+ <li><a href="index.html#after">after</a></li>
+ </ul>
+
+
+</dd>
+ <dt>
<a name = "over"></a>
<strong>over (...)</strong>
</dt>
@@ -3920,43 +5199,46 @@
</dd>
<dt>
- <a name = "overEvery"></a>
- <strong>overEvery (...)</strong>
+ <a name = "overArgs"></a>
+ <strong>overArgs (f, ...)</strong>
</dt>
<dd>
- Creates a validation function. The returned function checks if <em>all</em> of the given predicates return
- truthy when invoked with the arguments it receives.
+ Creates a function that invokes <code>f</code> with its arguments transformed. 1rst arguments will be passed to
+ the 1rst transform, 2nd arg to the 2nd transform, etc. Remaining arguments will not be transformed.
<h3>Parameters:</h3>
<ul>
+ <li><span class="parameter">f</span>
+ a function
+ </li>
<li><span class="parameter">...</span>
- a list of predicate functions
+ a list of transforms funcs prototyped as <code>f (v)</code>
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a new function
+ the result of running <code>f</code> with its transformed arguments
</ol>
<h3>See also:</h3>
<ul>
<li><a href="index.html#over">over</a></li>
+ <li><a href="index.html#overEvery">overEvery</a></li>
<li><a href="index.html#overSome">overSome</a></li>
- <li><a href="index.html#overArgs">overArgs</a></li>
</ul>
</dd>
<dt>
- <a name = "overSome"></a>
- <strong>overSome (...)</strong>
+ <a name = "overEvery"></a>
+ <strong>overEvery (...)</strong>
</dt>
<dd>
- Creates a validation function. The return function checks if <em>any</em> of a given predicates return
+ Creates a validation function. The returned function checks if <em>all</em> of the given predicates return
truthy when invoked with the arguments it receives.
@@ -3977,35 +5259,32 @@
<h3>See also:</h3>
<ul>
<li><a href="index.html#over">over</a></li>
- <li><a href="index.html#overEvery">overEvery</a></li>
+ <li><a href="index.html#overSome">overSome</a></li>
<li><a href="index.html#overArgs">overArgs</a></li>
</ul>
</dd>
<dt>
- <a name = "overArgs"></a>
- <strong>overArgs (f, ...)</strong>
+ <a name = "overSome"></a>
+ <strong>overSome (...)</strong>
</dt>
<dd>
- Creates a function that invokes <code>f</code> with its arguments transformed. 1rst arguments will be passed to
- the 1rst transform, 2nd arg to the 2nd transform, etc. Remaining arguments will not be transformed.
+ Creates a validation function. The return function checks if <em>any</em> of a given predicates return
+ truthy when invoked with the arguments it receives.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">f</span>
- a function
- </li>
<li><span class="parameter">...</span>
- a list of transforms funcs prototyped as <code>f (v)</code>
+ a list of predicate functions
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the result of running <code>f</code> with its transformed arguments
+ a new function
</ol>
@@ -4013,7 +5292,7 @@
<ul>
<li><a href="index.html#over">over</a></li>
<li><a href="index.html#overEvery">overEvery</a></li>
- <li><a href="index.html#overSome">overSome</a></li>
+ <li><a href="index.html#overArgs">overArgs</a></li>
</ul>
@@ -4023,8 +5302,8 @@
<strong>partial (f, ...)</strong>
</dt>
<dd>
- Partially apply a function by filling in any number of its arguments.<br/>
- One may pass a string <code>&apos;_&apos;</code> as a placeholder in the list of arguments to specify an argument
+ Partially apply a function by filling in any number of its arguments. <br/>
+ One may pass a string <code>&apos;M&apos;</code> as a placeholder in the list of arguments to specify an argument
that should not be pre-filled, but left open to be supplied at call-time.
@@ -4087,47 +5366,45 @@
</dd>
<dt>
- <a name = "curry"></a>
- <strong>curry (f[, n_args])</strong>
+ <a name = "pipe"></a>
+ <strong>pipe (value, ...)</strong>
</dt>
<dd>
- Curries a function. If the given function <code>f</code> takes multiple arguments, it returns another version of
- <code>f</code> that takes a single argument (the first of the arguments to the original function) and returns a new
- function that takes the remainder of the arguments and returns the result.
+ Pipes a value through a series of functions. In math terms,
+ given some functions <code>f</code>, <code>g</code>, and <code>h</code> in that order, it returns <code>f(g(h(value)))</code>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">f</span>
- a function
+ <li><span class="parameter">value</span>
+ a value
</li>
- <li><span class="parameter">n_args</span>
- the number of arguments expected for <code>f</code>. Defaults to 2.
- (<em>optional</em>)
+ <li><span class="parameter">...</span>
+ a variable number of functions
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a curried version of <code>f</code>
+ the result of the composition of function calls.
</ol>
<h3>See also:</h3>
<ul>
- <li><a href="index.html#partial">partial</a></li>
- <li><a href="index.html#partialRight">partialRight</a></li>
+ <a href="index.html#compose">compose</a>
</ul>
</dd>
<dt>
- <a name = "time"></a>
- <strong>time (f[, ...])</strong>
+ <a name = "rearg"></a>
+ <strong>rearg (f, indexes)</strong>
</dt>
<dd>
- Returns the execution time of <code>f (&hellip;)</code> and its returned values.
+ Returns a function which runs with arguments rearranged. Arguments are passed to the
+ returned function in the order of supplied <code>indexes</code> at call-time.
<h3>Parameters:</h3>
@@ -4135,45 +5412,44 @@
<li><span class="parameter">f</span>
a function
</li>
- <li><span class="parameter">...</span>
- optional args to <code>f</code>
- (<em>optional</em>)
+ <li><span class="parameter">indexes</span>
+ an array list of indexes
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the execution time and the results of <code>f (&hellip;)</code>
+ a function
</ol>
</dd>
-</dl>
- <h2 class="section-header "><a name="Object_functions"></a>Object functions </h2>
-
- <dl class="function">
<dt>
- <a name = "keys"></a>
- <strong>keys (obj)</strong>
+ <a name = "time"></a>
+ <strong>time (f[, ...])</strong>
</dt>
<dd>
- Returns the keys of the object properties.
+ Returns the execution time of <code>f (...)</code> and its returned values.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">obj</span>
- an object
+ <li><span class="parameter">f</span>
+ a function
+ </li>
+ <li><span class="parameter">...</span>
+ optional args to <code>f</code>
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array
+ the execution time and the results of <code>f (...)</code>
</ol>
@@ -4181,24 +5457,32 @@
</dd>
<dt>
- <a name = "values"></a>
- <strong>values (obj)</strong>
+ <a name = "times"></a>
+ <strong>times (iter[, n[, ...]])</strong>
</dt>
<dd>
- Returns the values of the object properties.
+ Runs <code>iter</code> function <code>n</code> times. Collects the results of each run and returns them in an array.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">obj</span>
- an object
+ <li><span class="parameter">iter</span>
+ an iterator function, prototyped as <code>iter (i, ...)</code>
+ </li>
+ <li><span class="parameter">n</span>
+ the number of times <code>iter</code> should be called. Defaults to 1.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">...</span>
+ args to be passed to <code>iter</code> function
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array
+ table an array of results
</ol>
@@ -4206,142 +5490,180 @@
</dd>
<dt>
- <a name = "kvpairs"></a>
- <strong>kvpairs (obj)</strong>
+ <a name = "unary"></a>
+ <strong>unary (f)</strong>
</dt>
<dd>
- Converts keys and values a an array-list of [k, v].
+ Returns a function which accepts up to one arg. It ignores any additional arguments.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">obj</span>
- an object
+ <li><span class="parameter">f</span>
+ a function
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an array list of key-values pairs
+ a function
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#toObj">toObj</a>
+ <a href="index.html#ary">ary</a>
</ul>
</dd>
<dt>
- <a name = "toObj"></a>
- <strong>toObj (kvpairs)</strong>
+ <a name = "unfold"></a>
+ <strong>unfold (f, seed)</strong>
</dt>
<dd>
- Converts an array list of <a href="index.html#kvpairs">kvpairs</a> to an object. Keys are taken
- from the 1rst column in the <a href="index.html#kvpairs">kvpairs</a> sequence, associated with values in the 2nd
- column
+ Builds a list from a seed value. Accepts an iterator function, which
+ returns either nil to stop iteration or two values : the value to add to the list
+ of results and the seed to be used in the next call to the iterator function.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">kvpairs</span>
- an array-list of <a href="index.html#kvpairs">kvpairs</a>
+ <li><span class="parameter">f</span>
+ an iterator function
+ </li>
+ <li><span class="parameter">seed</span>
+ a seed value
</li>
</ul>
<h3>Returns:</h3>
<ol>
- an object
+ an array of values
</ol>
- <h3>See also:</h3>
- <ul>
- <a href="index.html#kvpairs">kvpairs</a>
- </ul>
</dd>
<dt>
- <a name = "property"></a>
- <strong>property (key)</strong>
+ <a name = "uniqueId"></a>
+ <strong>uniqueId ([template[, ...]])</strong>
</dt>
<dd>
- Returns a function that will return the key property of any passed-in object.
+ Generates an unique ID for the current session. If given a string <a href="index.html#template">template</a>, it
+ will use this template for output formatting. Otherwise, if <a href="index.html#template">template</a> is a function, it
+ will evaluate <code>template (id, ...)</code>.
+ <br/><em>Aliased as <code>uid</code></em>.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">key</span>
- a key property name
+ <li><span class="parameter">template</span>
+ either a string or a function template to format the ID
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">...</span>
+ a variable number of arguments to be passed to <a href="index.html#template">template</a>, in case it is a function.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a function which should accept an object as argument
+ value an ID
</ol>
- <h3>See also:</h3>
- <ul>
- <a href="index.html#propertyOf">propertyOf</a>
- </ul>
</dd>
<dt>
- <a name = "propertyOf"></a>
- <strong>propertyOf (obj)</strong>
+ <a name = "wrap"></a>
+ <strong>wrap (f, wrapper)</strong>
</dt>
<dd>
- Returns a function which will return the value of an object property.
+ Wraps <code>f</code> inside of the <code>wrapper</code> function. It passes <code>f</code> as the first argument to <code>wrapper</code>.
+ This allows the wrapper to execute code before and after <code>f</code> runs,
+ adjust the arguments, and execute it conditionally.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">obj</span>
- an object
+ <li><span class="parameter">f</span>
+ a function to be wrapped, prototyped as <code>f (...)</code>
+ </li>
+ <li><span class="parameter">wrapper</span>
+ a wrapper function, prototyped as <code>wrapper (f, ...)</code>
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a function which should accept a key property argument
+ the results
</ol>
- <h3>See also:</h3>
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Object_functions"></a>Object functions </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "chain"></a>
+ <strong>chain (value)</strong>
+ </dt>
+ <dd>
+ Returns a wrapped object. Calling library functions as methods on this object
+ will continue to return wrapped objects until <a href="index.html#obj:value">obj:value</a> is used. Can be aliased as <code>M(value)</code>.
+
+
+ <h3>Parameters:</h3>
<ul>
- <a href="index.html#property">property</a>
+ <li><span class="parameter">value</span>
+ a value to be wrapped
+ </li>
</ul>
+ <h3>Returns:</h3>
+ <ol>
+
+ a wrapped object
+ </ol>
+
+
+
</dd>
<dt>
- <a name = "toBoolean"></a>
- <strong>toBoolean (value)</strong>
+ <a name = "clone"></a>
+ <strong>clone (obj[, shallow])</strong>
</dt>
<dd>
- Converts any given value to a boolean
+ Clones a given object properties. If <code>shallow</code> is passed will also clone nested array properties.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">value</span>
- a value. Can be of any type
+ <li><span class="parameter">obj</span>
+ an object
+ </li>
+ <li><span class="parameter">shallow</span>
+ whether or not nested array-properties should be cloned, defaults to false.
+ (<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> if value is true, <code>false</code> otherwise (false or nil).
+ a copy of the passed-in object
</ol>
@@ -4408,11 +5730,11 @@
</dd>
<dt>
- <a name = "clone"></a>
- <strong>clone (obj[, shallow])</strong>
+ <a name = "has"></a>
+ <strong>has (obj, key)</strong>
</dt>
<dd>
- Clones a given object properties. If <code>shallow</code> is passed will also clone nested array properties.
+ Checks if a given object implements a property.
<h3>Parameters:</h3>
@@ -4420,16 +5742,15 @@
<li><span class="parameter">obj</span>
an object
</li>
- <li><span class="parameter">shallow</span>
- whether or not nested array-properties should be cloned, defaults to false.
- (<em>optional</em>)
+ <li><span class="parameter">key</span>
+ a key property to be checked
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a copy of the passed-in object
+ <code>true</code> or <code>false</code>
</ol>
@@ -4437,25 +5758,21 @@
</dd>
<dt>
- <a name = "tap"></a>
- <strong>tap (obj, f[, ...])</strong>
+ <a name = "import"></a>
+ <strong>import ([context[, noConflict]])</strong>
</dt>
<dd>
- Invokes interceptor with the object, and then returns object.
- The primary purpose of this method is to &ldquo;tap into&rdquo; a method chain, in order to perform operations
- on intermediate results within the chain.
+ Imports all library functions into a context.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">obj</span>
- an object
- </li>
- <li><span class="parameter">f</span>
- an interceptor function, should be prototyped as <code>f (obj, &hellip;)</code>
+ <li><span class="parameter">context</span>
+ a context. Defaults to <code>_ENV or </code>_G`` (current environment).
+ (<em>optional</em>)
</li>
- <li><span class="parameter">...</span>
- args to be passed to <code>f</code>
+ <li><span class="parameter">noConflict</span>
+ if supplied, will not import conflicting functions in the destination context.
(<em>optional</em>)
</li>
</ul>
@@ -4463,7 +5780,7 @@
<h3>Returns:</h3>
<ol>
- the passed-in object
+ the passed-in context
</ol>
@@ -4471,11 +5788,12 @@
</dd>
<dt>
- <a name = "has"></a>
- <strong>has (obj, key)</strong>
+ <a name = "isArray"></a>
+ <strong>isArray (obj)</strong>
</dt>
<dd>
- Checks if a given object implements a property.
+ Checks if the given argument is an array. Assumes <code>obj</code> is an array
+ if is a table with consecutive integer keys starting at 1.
<h3>Parameters:</h3>
@@ -4483,9 +5801,6 @@
<li><span class="parameter">obj</span>
an object
</li>
- <li><span class="parameter">key</span>
- a key property to be checked
- </li>
</ul>
<h3>Returns:</h3>
@@ -4499,12 +5814,11 @@
</dd>
<dt>
- <a name = "pick"></a>
- <strong>pick (obj, ...)</strong>
+ <a name = "isBoolean"></a>
+ <strong>isBoolean (obj)</strong>
</dt>
<dd>
- Returns an object copy having white-listed properties.
- <br/><em>Aliased as <code>choose</code></em>.
+ Checks if the given argument is a boolean.
<h3>Parameters:</h3>
@@ -4512,15 +5826,12 @@
<li><span class="parameter">obj</span>
an object
</li>
- <li><span class="parameter">...</span>
- a variable number of string keys
- </li>
</ul>
<h3>Returns:</h3>
<ol>
- the filtered object
+ <code>true</code> or <code>false</code>
</ol>
@@ -4528,12 +5839,12 @@
</dd>
<dt>
- <a name = "omit"></a>
- <strong>omit (obj, ...)</strong>
+ <a name = "isCallable"></a>
+ <strong>isCallable (obj)</strong>
</dt>
<dd>
- Returns an object copy without black-listed properties.
- <br/><em>Aliased as <code>drop</code></em>.
+ Checks if the given argument is callable. Assumes <code>obj</code> is callable if
+ it is either a function or a table having a metatable implementing <code>__call</code> metamethod.
<h3>Parameters:</h3>
@@ -4541,15 +5852,12 @@
<li><span class="parameter">obj</span>
an object
</li>
- <li><span class="parameter">...</span>
- a variable number of string keys
- </li>
</ul>
<h3>Returns:</h3>
<ol>
- the filtered object
+ <code>true</code> or <code>false</code>
</ol>
@@ -4557,21 +5865,19 @@
</dd>
<dt>
- <a name = "template"></a>
- <strong>template (obj[, template])</strong>
+ <a name = "isEmpty"></a>
+ <strong>isEmpty ([obj])</strong>
</dt>
<dd>
- Applies a template to an object, preserving non-nil properties.
- <br/><em>Aliased as <code>defaults</code></em>.
+ Checks if the given pbject is empty. If <code>obj</code> is a string, will return <code>true</code>
+ if <code>#obj == 0</code>. Otherwise, if <code>obj</code> is a table, will return whether or not this table
+ is empty. If <code>obj</code> is <code>nil</code>, it will return true.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">obj</span>
an object
- </li>
- <li><span class="parameter">template</span>
- a template object. Defaults to an empty table <code>{}</code>.
(<em>optional</em>)
</li>
</ul>
@@ -4579,7 +5885,7 @@
<h3>Returns:</h3>
<ol>
- the passed-in object filled
+ <code>true</code> or <code>false</code>
</ol>
@@ -4595,7 +5901,7 @@
(by reference), nil, booleans. Compares tables by reference or by values. If <code>useMt</code>
is passed, the equality operator <code>==</code> will be used if one of the given objects has a
metatable implementing <code>__eq</code>.
- <br/><em>Aliased as <code>_.compare</code></em>
+ <br/><em>Aliased as <code>M.compare</code>, <code>M.matches</code></em>
<h3>Parameters:</h3>
@@ -4623,12 +5929,11 @@
</dd>
<dt>
- <a name = "result"></a>
- <strong>result (obj, method[, ...])</strong>
+ <a name = "isFinite"></a>
+ <strong>isFinite (obj)</strong>
</dt>
<dd>
- Invokes an object method. It passes the object itself as the first argument. if <code>method</code> is not
- callable, will return <code>obj[method]</code>.
+ Checks if the given argument is a finite number.
<h3>Parameters:</h3>
@@ -4636,19 +5941,12 @@
<li><span class="parameter">obj</span>
an object
</li>
- <li><span class="parameter">method</span>
- a string key to index in object <code>obj</code>.
- </li>
- <li><span class="parameter">...</span>
- Optional args to be passed to <code>method</code>
- (<em>optional</em>)
- </li>
</ul>
<h3>Returns:</h3>
<ol>
- the returned value of <code>method (obj, &hellip;)</code> call
+ <code>true</code> or <code>false</code>
</ol>
@@ -4656,17 +5954,17 @@
</dd>
<dt>
- <a name = "isTable"></a>
- <strong>isTable (t)</strong>
+ <a name = "isFunction"></a>
+ <strong>isFunction (obj)</strong>
</dt>
<dd>
- Checks if the given arg is a table.
+ Checks if the given argument is a function.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">t</span>
- a value to be tested
+ <li><span class="parameter">obj</span>
+ an object
</li>
</ul>
@@ -4681,12 +5979,11 @@
</dd>
<dt>
- <a name = "isCallable"></a>
- <strong>isCallable (obj)</strong>
+ <a name = "isInteger"></a>
+ <strong>isInteger (obj)</strong>
</dt>
<dd>
- Checks if the given argument is callable. Assumes <code>obj</code> is callable if
- it is either a function or a table having a metatable implementing <code>__call</code> metamethod.
+ Checks if the given argument is an integer.
<h3>Parameters:</h3>
@@ -4707,12 +6004,36 @@
</dd>
<dt>
- <a name = "isArray"></a>
- <strong>isArray (obj)</strong>
+ <a name = "isIterable"></a>
+ <strong>isIterable (obj)</strong>
</dt>
<dd>
- Checks if the given argument is an array. Assumes <code>obj</code> is an array
- if is a table with consecutive integer keys starting at 1.
+ Checks if the given object is iterable with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a> (or <a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a>).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ an object
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>true</code> if the object can be iterated with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a> (or <a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a>), <code>false</code> otherwise
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isNaN"></a>
+ <strong>isNaN (obj)</strong>
+ </dt>
+ <dd>
+ Checks if the given argument is NaN (see <a href="http://en.wikipedia.org/wiki/NaN">Not-A-Number</a>).
<h3>Parameters:</h3>
@@ -4729,15 +6050,19 @@
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#isNumber">isNumber</a>
+ </ul>
</dd>
<dt>
- <a name = "isIterable"></a>
- <strong>isIterable (obj)</strong>
+ <a name = "isNil"></a>
+ <strong>isNil (obj)</strong>
</dt>
<dd>
- Checks if the given object is iterable with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a> (or <a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a>).
+ Checks if the given argument is nil.
<h3>Parameters:</h3>
@@ -4750,7 +6075,7 @@
<h3>Returns:</h3>
<ol>
- <code>true</code> if the object can be iterated with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a> (or <a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a>), <code>false</code> otherwise
+ <code>true</code> or <code>false</code>
</ol>
@@ -4758,20 +6083,17 @@
</dd>
<dt>
- <a name = "isEmpty"></a>
- <strong>isEmpty ([obj])</strong>
+ <a name = "isNumber"></a>
+ <strong>isNumber (obj)</strong>
</dt>
<dd>
- Checks if the given pbject is empty. If <code>obj</code> is a string, will return <code>true</code>
- if <code>#obj == 0</code>. Otherwise, if <code>obj</code> is a table, will return whether or not this table
- is empty. If <code>obj</code> is <code>nil</code>, it will return true.
+ Checks if the given argument is a number.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">obj</span>
an object
- (<em>optional</em>)
</li>
</ul>
@@ -4782,6 +6104,10 @@
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#isNaN">isNaN</a>
+ </ul>
</dd>
@@ -4811,11 +6137,36 @@
</dd>
<dt>
- <a name = "isFunction"></a>
- <strong>isFunction (obj)</strong>
+ <a name = "isTable"></a>
+ <strong>isTable (t)</strong>
</dt>
<dd>
- Checks if the given argument is a function.
+ Checks if the given arg is a table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a value to be tested
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>true</code> or <code>false</code>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "keys"></a>
+ <strong>keys (obj)</strong>
+ </dt>
+ <dd>
+ Returns the keys of the object properties.
<h3>Parameters:</h3>
@@ -4828,7 +6179,7 @@
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ an array
</ol>
@@ -4836,11 +6187,11 @@
</dd>
<dt>
- <a name = "isNil"></a>
- <strong>isNil (obj)</strong>
+ <a name = "kvpairs"></a>
+ <strong>kvpairs (obj)</strong>
</dt>
<dd>
- Checks if the given argument is nil.
+ Converts key-value pairs to an array-list of <code>[k, v]</code> pairs.
<h3>Parameters:</h3>
@@ -4853,19 +6204,43 @@
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ an array list of key-value pairs
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#toObj">toObj</a>
+ </ul>
</dd>
<dt>
- <a name = "isNumber"></a>
- <strong>isNumber (obj)</strong>
+ <a name = "obj:value"></a>
+ <strong>obj:value ()</strong>
</dt>
<dd>
- Checks if the given argument is a number.
+ Extracts the value of a wrapped object. Must be called on an chained object (see <a href="index.html#chain">chain</a>).
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the value previously wrapped
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "omit"></a>
+ <strong>omit (obj, ...)</strong>
+ </dt>
+ <dd>
+ Returns an object copy without black-listed properties.
+ <br/><em>Aliased as <code>drop</code></em>.
<h3>Parameters:</h3>
@@ -4873,28 +6248,114 @@
<li><span class="parameter">obj</span>
an object
</li>
+ <li><span class="parameter">...</span>
+ a variable number of string keys
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ the filtered object
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "path"></a>
+ <strong>path (obj, ...)</strong>
+ </dt>
+ <dd>
+ Returns the value at a given path in an object. <br/>
+ Path is given as a vararg list of keys.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ an object
+ </li>
+ <li><span class="parameter">...</span>
+ a vararg list of keys
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a value or nil
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pick"></a>
+ <strong>pick (obj, ...)</strong>
+ </dt>
+ <dd>
+ Returns an object copy having white-listed properties.
+ <br/><em>Aliased as <code>choose</code></em>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ an object
+ </li>
+ <li><span class="parameter">...</span>
+ a variable number of string keys
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the filtered object
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "property"></a>
+ <strong>property (key)</strong>
+ </dt>
+ <dd>
+ Returns a function that will return the key property of any passed-in object.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">key</span>
+ a key property name
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function which should accept an object as argument
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#isNaN">isNaN</a>
+ <a href="index.html#propertyOf">propertyOf</a>
</ul>
</dd>
<dt>
- <a name = "isNaN"></a>
- <strong>isNaN (obj)</strong>
+ <a name = "propertyOf"></a>
+ <strong>propertyOf (obj)</strong>
</dt>
<dd>
- Checks if the given argument is NaN (see <a href="http://en.wikipedia.org/wiki/NaN">Not-A-Number</a>).
+ Returns a function which will return the value of an object property.
<h3>Parameters:</h3>
@@ -4907,23 +6368,24 @@
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ a function which should accept a key property argument
</ol>
<h3>See also:</h3>
<ul>
- <a href="index.html#isNumber">isNumber</a>
+ <a href="index.html#property">property</a>
</ul>
</dd>
<dt>
- <a name = "isFinite"></a>
- <strong>isFinite (obj)</strong>
+ <a name = "result"></a>
+ <strong>result (obj, method[, ...])</strong>
</dt>
<dd>
- Checks if the given argument is a finite number.
+ Invokes an object method. It passes the object itself as the first argument. if <code>method</code> is not
+ callable, will return <code>obj[method]</code>.
<h3>Parameters:</h3>
@@ -4931,12 +6393,19 @@
<li><span class="parameter">obj</span>
an object
</li>
+ <li><span class="parameter">method</span>
+ a string key to index in object <code>obj</code>.
+ </li>
+ <li><span class="parameter">...</span>
+ Optional args to be passed to <code>method</code>
+ (<em>optional</em>)
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ the returned value of <code>method (obj, ...)</code> call
</ol>
@@ -4944,11 +6413,13 @@
</dd>
<dt>
- <a name = "isBoolean"></a>
- <strong>isBoolean (obj)</strong>
+ <a name = "tap"></a>
+ <strong>tap (obj, f[, ...])</strong>
</dt>
<dd>
- Checks if the given argument is a boolean.
+ Invokes interceptor with the object, and then returns object.
+ The primary purpose of this method is to "tap into" a method chain, in order to perform operations
+ on intermediate results within the chain.
<h3>Parameters:</h3>
@@ -4956,12 +6427,19 @@
<li><span class="parameter">obj</span>
an object
</li>
+ <li><span class="parameter">f</span>
+ an interceptor function, should be prototyped as <code>f (obj, ...)</code>
+ </li>
+ <li><span class="parameter">...</span>
+ args to be passed to <code>f</code>
+ (<em>optional</em>)
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ the passed-in object
</ol>
@@ -4969,11 +6447,12 @@
</dd>
<dt>
- <a name = "isInteger"></a>
- <strong>isInteger (obj)</strong>
+ <a name = "template"></a>
+ <strong>template (obj[, template])</strong>
</dt>
<dd>
- Checks if the given argument is an integer.
+ Applies a template to an object, preserving non-nil properties.
+ <br/><em>Aliased as <code>defaults</code></em>.
<h3>Parameters:</h3>
@@ -4981,12 +6460,16 @@
<li><span class="parameter">obj</span>
an object
</li>
+ <li><span class="parameter">template</span>
+ a template object. If <code>nil</code>, leaves <code>obj</code> untouched.
+ (<em>optional</em>)
+ </li>
</ul>
<h3>Returns:</h3>
<ol>
- <code>true</code> or <code>false</code>
+ the passed-in object filled
</ol>
@@ -4994,25 +6477,24 @@
</dd>
<dt>
- <a name = "chain"></a>
- <strong>chain (value)</strong>
+ <a name = "toBoolean"></a>
+ <strong>toBoolean (value)</strong>
</dt>
<dd>
- Returns a wrapped object. Calling library functions as methods on this object
- will continue to return wrapped objects until <a href="index.html#obj:value">obj:value</a> is used. Can be aliased as <code>_(value)</code>.
+ Converts any given value to a boolean
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">value</span>
- a value to be wrapped
+ a value. Can be of any type
</li>
</ul>
<h3>Returns:</h3>
<ol>
- a wrapped object
+ <code>true</code> if value is true, <code>false</code> otherwise (false or nil).
</ol>
@@ -5020,48 +6502,55 @@
</dd>
<dt>
- <a name = "obj:value"></a>
- <strong>obj:value ()</strong>
+ <a name = "toObj"></a>
+ <strong>toObj (kvpairs)</strong>
</dt>
<dd>
- Extracts the value of a wrapped object. Must be called on an chained object (see <a href="index.html#chain">chain</a>).
+ Converts an array list of <code>[k,v]</code> pairs to an object. Keys are taken
+ from the 1rst column in the <code>[k,v]</code> pairs sequence, associated with values in the 2nd
+ column.
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">kvpairs</span>
+ an array-list of <code>[k,v]</code> pairs
+ </li>
+ </ul>
<h3>Returns:</h3>
<ol>
- the value previously wrapped
+ an object
</ol>
+ <h3>See also:</h3>
+ <ul>
+ <a href="index.html#kvpairs">kvpairs</a>
+ </ul>
</dd>
<dt>
- <a name = "import"></a>
- <strong>import ([context[, noConflict]])</strong>
+ <a name = "values"></a>
+ <strong>values (obj)</strong>
</dt>
<dd>
- Imports all library functions into a context.
+ Returns the values of the object properties.
<h3>Parameters:</h3>
<ul>
- <li><span class="parameter">context</span>
- a context. Defaults to <code>_G</code> (global environment) when not given.
- (<em>optional</em>)
- </li>
- <li><span class="parameter">noConflict</span>
- if supplied, will not import functions having a key existing in the destination context.
- (<em>optional</em>)
+ <li><span class="parameter">obj</span>
+ an object
</li>
</ul>
<h3>Returns:</h3>
<ol>
- the passed-in context
+ an array of values
</ol>
@@ -5075,7 +6564,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
-<i style="float:right;">Last updated 2017-04-27 15:26:55 </i>
+<i style="float:right;">Last updated 2018-08-22 18:44:44 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
diff --git a/doc/ldoc.css b/doc/ldoc.css
deleted file mode 100644
index 52c4ad2..0000000
--- a/doc/ldoc.css
+++ /dev/null
@@ -1,303 +0,0 @@
-/* BEGIN RESET
-
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 2.8.2r1
-*/
-html {
- color: #000;
- background: #FFF;
-}
-body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
- margin: 0;
- padding: 0;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-fieldset,img {
- border: 0;
-}
-address,caption,cite,code,dfn,em,strong,th,var,optgroup {
- font-style: inherit;
- font-weight: inherit;
-}
-del,ins {
- text-decoration: none;
-}
-li {
- margin-left: 20px;
-}
-caption,th {
- text-align: left;
-}
-h1,h2,h3,h4,h5,h6 {
- font-size: 100%;
- font-weight: bold;
-}
-q:before,q:after {
- content: '';
-}
-abbr,acronym {
- border: 0;
- font-variant: normal;
-}
-sup {
- vertical-align: baseline;
-}
-sub {
- vertical-align: baseline;
-}
-legend {
- color: #000;
-}
-input,button,textarea,select,optgroup,option {
- font-family: inherit;
- font-size: inherit;
- font-style: inherit;
- font-weight: inherit;
-}
-input,button,textarea,select {*font-size:100%;
-}
-/* END RESET */
-
-body {
- margin-left: 1em;
- margin-right: 1em;
- font-family: arial, helvetica, geneva, sans-serif;
- background-color: #ffffff; margin: 0px;
-}
-
-code, tt { font-family: monospace; font-size: 1.1em; }
-span.parameter { font-family:monospace; }
-span.parameter:after { content:":"; }
-span.types:before { content:"("; }
-span.types:after { content:")"; }
-.type { font-weight: bold; font-style:italic }
-
-body, p, td, th { font-size: .95em; line-height: 1.2em;}
-
-p, ul { margin: 10px 0 0 0px;}
-
-strong { font-weight: bold;}
-
-em { font-style: italic;}
-
-h1 {
- font-size: 1.5em;
- margin: 20px 0 20px 0;
-}
-h2, h3, h4 { margin: 15px 0 10px 0; }
-h2 { font-size: 1.25em; }
-h3 { font-size: 1.15em; }
-h4 { font-size: 1.06em; }
-
-a:link { font-weight: bold; color: #004080; text-decoration: none; }
-a:visited { font-weight: bold; color: #006699; text-decoration: none; }
-a:link:hover { text-decoration: underline; }
-
-hr {
- color:#cccccc;
- background: #00007f;
- height: 1px;
-}
-
-blockquote { margin-left: 3em; }
-
-ul { list-style-type: disc; }
-
-p.name {
- font-family: "Andale Mono", monospace;
- padding-top: 1em;
-}
-
-pre {
- background-color: rgb(245, 245, 245);
- border: 1px solid #C0C0C0; /* silver */
- padding: 10px;
- margin: 10px 0 10px 0;
- overflow: auto;
- font-family: "Andale Mono", monospace;
-}
-
-pre.example {
- font-size: .85em;
-}
-
-table.index { border: 1px #00007f; }
-table.index td { text-align: left; vertical-align: top; }
-
-#container {
- margin-left: 1em;
- margin-right: 1em;
- background-color: #f0f0f0;
-}
-
-#product {
- text-align: center;
- border-bottom: 1px solid #cccccc;
- background-color: #ffffff;
-}
-
-#product big {
- font-size: 2em;
-}
-
-#main {
- background-color: #f0f0f0;
- border-left: 2px solid #cccccc;
-}
-
-#navigation {
- float: left;
- width: 14em;
- vertical-align: top;
- background-color: #f0f0f0;
- overflow: visible;
-}
-
-#navigation h2 {
- background-color:#e7e7e7;
- font-size:1.1em;
- color:#000000;
- text-align: left;
- padding:0.2em;
- border-top:1px solid #dddddd;
- border-bottom:1px solid #dddddd;
-}
-
-#navigation ul
-{
- font-size:1em;
- list-style-type: none;
- margin: 1px 1px 10px 1px;
-}
-
-#navigation li {
- text-indent: -1em;
- display: block;
- margin: 3px 0px 0px 22px;
-}
-
-#navigation li li a {
- margin: 0px 3px 0px -1em;
-}
-
-#content {
- margin-left: 14em;
- padding: 1em;
- width: 700px;
- border-left: 2px solid #cccccc;
- border-right: 2px solid #cccccc;
- background-color: #ffffff;
-}
-
-#about {
- clear: both;
- padding: 5px;
- border-top: 2px solid #cccccc;
- background-color: #ffffff;
-}
-
-@media print {
- body {
- font: 12pt "Times New Roman", "TimeNR", Times, serif;
- }
- a { font-weight: bold; color: #004080; text-decoration: underline; }
-
- #main {
- background-color: #ffffff;
- border-left: 0px;
- }
-
- #container {
- margin-left: 2%;
- margin-right: 2%;
- background-color: #ffffff;
- }
-
- #content {
- padding: 1em;
- background-color: #ffffff;
- }
-
- #navigation {
- display: none;
- }
- pre.example {
- font-family: "Andale Mono", monospace;
- font-size: 10pt;
- page-break-inside: avoid;
- }
-}
-
-table.module_list {
- border-width: 1px;
- border-style: solid;
- border-color: #cccccc;
- border-collapse: collapse;
-}
-table.module_list td {
- border-width: 1px;
- padding: 3px;
- border-style: solid;
- border-color: #cccccc;
-}
-table.module_list td.name { background-color: #f0f0f0; min-width: 200px; }
-table.module_list td.summary { width: 100%; }
-
-
-table.function_list {
- border-width: 1px;
- border-style: solid;
- border-color: #cccccc;
- border-collapse: collapse;
-}
-table.function_list td {
- border-width: 1px;
- padding: 3px;
- border-style: solid;
- border-color: #cccccc;
-}
-table.function_list td.name { background-color: #f0f0f0; min-width: 200px; }
-table.function_list td.summary { width: 100%; }
-
-ul.nowrap {
- overflow:auto;
- white-space:nowrap;
-}
-
-dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
-dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
-dl.table h3, dl.function h3 {font-size: .95em;}
-
-/* stop sublists from having initial vertical space */
-ul ul { margin-top: 0px; }
-ol ul { margin-top: 0px; }
-ol ol { margin-top: 0px; }
-ul ol { margin-top: 0px; }
-
-/* make the target distinct; helps when we're navigating to a function */
-a:target + * {
- background-color: #FF9;
-}
-
-
-/* styles for prettification of source */
-pre .comment { color: #558817; }
-pre .constant { color: #a8660d; }
-pre .escape { color: #844631; }
-pre .keyword { color: #aa5050; font-weight: bold; }
-pre .library { color: #0e7c6b; }
-pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
-pre .string { color: #8080ff; }
-pre .number { color: #f8660d; }
-pre .operator { color: #2239a8; font-weight: bold; }
-pre .preprocessor, pre .prepro { color: #a33243; }
-pre .global { color: #800080; }
-pre .user-keyword { color: #800080; }
-pre .prompt { color: #558817; }
-pre .url { color: #272fc2; text-decoration: underline; }
-
diff --git a/doc/topics/tutorial.md.html b/doc/manual/tutorial.md.html
index 1acd09f..f06e248 100644
--- a/doc/topics/tutorial.md.html
+++ b/doc/manual/tutorial.md.html
@@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Moses documentation</title>
- <link rel="stylesheet" href="../ldoc.css" type="text/css" />
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
</head>
<body>
@@ -38,13 +38,13 @@
</ul>
-<h2>Topics</h2>
-<ul class="">
+<h2>Manual</h2>
+<ul class="nowrap">
<li><strong>tutorial</strong></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
- <li><a href="../index.html">moses</a></li>
+ <li><a href="index.html">moses</a></li>
</ul>
</div>
@@ -54,364 +54,394 @@
<em>Moses: a utility-belt library for functional programming in Lua</em></p>
<p><strong>Moses</strong> is a Lua utility library which provides support for functional programming.
-It complements built-in Lua functions, making easier common operations on tables, arrays, lists, collections, objects, and a lot more.<br/>
-<strong>Moses</strong> was deeply inspired by <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>. </p>
+It complements built-in Lua functions, making easier common operations on tables, arrays, lists, collections, objects, and a lot more.
+<br/>
+<br/></p>
+
+<h1><a name='TOC'>Sections</a></h1>
-<h1><a name='TOC'>Table of Contents</a></h1>
<ul>
-<li><a href="#adding">Adding <em>Moses</em> to your project</a></li>
-<li><a href="#table">Table functions</a></li>
-<li><a href="#array">Array functions</a></li>
-<li><a href="#utility">Utility functions</a></li>
-<li><a href="#object">Object functions</a></li>
-<li><a href="#chaining">Chaining</a></li>
-<li><a href="#import">Import</a></li>
+ <li><a href="#adding">Adding <em>Moses</em> to your project</a></li>
+ <li><a href="#table">Table functions</a></li>
+ <li><a href="#array">Array functions</a></li>
+ <li><a href="#utility">Utility functions</a></li>
+ <li><a href="#object">Object functions</a></li>
+ <li><a href="#chaining">Chaining</a></li>
+ <li><a href="#import">Import</a>
+ <br/><br/>
+ <h1><a name='adding'>Adding <em>Moses</em> to your project</a></h1></li>
</ul>
-
-<h1><a name='adding'>Adding <em>Moses</em> to your project</a></h1>
-
<p>Drop the file <a href="http://github.com/Yonaba/Moses/blob/master/moses.lua">moses.lua</a> into your project and add it to your code with the <em>require</em> function:</p>
+
<pre>
-<span class="keyword">local</span> _ = <span class="global">require</span> (<span class="string">"moses"</span>)
+<span class="keyword">local</span> M = <span class="global">require</span> (<span class="string">"moses"</span>)
</pre>
-<p><em>Note: Lua purists tend to use &ldquo;_&rdquo; to design a &ldquo;dummy variable&rdquo;. Here, the usage of this underscore is quite idiomatic and refers to the name <a href="http://documentcloud.github.com/underscore/">Underscore</a>, the JS library from which </em>Moses<em> takes inspiration</em>.</p>
-
-<p><em>Moses</em>&lsquo; provides a large set of functions that can be classified into four categories:</p>
+<p><em>Moses</em> provides a large set of functions that can be classified into four categories:</p>
<ul>
-<li><strong>Table functions</strong>, which are mostly meant for tables, i.e Lua tables which contains both an array-part and a hash-part,</li>
-<li><strong>Array functions</strong>, meant for array lists (or sequences),</li>
-<li><strong>Utility functions</strong>,</li>
-<li><strong>Object functions</strong>.</li>
+ <li><a href="#table"><strong>Table functions</strong></a>, which are mostly meant for tables, i.e Lua tables which contains both an array-part and a hash-part,</li>
+ <li><a href="#array"><strong>Array functions</strong></a>, meant for array lists (or sequences),</li>
+ <li><a href="#utility"><strong>Utility functions</strong></a>,</li>
+ <li><a href="#object"><strong>Object functions</strong></a>.</li>
</ul>
-
<p><strong><a href="#TOC">[⬆]</a></strong></p>
<p><a name="_a_name__table__Table_functions__a_"></a></p>
-
<h2><a name='table'>Table functions</a></h2>
<h3>clear (t)</h3>
-<p>Clears a table. All its values becomes nil. It returns the passed-in table.</p>
+<p>Clears a table. All its values becomes nil. Returns the passed-in table.</p>
+
<pre>
-<span class="keyword">local</span> t = _.clear({<span class="number">1</span>,<span class="number">2</span>,<span class="string">'hello'</span>,<span class="keyword">true</span>}) <span class="comment">-- =&gt; {}</span>
+M.clear({<span class="number">1</span>,<span class="number">2</span>,<span class="string">'hello'</span>,<span class="keyword">true</span>}) <span class="comment">-- =&gt; {}</span>
</pre>
-<h3>each (t, f, &hellip;)</h3>
+<h3>each (t, f [, ...])</h3>
+<p>*Aliases: <code>forEach</code>*.</p>
-<p><em>Aliases: <code>_.forEach</code></em>.</p>
+<p>Iterates over each value-key pair in the passed-in table.</p>
-<p>Iterates over each key-value pair in table.</p>
<pre>
-_.each({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="global">print</span>)
+M.each({<span class="number">4</span>,<span class="number">2</span>,<span class="number">1</span>},<span class="global">print</span>)
-<span class="comment">-- =&gt; 1 1
+<span class="comment">-- =&gt; 4 1
</span><span class="comment">-- =&gt; 2 2
-</span><span class="comment">-- =&gt; 3 3</span>
+</span><span class="comment">-- =&gt; 1 3</span>
</pre>
-<p>The table can be map-like (array part and hash-part).</p>
+<p>The table can be map-like (both array part and hash part).</p>
+
<pre>
-_.each({one = <span class="number">1</span>, two = <span class="number">2</span>, three = <span class="number">3</span>},<span class="global">print</span>)
+M.each({one = <span class="number">1</span>, two = <span class="number">2</span>, three = <span class="number">3</span>},<span class="global">print</span>)
-<span class="comment">-- =&gt; one 1
-</span><span class="comment">-- =&gt; two 2
-</span><span class="comment">-- =&gt; three 3</span>
+<span class="comment">-- =&gt; 1 one
+</span><span class="comment">-- =&gt; 2 two
+</span><span class="comment">-- =&gt; 3 three</span>
</pre>
<p>Can index and assign in an outer table or in the passed-in table:</p>
+
<pre>
t = {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>}
-_.each(t,<span class="keyword">function</span>(i,v)
+M.each(t,<span class="keyword">function</span>(v,i)
t[i] = v:rep(<span class="number">2</span>)
<span class="global">print</span>(t[i])
<span class="keyword">end</span>)
-<span class="comment">-- =&gt; 1 aa
-</span><span class="comment">-- =&gt; 2 bb
-</span><span class="comment">-- =&gt; 3 cc</span>
+<span class="comment">-- =&gt; aa
+</span><span class="comment">-- =&gt; bb
+</span><span class="comment">-- =&gt; cc</span>
</pre>
-<h3>eachi (t, f, &hellip;)</h3>
+<h3>eachi (t, f [, ...])</h3>
+<p>*Aliases: <code>forEachi</code>*.</p>
-<p><em>Aliases: <code>_.forEachi</code></em>.</p>
+<p>Iterates only on integer keys in an array table. It returns value-key pairs.</p>
-<p>Iterates only on integer keys in a sparse array table.</p>
<pre>
-_.eachi({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="global">print</span>)
+M.eachi({<span class="number">4</span>,<span class="number">2</span>,<span class="number">1</span>},<span class="global">print</span>)
-<span class="comment">-- =&gt; 1 1
+<span class="comment">-- =&gt; 4 1
</span><span class="comment">-- =&gt; 2 2
-</span><span class="comment">-- =&gt; 3 3</span>
+</span><span class="comment">-- =&gt; 1 3</span>
</pre>
<p>The given array can be sparse, or even have a hash-like part.</p>
+
<pre>
<span class="keyword">local</span> t = {a = <span class="number">1</span>, b = <span class="number">2</span>, [<span class="number">0</span>] = <span class="number">1</span>, [-<span class="number">1</span>] = <span class="number">6</span>, <span class="number">3</span>, x = <span class="number">4</span>, <span class="number">5</span>}
-_.eachi(t,<span class="keyword">function</span>(i,v)
- <span class="global">print</span>(i,v)
-<span class="keyword">end</span>)
+M.eachi(t,<span class="global">print</span>)
-<span class="comment">-- =&gt; -1 6
-</span><span class="comment">-- =&gt; 0 1
-</span><span class="comment">-- =&gt; 1 3
-</span><span class="comment">-- =&gt; 2 5</span>
+<span class="comment">-- =&gt; 6 -1
+</span><span class="comment">-- =&gt; 1 0
+</span><span class="comment">-- =&gt; 3 1
+</span><span class="comment">-- =&gt; 5 2</span>
</pre>
-<h3>at (t, &hellip;)</h3>
+<h3>at (t, ...)</h3>
+
+<p>Collects values at given keys and returns them in an array.</p>
-<p>Collects all values at some specific keys and returns them in an array.</p>
<pre>
<span class="keyword">local</span> t = {<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}
-_.at(t,<span class="number">1</span>,<span class="number">3</span>) <span class="comment">-- =&gt; "{4,6}"
+M.at(t,<span class="number">1</span>,<span class="number">3</span>) <span class="comment">-- =&gt; "{4,6}"
</span>
<span class="keyword">local</span> t = {a = <span class="number">4</span>, bb = <span class="keyword">true</span>, ccc = <span class="keyword">false</span>}
-_.at(t,<span class="string">'a'</span>, <span class="string">'ccc'</span>) <span class="comment">-- =&gt; "{4, false}"</span>
+M.at(t,<span class="string">'a'</span>, <span class="string">'ccc'</span>) <span class="comment">-- =&gt; "{4, false}"</span>
</pre>
-<h3>count (t, value)</h3>
+<h3>adjust (t, key, f [, ...])</h3>
+
+<p>Adjusts the value at a given key using a function or a value. In case <code>f</code> is a function, it should be prototyped <code>f(v, ...)</code>. It does not mutate the given table, but rather returns a new array.</p>
+
+
+<pre>
+<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+M.adjust(t, <span class="number">2</span>, <span class="global">math</span>.sin) <span class="comment">-- =&gt; {1, 0.90929, 3}
+</span>
+<span class="keyword">local</span> v = {x = <span class="number">1</span>}
+ M.adjust(t, <span class="string">'x'</span>, <span class="number">4</span>) <span class="comment">-- =&gt; {x = 4}</span>
+</pre>
+
+
+<p>In case the given <code>key</code> does not exist in <code>t</code>, it throws an error.</p>
+
+<h3>count (t [, val])</h3>
<p>Counts the number of occurences of a given value in a table.</p>
+
<pre>
-_.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>},<span class="number">1</span>) <span class="comment">-- =&gt; 2
-</span>_.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>},<span class="number">2</span>) <span class="comment">-- =&gt; 2
-</span>_.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>},<span class="number">3</span>) <span class="comment">-- =&gt; 4
-</span>_.count({<span class="keyword">false</span>, <span class="keyword">false</span>, <span class="keyword">true</span>},<span class="keyword">false</span>) <span class="comment">-- =&gt; 2
-</span>_.count({<span class="keyword">false</span>, <span class="keyword">false</span>, <span class="keyword">true</span>},<span class="keyword">true</span>) <span class="comment">-- =&gt; 1</span>
+M.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>},<span class="number">1</span>) <span class="comment">-- =&gt; 2
+</span>M.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>},<span class="number">2</span>) <span class="comment">-- =&gt; 3
+</span>M.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>},<span class="number">3</span>) <span class="comment">-- =&gt; 4
+</span>M.count({<span class="keyword">false</span>, <span class="keyword">false</span>, <span class="keyword">true</span>},<span class="keyword">false</span>) <span class="comment">-- =&gt; 2
+</span>M.count({<span class="keyword">false</span>, <span class="keyword">false</span>, <span class="keyword">true</span>},<span class="keyword">true</span>) <span class="comment">-- =&gt; 1</span>
</pre>
<p>Returns the size of the list in case no value was provided.</p>
+
<pre>
-_.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; 5</span>
+M.count({<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; 5</span>
</pre>
-<h3>countf (t, f, &hellip;)</h3>
+<h3>countf (t, f [, ...])</h3>
+
+<p>Counts the number of values passing an iterator test.</p>
-<p>Count the number of occurences of all values passing an iterator test.</p>
<pre>
-_.countf({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}, <span class="keyword">function</span>(i,v)
+M.countf({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}, <span class="keyword">function</span>(v)
<span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span>
<span class="keyword">end</span>) <span class="comment">-- =&gt; 3
</span>
-_.countf({<span class="global">print</span>, <span class="global">pairs</span>, <span class="global">os</span>, <span class="global">assert</span>, <span class="global">ipairs</span>}, <span class="keyword">function</span>(i,v)
+M.countf({<span class="global">print</span>, <span class="global">pairs</span>, <span class="global">os</span>, <span class="global">assert</span>, <span class="global">ipairs</span>}, <span class="keyword">function</span>(v)
<span class="keyword">return</span> <span class="global">type</span>(v)==<span class="string">'function'</span>
<span class="keyword">end</span>) <span class="comment">-- =&gt; 4</span>
</pre>
-<h3>cycle (t, n)</h3>
-
-<p><em>Aliases: <code>_.loop</code></em>.</p>
+<h3>cycle (t [, n = 1])</h3>
+<p>*Aliases: <code>loop</code>*.</p>
-<p>Returns a function which iterates on each key-value pair in a given table (similarly to <code>_.each</code>), except that it restarts iterating again <code>n</code> times.
+<p>Returns a function which iterates on each value-key pair in a given table (similarly to <code>M.each</code>), except that it restarts iterating again <code>n</code> times.
If <code>n</code> is not provided, it defaults to 1.</p>
+
<pre>
-<span class="keyword">local</span> t = {<span class="string">'a,'</span>b<span class="string">','</span>c<span class="string">'}
-for k,v in _.cycle(t, 2) do
- print(k,v)
-end
+<span class="keyword">local</span> t = {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>}
+<span class="keyword">for</span> v <span class="keyword">in</span> M.cycle(t, <span class="number">2</span>) <span class="keyword">do</span>
+ <span class="global">print</span>(v)
+<span class="keyword">end</span>
--- =&gt; 1 '</span>a<span class="string">'
--- =&gt; 2 '</span>b<span class="string">'
--- =&gt; 3 '</span>c<span class="string">'
--- =&gt; 1 '</span>a<span class="string">'
--- =&gt; 2 '</span>b<span class="string">'
--- =&gt; 3 '</span>c'
+<span class="comment">-- =&gt; 'a'
+</span><span class="comment">-- =&gt; 'b'
+</span><span class="comment">-- =&gt; 'c'
+</span><span class="comment">-- =&gt; 'a'
+</span><span class="comment">-- =&gt; 'b'
+</span><span class="comment">-- =&gt; 'c'</span>
</pre>
<p>Supports array-like tables and map-like tables.</p>
+
<pre>
<span class="keyword">local</span> t = {x = <span class="number">1</span>, y = <span class="number">2</span>, z = <span class="number">3</span>}
-<span class="keyword">for</span> k,v <span class="keyword">in</span> _.cycle(t) <span class="keyword">do</span>
- <span class="global">print</span>(k,v)
+<span class="keyword">for</span> v <span class="keyword">in</span> M.cycle(t) <span class="keyword">do</span>
+ <span class="global">print</span>(v)
<span class="keyword">end</span>
-<span class="comment">-- =&gt; y 2
-</span><span class="comment">-- =&gt; x 1
-</span><span class="comment">-- =&gt; z 3</span>
+<span class="comment">-- =&gt; 2
+</span><span class="comment">-- =&gt; 1
+</span><span class="comment">-- =&gt; 3</span>
</pre>
-<h3>map (t, f, &hellip;)</h3>
+<h3>map (t, f [, ...])</h3>
+<p>*Aliases: <code>collect</code>*.</p>
-<p><em>Aliases: <code>_.collect</code></em>.</p>
+<p>Executes a function on each value in a given array.</p>
-<p>Executes a function on each key-value pairs.</p>
<pre>
-_.map({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="keyword">function</span>(i,v)
+M.map({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="keyword">function</span>(v)
<span class="keyword">return</span> v+<span class="number">10</span>
<span class="keyword">end</span>) <span class="comment">-- =&gt; "{11,12,13}"</span>
</pre>
+
<pre>
-_.map({a = <span class="number">1</span>, b = <span class="number">2</span>},<span class="keyword">function</span>(k,v)
+M.map({a = <span class="number">1</span>, b = <span class="number">2</span>},<span class="keyword">function</span>(v, k)
<span class="keyword">return</span> k..v
<span class="keyword">end</span>) <span class="comment">-- =&gt; "{a = 'a1', b = 'b2'}"</span>
</pre>
-<p>It also maps key-value pairs to key-value pairs</p>
+<p>It also maps both keys and values.</p>
+
<pre>
-_.map({a = <span class="number">1</span>, b = <span class="number">2</span>},<span class="keyword">function</span>(k,v)
+M.map({a = <span class="number">1</span>, b = <span class="number">2</span>},<span class="keyword">function</span>(v, k)
<span class="keyword">return</span> k..k, v*<span class="number">2</span>
<span class="keyword">end</span>) <span class="comment">-- =&gt; "{aa = 2, bb = 4}"</span>
</pre>
-<h3>reduce (t, f, state)</h3>
+<h3>reduce (t, f [, state = next(t)])</h3>
+<p>*Aliases: <code>inject</code>, <code>foldl</code>*.</p>
-<p><em>Aliases: <code>_.inject</code>, <code>_.foldl</code></em>.</p>
+<p>Can sum all values in a table. In case <code>state</code> is not provided, it defaults to the first value in the given table <code>t</code>.</p>
-<p>Can sums all values in a table.</p>
<pre>
-_.reduce({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>},<span class="keyword">function</span>(memo,v)
- <span class="keyword">return</span> memo+v
-<span class="keyword">end</span>) <span class="comment">-- =&gt; 10</span>
+<span class="keyword">local</span> <span class="keyword">function</span> add(a,b) <span class="keyword">return</span> a+b <span class="keyword">end</span>
+M.reduce({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>},add) <span class="comment">-- =&gt; 10</span>
</pre>
<p>Or concatenates all values.</p>
+
<pre>
-_.reduce({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>},<span class="keyword">function</span>(memo,v)
- <span class="keyword">return</span> memo..v
-<span class="keyword">end</span>) <span class="comment">-- =&gt; abcd </span>
+<span class="keyword">local</span> <span class="keyword">function</span> concat(a,b) <span class="keyword">return</span> a..b <span class="keyword">end</span>
+M.reduce({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>},concat) <span class="comment">-- =&gt; abcd </span>
</pre>
-<h3>reduceby (t, f, state, pred, &hellip;)</h3>
+<h3>reduceby (t, f, pred [, state = next(t) [, ...]])</h3>
<p>Reduces a table considering only values matching a predicate.
For example,let us define a set of values.</p>
+
<pre>
<span class="keyword">local</span> val = {-<span class="number">1</span>, <span class="number">8</span>, <span class="number">0</span>, -<span class="number">6</span>, <span class="number">3</span>, -<span class="number">1</span>, <span class="number">7</span>, <span class="number">1</span>, -<span class="number">9</span>}
</pre>
+<p>And a reduction function which will add up values.</p>
+
+
+<pre>
+<span class="keyword">local</span> <span class="keyword">function</span> add(a,b) <span class="keyword">return</span> a+b <span class="keyword">end</span>
+</pre>
+
+
<p>We can also define some predicate functions.</p>
+
<pre>
<span class="comment">-- predicate for negative values
-</span><span class="keyword">local</span> <span class="keyword">function</span> neg(_, v) <span class="keyword">return</span> v&lt;=<span class="number">0</span> <span class="keyword">end</span>
+</span><span class="keyword">local</span> <span class="keyword">function</span> neg(v) <span class="keyword">return</span> v&lt;=<span class="number">0</span> <span class="keyword">end</span>
<span class="comment">-- predicate for positive values
-</span><span class="keyword">local</span> <span class="keyword">function</span> pos(_, v) <span class="keyword">return</span> v&gt;=<span class="number">0</span> <span class="keyword">end</span>
+</span><span class="keyword">local</span> <span class="keyword">function</span> pos(v) <span class="keyword">return</span> v&gt;=<span class="number">0</span> <span class="keyword">end</span>
</pre>
-<p>Then we can perform reduction considering only negative values :</p>
+<p>Then we can perform reduction considering only negative or positive values :</p>
+
<pre>
-_.reduceby(val, <span class="keyword">function</span>(memo,v)
- <span class="keyword">return</span> memo+v
-<span class="keyword">end</span>, <span class="number">0</span>, neg) <span class="comment">-- =&gt; -17</span>
+M.reduceby(val, add, neg) <span class="comment">-- =&gt; -17
+</span>M.reduceby(val, add, pos) <span class="comment">-- =&gt; 19</span>
</pre>
-<p>Or only positive values :</p>
+<p>An initial state can be passed in.</p>
+
<pre>
-_.reduceby(val, <span class="keyword">function</span>(memo,v)
- <span class="keyword">return</span> memo+v
-<span class="keyword">end</span>, <span class="number">0</span>, pos) <span class="comment">-- =&gt; 19</span>
+M.reduceby(val, add, neg, <span class="number">17</span>) <span class="comment">-- =&gt; 0
+</span>M.reduceby(val, add, pos, -<span class="number">19</span>) <span class="comment">-- =&gt; 0</span>
</pre>
-<h3>reduceRight (t, f, state)</h3>
+<h3>reduceRight (t, f [, state = next(t)])</h3>
+<p>*Aliases: <code>injectr</code>, <code>foldr</code>*.</p>
-<p><em>Aliases: <code>_.injectr</code>, <code>_.foldr</code></em>.</p>
+<p>Similar to <code>M.reduce</code>, but performs from right to left.</p>
-<p>Similar to <code>_.reduce</code>, but performs from right to left.</p>
<pre>
<span class="keyword">local</span> initial_state = <span class="number">256</span>
-_.reduceRight({<span class="number">1</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">16</span>},<span class="keyword">function</span>(memo,v)
- <span class="keyword">return</span> memo/v
-<span class="keyword">end</span>,initial_state) <span class="comment">-- =&gt; 2</span>
+<span class="keyword">local</span> <span class="keyword">function</span> div(a,b) <span class="keyword">return</span> a/b <span class="keyword">end</span>
+M.reduceRight({<span class="number">1</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">16</span>},div,initial_state) <span class="comment">-- =&gt; 2</span>
</pre>
-<h3>mapReduce (t, f, state)</h3>
-
-<p><em>Aliases: <code>_.mapr</code></em>.</p>
+<h3>mapReduce (t, f [, state = next(t)])</h3>
+<p>*Aliases: <code>mapr</code>*.</p>
<p>Reduces while saving intermediate states.</p>
+
<pre>
-_.mapReduce({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>},<span class="keyword">function</span>(memo,v)
- <span class="keyword">return</span> memo..v
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{'a', 'ab', 'abc'}"</span>
+<span class="keyword">local</span> <span class="keyword">function</span> concat(a,b) <span class="keyword">return</span> a..b <span class="keyword">end</span>
+M.mapReduce({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>},concat) <span class="comment">-- =&gt; "{'a', 'ab', 'abc'}"</span>
</pre>
-<h3>mapReduceRight (t, f, state)</h3>
-
-<p><em>Aliases: <code>_.maprr</code></em>.</p>
+<h3>mapReduceRight (t, f [, state = next(t)])</h3>
+<p>*Aliases: <code>maprr</code>*.</p>
<p>Reduces from right to left, while saving intermediate states.</p>
+
<pre>
-_.mapReduceRight({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>},<span class="keyword">function</span>(memo,v)
- <span class="keyword">return</span> memo..v
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{'c', 'cb', 'cba'}"</span>
+<span class="keyword">local</span> <span class="keyword">function</span> concat(a,b) <span class="keyword">return</span> a..b <span class="keyword">end</span>
+M.mapReduceRight({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>},concat) <span class="comment">-- =&gt; "{'c', 'cb', 'cba'}"</span>
</pre>
<h3>include (t, value)</h3>
-
-<p><em>Aliases: <code>_.any</code>, <code>_.some</code>, <code>_.contains</code></em>.</p>
+<p>*Aliases: <code>any</code>, <code>some</code>, <code>contains</code>*.</p>
<p>Looks for a value in a table.</p>
+
<pre>
-_.include({<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>,<span class="number">16</span>,<span class="number">29</span>},<span class="number">16</span>) <span class="comment">-- =&gt; true
-</span>_.include({<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>,<span class="number">16</span>,<span class="number">29</span>},<span class="number">1</span>) <span class="comment">-- =&gt; false
+M.include({<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>,<span class="number">16</span>,<span class="number">29</span>},<span class="number">16</span>) <span class="comment">-- =&gt; true
+</span>M.include({<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>,<span class="number">16</span>,<span class="number">29</span>},<span class="number">1</span>) <span class="comment">-- =&gt; false
</span>
<span class="keyword">local</span> complex_table = {<span class="number">18</span>,{<span class="number">2</span>,{<span class="number">3</span>}}}
<span class="keyword">local</span> collection = {<span class="number">6</span>,{<span class="number">18</span>,{<span class="number">2</span>,<span class="number">6</span>}},<span class="number">10</span>,{<span class="number">18</span>,{<span class="number">2</span>,{<span class="number">3</span>}}},<span class="number">29</span>}
-_.include(collection, complex_table) <span class="comment">-- =&gt; true</span>
+M.include(collection, complex_table) <span class="comment">-- =&gt; true</span>
</pre>
<p>Handles iterator functions.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> isUpper(v) <span class="keyword">return</span> v:upper()== v <span class="keyword">end</span>
-_.include({<span class="string">'a'</span>,<span class="string">'B'</span>,<span class="string">'c'</span>},isUpper) <span class="comment">-- =&gt; true</span>
+M.include({<span class="string">'a'</span>,<span class="string">'B'</span>,<span class="string">'c'</span>},isUpper) <span class="comment">-- =&gt; true</span>
</pre>
@@ -419,23 +449,25 @@ _.include({<span class="string">'a'</span>,<span class="string">'B'</span>,<span
<p>Returns the index of a value in a table.</p>
+
<pre>
-_.detect({<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>,<span class="number">16</span>},<span class="number">8</span>) <span class="comment">-- =&gt; 2
-</span>_.detect({<span class="keyword">nil</span>,<span class="keyword">true</span>,<span class="number">0</span>,<span class="keyword">true</span>,<span class="keyword">true</span>},<span class="keyword">false</span>) <span class="comment">-- =&gt; nil
+M.detect({<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>,<span class="number">16</span>},<span class="number">8</span>) <span class="comment">-- =&gt; 2
+</span>M.detect({<span class="keyword">nil</span>,<span class="keyword">true</span>,<span class="number">0</span>,<span class="keyword">true</span>,<span class="keyword">true</span>},<span class="keyword">false</span>) <span class="comment">-- =&gt; nil
</span>
<span class="keyword">local</span> complex_table = {<span class="number">18</span>,{<span class="number">2</span>,<span class="number">6</span>}}
<span class="keyword">local</span> collection = {<span class="number">6</span>,{<span class="number">18</span>,{<span class="number">2</span>,<span class="number">6</span>}},<span class="number">10</span>,{<span class="number">18</span>,{<span class="number">2</span>,{<span class="number">3</span>}}},<span class="number">29</span>}
-_.detect(collection, complex_table) <span class="comment">-- =&gt; 2</span>
+M.detect(collection, complex_table) <span class="comment">-- =&gt; 2</span>
</pre>
<p>Handles iterator functions.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> isUpper(v)
<span class="keyword">return</span> v:upper()==v
<span class="keyword">end</span>
-_.detect({<span class="string">'a'</span>,<span class="string">'B'</span>,<span class="string">'c'</span>},isUpper) <span class="comment">-- =&gt; 2</span>
+M.detect({<span class="string">'a'</span>,<span class="string">'B'</span>,<span class="string">'c'</span>},isUpper) <span class="comment">-- =&gt; 2</span>
</pre>
@@ -443,168 +475,152 @@ _.detect({<span class="string">'a'</span>,<span class="string">'B'</span>,<span
<p>Looks through a table and returns all the values that matches all of the key-value pairs listed in <code>props</code>. </p>
-<pre>
-<span class="keyword">local</span> tA = {a = <span class="number">1</span>, b = <span class="number">2</span>, c = <span class="number">0</span>}
-<span class="keyword">local</span> tB = {a = <span class="number">1</span>, b = <span class="number">4</span>, c = <span class="number">1</span>}
-<span class="keyword">local</span> tC = {a = <span class="number">4</span>, b = <span class="number">4</span>, c = <span class="number">3</span>}
-<span class="keyword">local</span> tD = {a = <span class="number">1</span>, b = <span class="number">2</span>, c = <span class="number">3</span>}
-<span class="keyword">local</span> found = _.where({tA, tB, tC, tD}, {a = <span class="number">1</span>})
-<span class="comment">-- =&gt; found = {tA, tB, tD}
-</span>
-found = _.where({tA, tB, tC, tD}, {b = <span class="number">4</span>})
-
-<span class="comment">-- =&gt; found = {tB, tC}
-</span>
-found = _.where({tA, tB, tC, tD}, {b = <span class="number">4</span>, c = <span class="number">3</span>})
-
-<span class="comment">-- =&gt; found = {tC}</span>
+<pre>
+<span class="keyword">local</span> items = {
+ {height = <span class="number">10</span>, weight = <span class="number">8</span>, price = <span class="number">500</span>},
+ {height = <span class="number">10</span>, weight = <span class="number">15</span>, price = <span class="number">700</span>},
+ {height = <span class="number">15</span>, weight = <span class="number">15</span>, price = <span class="number">3000</span>},
+ {height = <span class="number">10</span>, weight = <span class="number">8</span>, price = <span class="number">3000</span>},
+}
+M.where(items, {height = <span class="number">10</span>}) <span class="comment">-- =&gt; {items[1], items[2], items[4]}
+</span>M.where(items, {weight = <span class="number">15</span>}) <span class="comment">-- =&gt; {items[2], items[3]}
+</span>M.where(items, {prince = <span class="number">3000</span>}) <span class="comment">-- =&gt; {items[3], items[4]}
+</span>M.where(items, {height = <span class="number">10</span>, weight = <span class="number">15</span>, prince = <span class="number">700</span>}) <span class="comment">-- =&gt; {items[2]}</span>
</pre>
<h3>findWhere (t, props)</h3>
-<p>Looks through a table and returns the first value that matches all of the key-value pairs listed in <code>props</code>. </p>
+<p>Looks through a table and returns the first value found that matches all of the key-value pairs listed in <code>props</code>. </p>
+
<pre>
<span class="keyword">local</span> a = {a = <span class="number">1</span>, b = <span class="number">2</span>, c = <span class="number">3</span>}
<span class="keyword">local</span> b = {a = <span class="number">2</span>, b = <span class="number">3</span>, d = <span class="number">4</span>}
<span class="keyword">local</span> c = {a = <span class="number">3</span>, b = <span class="number">4</span>, e = <span class="number">5</span>}
-_.findWhere({a, b, c}, {a = <span class="number">3</span>, b = <span class="number">4</span>}) == c <span class="comment">-- =&gt; true</span>
+M.findWhere({a, b, c}, {a = <span class="number">3</span>, b = <span class="number">4</span>}) == c <span class="comment">-- =&gt; true</span>
</pre>
-<h3>select (t, f, &hellip;)</h3>
-
-<p><em>Aliases: <code>_.filter</code></em>.</p>
+<h3>select (t, f [, ...])</h3>
+<p>*Aliases: <code>filter</code>*.</p>
<p>Collects values passing a validation test.</p>
+
<pre>
-<span class="comment">-- Even values
-</span>_.<span class="global">select</span>({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, <span class="keyword">function</span>(key,value)
- <span class="keyword">return</span> (value%<span class="number">2</span>==<span class="number">0</span>)
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{2,4,6}"
-</span>
-<span class="comment">-- Odd values
-</span>_.<span class="global">select</span>({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, <span class="keyword">function</span>(key,value)
- <span class="keyword">return</span> (value%<span class="number">2</span>~=<span class="number">0</span>)
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{1,3,5,7}"</span>
+<span class="keyword">local</span> <span class="keyword">function</span> isEven(v) <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">end</span>
+<span class="keyword">local</span> <span class="keyword">function</span> isOdd(v) <span class="keyword">return</span> v%<span class="number">2</span>~=<span class="number">0</span> <span class="keyword">end</span>
+
+M.<span class="global">select</span>({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, isEven) <span class="comment">-- =&gt; "{2,4,6}"
+</span>M.<span class="global">select</span>({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, isOdd) <span class="comment">-- =&gt; "{1,3,5,7}"</span>
</pre>
-<h3>reject (t, f, &hellip;)</h3>
+<h3>reject (t, f [, ...])</h3>
+<p>*Aliases: <a href="index.html#reject">reject</a>*.</p>
-<p><em>Aliases: <code>_.reject</code></em>.</p>
+<p>Removes all values failing (returning false or nil) a validation test:</p>
-<p>Removes all values failing a validation test:</p>
<pre>
-_.reject({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, <span class="keyword">function</span>(key,value)
- <span class="keyword">return</span> (value%<span class="number">2</span>==<span class="number">0</span>)
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{1,3,5,7}"
-</span>
-_.reject({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, <span class="keyword">function</span>(key,value)
- <span class="keyword">return</span> (value%<span class="number">2</span>~=<span class="number">0</span>)
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{2,4,6}"</span>
-</pre>
+<span class="keyword">local</span> <span class="keyword">function</span> isEven(v) <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">end</span>
+<span class="keyword">local</span> <span class="keyword">function</span> isOdd(v) <span class="keyword">return</span> v%<span class="number">2</span>~=<span class="number">0</span> <span class="keyword">end</span>
+M.reject({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, isEven) <span class="comment">-- =&gt; "{1,3,5,7}"
+</span>M.reject({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}, isOdd) <span class="comment">-- =&gt; "{2,4,6}"</span>
+</pre>
-<h3>all (t, f, &hellip;)</h3>
-<p><em>Aliases: <code>_.every</code></em>.</p>
+<h3>all (t, f [, ...])</h3>
+<p>*Aliases: <code>every</code>*.</p>
<p>Checks whether or not all elements pass a validation test.</p>
+
<pre>
-_.all({<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>}, <span class="keyword">function</span>(key,value)
- <span class="keyword">return</span> (value%<span class="number">2</span>==<span class="number">0</span>)
-<span class="keyword">end</span>) <span class="comment">-- =&gt; true</span>
+<span class="keyword">local</span> <span class="keyword">function</span> isEven(v) <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">end</span>
+M.all({<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>}, isEven) <span class="comment">-- =&gt; true</span>
</pre>
-<h3>invoke (t, method, &hellip;)</h3>
+<h3>invoke (t, method [, ...])</h3>
+
+<p>Invokes a given function on each value in a table.</p>
-<p>Invokes a given function on each value in a table</p>
<pre>
-_.invoke({<span class="string">'a'</span>,<span class="string">'bea'</span>,<span class="string">'cdhza'</span>},<span class="global">string</span>.len) <span class="comment">-- =&gt; "{1,3,5}"</span>
+M.invoke({<span class="string">'a'</span>,<span class="string">'bea'</span>,<span class="string">'cdhza'</span>},<span class="global">string</span>.len) <span class="comment">-- =&gt; "{1,3,5}"</span>
</pre>
<p>Can reference the method of the same name in each value.</p>
-<pre>
-<span class="keyword">local</span> a = {}
-<span class="keyword">function</span> a:call() <span class="keyword">return</span> <span class="string">'a'</span> <span class="keyword">end</span>
-<span class="keyword">local</span> b, c, d = {}, {}, {}
-b.call, c.call, d.call = a.call, a.call, a.call
-_.invoke({a,b,c,d},<span class="string">'call'</span>) <span class="comment">-- =&gt; "{'a','a','a','a'}"</span>
+<pre>
+<span class="keyword">local</span> a, b, c, d = {id = <span class="string">'a'</span>}, {id = <span class="string">'b'</span>}, {id = <span class="string">'c'</span>}, {id = <span class="string">'d'</span>}
+<span class="keyword">local</span> <span class="keyword">function</span> call(self) <span class="keyword">return</span> self.id <span class="keyword">end</span>
+M.invoke({a,b,c,d},call) <span class="comment">-- =&gt; "{'a','b','c','d'}"</span>
</pre>
<h3>pluck (t, property)</h3>
-<p>Fetches all values indxed with specific key in a table of objects.</p>
+<p>Fetches all values indexed with specific key in a table of objects.</p>
+
<pre>
<span class="keyword">local</span> peoples = {
{name = <span class="string">'John'</span>, age = <span class="number">23</span>},{name = <span class="string">'Peter'</span>, age = <span class="number">17</span>},
{name = <span class="string">'Steve'</span>, age = <span class="number">15</span>},{age = <span class="number">33</span>}}
-_.pluck(peoples,<span class="string">'age'</span>) <span class="comment">-- =&gt; "{23,17,15,33}"
-</span>_.pluck(peoples,<span class="string">'name'</span>) <span class="comment">-- =&gt; "{'John', 'Peter', 'Steve'}"</span>
+M.pluck(peoples,<span class="string">'age'</span>) <span class="comment">-- =&gt; "{23,17,15,33}"
+</span>M.pluck(peoples,<span class="string">'name'</span>) <span class="comment">-- =&gt; "{'John', 'Peter', 'Steve'}"</span>
</pre>
-<h3>max (t, transform, &hellip;)</h3>
+<h3>max (t [, transform [, ...]])</h3>
<p>Returns the maximum value in a collection.</p>
+
<pre>
-_.max {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">-- =&gt; 3
-</span>_.max {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>} <span class="comment">-- =&gt; 'c'</span>
+M.max {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">-- =&gt; 3
+</span>M.max {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>} <span class="comment">-- =&gt; 'c'</span>
</pre>
<p>Can take an iterator function to extract a specific property.</p>
+
<pre>
<span class="keyword">local</span> peoples = {
{name = <span class="string">'John'</span>, age = <span class="number">23</span>},{name = <span class="string">'Peter'</span>, age = <span class="number">17</span>},
{name = <span class="string">'Steve'</span>, age = <span class="number">15</span>},{age = <span class="number">33</span>}}
-_.max(peoples,<span class="keyword">function</span>(people) <span class="keyword">return</span> people.age <span class="keyword">end</span>) <span class="comment">-- =&gt; 33</span>
+M.max(peoples,<span class="keyword">function</span>(people) <span class="keyword">return</span> people.age <span class="keyword">end</span>) <span class="comment">-- =&gt; 33</span>
</pre>
-<h3>min (t, transform, &hellip;)</h3>
+<h3>min (t [, transform [, ...]])</h3>
<p>Returns the minimum value in a collection.</p>
+
<pre>
-_.min {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">-- =&gt; 1
-</span>_.min {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>} <span class="comment">-- =&gt; 'a'</span>
+M.min {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">-- =&gt; 1
+</span>M.min {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>} <span class="comment">-- =&gt; 'a'</span>
</pre>
<p>Can take an iterator function to extract a specific property.</p>
+
<pre>
<span class="keyword">local</span> peoples = {
{name = <span class="string">'John'</span>, age = <span class="number">23</span>},{name = <span class="string">'Peter'</span>, age = <span class="number">17</span>},
{name = <span class="string">'Steve'</span>, age = <span class="number">15</span>},{age = <span class="number">33</span>}}
-_.min(peoples,<span class="keyword">function</span>(people) <span class="keyword">return</span> people.age <span class="keyword">end</span>) <span class="comment">-- =&gt; 15</span>
-</pre>
-
-
-<h3>shuffle (t, seed)</h3>
-
-<p>Shuffles a collection.</p>
-
-<pre>
-<span class="keyword">local</span> list = _.shuffle {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>} <span class="comment">-- =&gt; "{3,2,6,4,1,5}"
-</span>_.each(list,<span class="global">print</span>)
+M.min(peoples,<span class="keyword">function</span>(people) <span class="keyword">return</span> people.age <span class="keyword">end</span>) <span class="comment">-- =&gt; 15</span>
</pre>
@@ -612,40 +628,44 @@ _.min(peoples,<span class="keyword">function</span>(people) <span class="keyword
<p>Tests whether or not all values in each of the passed-in tables exists in both tables.</p>
+
<pre>
<span class="keyword">local</span> a = {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>}
<span class="keyword">local</span> b = {<span class="string">'b'</span>,<span class="string">'a'</span>,<span class="string">'d'</span>,<span class="string">'c'</span>}
-_.same(a,b) <span class="comment">-- =&gt; true
+M.same(a,b) <span class="comment">-- =&gt; true
</span>
b[#b+<span class="number">1</span>] = <span class="string">'e'</span>
-_.same(a,b) <span class="comment">-- =&gt; false</span>
+M.same(a,b) <span class="comment">-- =&gt; false</span>
</pre>
-<h3>sort (t, comp)</h3>
+<h3>sort (t [, comp = math.min])</h3>
<p>Sorts a collection.</p>
+
<pre>
-_.sort({<span class="string">'b'</span>,<span class="string">'a'</span>,<span class="string">'d'</span>,<span class="string">'c'</span>}) <span class="comment">-- =&gt; "{'a','b','c','d'}"</span>
+M.sort({<span class="string">'b'</span>,<span class="string">'a'</span>,<span class="string">'d'</span>,<span class="string">'c'</span>}) <span class="comment">-- =&gt; "{'a','b','c','d'}"</span>
</pre>
<p>Handles custom comparison functions.</p>
+
<pre>
-_.sort({<span class="string">'b'</span>,<span class="string">'a'</span>,<span class="string">'d'</span>,<span class="string">'c'</span>}, <span class="keyword">function</span>(a,b)
+M.sort({<span class="string">'b'</span>,<span class="string">'a'</span>,<span class="string">'d'</span>,<span class="string">'c'</span>}, <span class="keyword">function</span>(a,b)
<span class="keyword">return</span> a:byte() &gt; b:byte()
<span class="keyword">end</span>) <span class="comment">-- =&gt; "{'d','c','b','a'}"</span>
</pre>
-<h3>sortBy (t, transform, comp)</h3>
+<h3>sortBy (t [, transform [, comp = math.min]])</h3>
<p>Sorts items in a collection based on the result of running a transform function through every item in the collection.</p>
+
<pre>
-<span class="keyword">local</span> r = _.sortBy({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}, <span class="global">math</span>.sin)
+<span class="keyword">local</span> r = M.sortBy({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}, <span class="global">math</span>.sin)
<span class="global">print</span>(<span class="global">table</span>.concat(r,<span class="string">','</span>))
<span class="comment">-- =&gt; {5,4,3,1,2}</span>
@@ -654,15 +674,16 @@ _.sort({<span class="string">'b'</span>,<span class="string">'a'</span>,<span cl
<p>The transform function can also be a string name property.</p>
+
<pre>
-<span class="keyword">local</span> people ={
+<span class="keyword">local</span> people = {
{name = <span class="string">'albert'</span>, age = <span class="number">40</span>},
{name = <span class="string">'louis'</span>, age = <span class="number">55</span>},
{name = <span class="string">'steve'</span>, age = <span class="number">35</span>},
{name = <span class="string">'henry'</span>, age = <span class="number">19</span>},
}
-<span class="keyword">local</span> r = _.sortBy(people, <span class="string">'age'</span>)
-_.each(r, <span class="keyword">function</span>(__,v) <span class="global">print</span>(v.age, v.name) <span class="keyword">end</span>)
+<span class="keyword">local</span> r = M.sortBy(people, <span class="string">'age'</span>)
+M.each(r, <span class="keyword">function</span>(v) <span class="global">print</span>(v.age, v.name) <span class="keyword">end</span>)
<span class="comment">-- =&gt; 19 henry
</span><span class="comment">-- =&gt; 35 steve
@@ -671,18 +692,18 @@ _.each(r, <span class="keyword">function</span>(__,v) <span class="global">print
</pre>
-<p>As seen above, the defaut comparison function is the &lsquo;&lt;&rsquo; operator. For example, let us supply a different one to sort
-the list of people by decreasing age order :</p>
+<p>As seen above, the defaut comparison function is the '&lt;' operator. For example, let us supply a different one to sort the list of people by decreasing age order :</p>
+
<pre>
-<span class="keyword">local</span> people ={
+<span class="keyword">local</span> people = {
{name = <span class="string">'albert'</span>, age = <span class="number">40</span>},
{name = <span class="string">'louis'</span>, age = <span class="number">55</span>},
{name = <span class="string">'steve'</span>, age = <span class="number">35</span>},
{name = <span class="string">'henry'</span>, age = <span class="number">19</span>},
}
-<span class="keyword">local</span> r = _.sortBy(people, <span class="string">'age'</span>, <span class="keyword">function</span>(a,b) <span class="keyword">return</span> a &gt; b <span class="keyword">end</span>)
-_.each(r, <span class="keyword">function</span>(__,v) <span class="global">print</span>(v.age, v.name) <span class="keyword">end</span>)
+<span class="keyword">local</span> r = M.sortBy(people, <span class="string">'age'</span>, <span class="keyword">function</span>(a,b) <span class="keyword">return</span> a &gt; b <span class="keyword">end</span>)
+M.each(r, <span class="keyword">function</span>(v) <span class="global">print</span>(v.age, v.name) <span class="keyword">end</span>)
<span class="comment">-- =&gt; 55 louis
</span><span class="comment">-- =&gt; 40 albert
@@ -691,57 +712,62 @@ _.each(r, <span class="keyword">function</span>(__,v) <span class="global">print
</pre>
-<p>The <code>transform</code> function defaults to <code>_.indentity</code> and in that case, <code>_.sortBy</code> behaves like <code>_.sort</code>.</p>
+<p>The <code>transform</code> function defaults to <code>M.indentity</code> and in that case, <code>M.sortBy</code> behaves like <code>M.sort</code>.</p>
+
<pre>
-<span class="keyword">local</span> r = _.sortBy({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>})
+<span class="keyword">local</span> r = M.sortBy({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>})
<span class="global">print</span>(<span class="global">table</span>.concat(r,<span class="string">','</span>))
<span class="comment">-- =&gt; {1,2,3,4,5}</span>
</pre>
-<h3>groupBy (t, iter, &hellip;)</h3>
+<h3>groupBy (t, iter [, ...])</h3>
<p>Groups values in a collection depending on their return value when passed to a predicate test.</p>
+
<pre>
-_.groupBy({<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},<span class="keyword">function</span>(i,value)
- <span class="keyword">return</span> value%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">and</span> <span class="string">'even'</span> <span class="keyword">or</span> <span class="string">'odd'</span>
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{odd = {1,3,5}, even = {0,2,4,6}}"
+M.groupBy({<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},<span class="keyword">function</span>(v)
+ <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">and</span> <span class="string">'even'</span> <span class="keyword">or</span> <span class="string">'odd'</span>
+<span class="keyword">end</span>)
+<span class="comment">-- =&gt; "{odd = {1,3,5}, even = {0,2,4,6}}"
</span>
-_.groupBy({<span class="number">0</span>,<span class="string">'a'</span>,<span class="keyword">true</span>, <span class="keyword">false</span>,<span class="keyword">nil</span>,b,<span class="number">0.5</span>},<span class="keyword">function</span>(i,value)
- <span class="keyword">return</span> <span class="global">type</span>(value)
-<span class="keyword">end</span>) <span class="comment">-- =&gt; "{number = {0,0.5}, string = {'a'}, boolean = {true, false}}" </span>
+M.groupBy({<span class="number">0</span>,<span class="string">'a'</span>,<span class="keyword">true</span>, <span class="keyword">false</span>,<span class="keyword">nil</span>,b,<span class="number">0.5</span>},<span class="global">type</span>)
+<span class="comment">-- =&gt; "{number = {0,0.5}, string = {'a'}, boolean = {true, false}}" </span>
</pre>
-<h3>countBy (t, iter, &hellip;)</h3>
+<h3>countBy (t [, iter [, ...]])</h3>
<p>Splits a table in subsets and provide the count for each subset.</p>
+
<pre>
-_.countBy({<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},<span class="keyword">function</span>(i,value)
- <span class="keyword">return</span> value%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">and</span> <span class="string">'even'</span> <span class="keyword">or</span> <span class="string">'odd'</span>
+M.countBy({<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},<span class="keyword">function</span>(v)
+ <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">and</span> <span class="string">'even'</span> <span class="keyword">or</span> <span class="string">'odd'</span>
<span class="keyword">end</span>) <span class="comment">-- =&gt; "{odd = 3, even = 4}"</span>
</pre>
-<h3>size (&hellip;)</h3>
+<h3>size (...)</h3>
<p>When given a table, provides the count for the very number of values in that table.</p>
+
<pre>
-_.size {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">-- =&gt; 3
-</span>_.size {one = <span class="number">1</span>, two = <span class="number">2</span>} <span class="comment">-- =&gt; 2</span>
+M.size {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">-- =&gt; 3
+</span>M.size {one = <span class="number">1</span>, two = <span class="number">2</span>} <span class="comment">-- =&gt; 2</span>
</pre>
-<p>When given a vararg list of argument, returns the count of these arguments.</p>
+<p>When given a vararg list of arguments, returns the count of these arguments.</p>
+
<pre>
-_.size(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>) <span class="comment">-- =&gt; 3
-</span>_.size(<span class="string">'a'</span>,<span class="string">'b'</span>,{}, <span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; 4</span>
+M.size(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>) <span class="comment">-- =&gt; 3
+</span>M.size(<span class="string">'a'</span>,<span class="string">'b'</span>,{}, <span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; 4</span>
</pre>
@@ -749,10 +775,11 @@ _.size(<span class="number">1</span>,<span class="number">2</span>,<span class="
<p>Checks whether a table has all the keys existing in another table.</p>
+
<pre>
-_.contains({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; true
-</span>_.contains({<span class="number">1</span>,<span class="number">2</span>,<span class="string">'d'</span>,<span class="string">'b'</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; true
-</span>_.contains({x = <span class="number">1</span>, y = <span class="number">2</span>, z = <span class="number">3</span>},{x = <span class="number">1</span>, y = <span class="number">2</span>}) <span class="comment">-- =&gt; true</span>
+M.contains({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; true
+</span>M.contains({<span class="number">1</span>,<span class="number">2</span>,<span class="string">'d'</span>,<span class="string">'b'</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; true
+</span>M.contains({x = <span class="number">1</span>, y = <span class="number">2</span>, z = <span class="number">3</span>},{x = <span class="number">1</span>, y = <span class="number">2</span>}) <span class="comment">-- =&gt; true</span>
</pre>
@@ -760,26 +787,27 @@ _.contains({<span class="number">1</span>,<span class="number">2</span>,<span cl
<p>Checks whether both tables features the same keys:</p>
+
<pre>
-_.sameKeys({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; false
-</span>_.sameKeys({<span class="number">1</span>,<span class="number">2</span>,<span class="string">'d'</span>,<span class="string">'b'</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; true
-</span>_.sameKeys({x = <span class="number">1</span>, y = <span class="number">2</span>, z = <span class="number">3</span>},{x = <span class="number">1</span>, y = <span class="number">2</span>}) <span class="comment">-- =&gt; false</span>
+M.sameKeys({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; false
+</span>M.sameKeys({<span class="number">1</span>,<span class="number">2</span>,<span class="string">'d'</span>,<span class="string">'b'</span>},{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; true
+</span>M.sameKeys({x = <span class="number">1</span>, y = <span class="number">2</span>, z = <span class="number">3</span>},{x = <span class="number">1</span>, y = <span class="number">2</span>}) <span class="comment">-- =&gt; false</span>
</pre>
<p><strong><a href="#TOC">[⬆]</a></strong></p>
<p><a name="_a_name__array__Array_functions__a_"></a></p>
-
<h2><a name='array'>Array functions</a></h2>
-<h3>sample (array, n, seed)</h3>
+<h3>sample (array [, n = 1 [, seed]])</h3>
<p>Samples <code>n</code> values from array.</p>
+
<pre>
-<span class="keyword">local</span> array = _.range(<span class="number">1</span>,<span class="number">20</span>)
-<span class="keyword">local</span> sample = _.sample(array, <span class="number">3</span>)
+<span class="keyword">local</span> array = M.range(<span class="number">1</span>,<span class="number">20</span>)
+<span class="keyword">local</span> sample = M.sample(array, <span class="number">3</span>)
<span class="global">print</span>(<span class="global">table</span>.concat(sample,<span class="string">','</span>))
<span class="comment">-- =&gt; {12,11,15}</span>
@@ -788,9 +816,10 @@ _.sameKeys({<span class="number">1</span>,<span class="number">2</span>,<span cl
<p><code>n</code> defaults to 1. In that case, a single value will be returned.</p>
+
<pre>
-<span class="keyword">local</span> array = _.range(<span class="number">1</span>,<span class="number">20</span>)
-<span class="keyword">local</span> sample = _.sample(array)
+<span class="keyword">local</span> array = M.range(<span class="number">1</span>,<span class="number">20</span>)
+<span class="keyword">local</span> sample = M.sample(array)
<span class="global">print</span>(sample)
<span class="comment">-- =&gt; 12</span>
@@ -799,48 +828,64 @@ _.sameKeys({<span class="number">1</span>,<span class="number">2</span>,<span cl
<p>An optional 3rd argument <code>seed</code> can be passed for deterministic random sampling.</p>
-<h3>sampleProb (array, prob, seed)</h3>
+<h3>sampleProb (array, prob [, seed])</h3>
<p>Returns an array of values randomly selected from a given array.
In case <code>seed</code> is provided, it is used for deterministic sampling.</p>
+
<pre>
-<span class="keyword">local</span> array = _.range(<span class="number">1</span>,<span class="number">20</span>)
-<span class="keyword">local</span> sample = _.sampleProb(array, <span class="number">0.2</span>)
+<span class="keyword">local</span> array = M.range(<span class="number">1</span>,<span class="number">20</span>)
+<span class="keyword">local</span> sample = M.sampleProb(array, <span class="number">0.2</span>)
<span class="global">print</span>(<span class="global">table</span>.concat(sample,<span class="string">','</span>))
<span class="comment">-- =&gt; 5,11,12,15
</span>
-sample = _.sampleProb(array, <span class="number">0.2</span>, <span class="global">os</span>.time())
+sample = M.sampleProb(array, <span class="number">0.2</span>, <span class="global">os</span>.time())
<span class="global">print</span>(<span class="global">table</span>.concat(sample,<span class="string">','</span>))
<span class="comment">-- =&gt; 1,6,10,12,15,20 (or similar)</span>
</pre>
-<h3>toArray (&hellip;)</h3>
+<h3>shuffle (array [, seed])</h3>
+
+<p>Shuffles a given array.</p>
+
+
+<pre>
+<span class="keyword">local</span> list = M.shuffle {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>} <span class="comment">-- =&gt; "{3,2,6,4,1,5}"
+</span>M.each(list,<span class="global">print</span>)
+</pre>
+
+
+<h3>toArray (...)</h3>
<p>Converts a vararg list of arguments to an array.</p>
+
<pre>
-_.toArray(<span class="number">1</span>,<span class="number">2</span>,<span class="number">8</span>,<span class="string">'d'</span>,<span class="string">'a'</span>,<span class="number">0</span>) <span class="comment">-- =&gt; "{1,2,8,'d','a',0}"</span>
+M.toArray(<span class="number">1</span>,<span class="number">2</span>,<span class="number">8</span>,<span class="string">'d'</span>,<span class="string">'a'</span>,<span class="number">0</span>) <span class="comment">-- =&gt; "{1,2,8,'d','a',0}"</span>
</pre>
-<h3>find (array, value, from)</h3>
+<h3>find (array, value [, from = 1])</h3>
<p>Looks for a value in a given array and returns the position of the first occurence.</p>
+
<pre>
-_.find({{<span class="number">4</span>},{<span class="number">3</span>},{<span class="number">2</span>},{<span class="number">1</span>}},{<span class="number">3</span>}) <span class="comment">-- =&gt; 2</span>
+<span class="keyword">local</span> value = {<span class="number">3</span>}
+M.find({{<span class="number">4</span>},{<span class="number">3</span>},{<span class="number">2</span>},{<span class="number">1</span>}},value) <span class="comment">-- =&gt; 2</span>
</pre>
<p>It can also start the search at a specific position in the array:</p>
+
<pre>
<span class="comment">-- search value 4 starting from index 3
-</span>_.find({<span class="number">1</span>,<span class="number">4</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>},<span class="number">4</span>,<span class="number">3</span>) <span class="comment">-- =&gt; 5</span>
+</span>M.find({<span class="number">1</span>,<span class="number">4</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>},<span class="number">4</span>,<span class="number">3</span>) <span class="comment">-- =&gt; 5</span>
</pre>
@@ -848,85 +893,122 @@ _.find({{<span class="number">4</span>},{<span class="number">3</span>},{<span c
<p>Reverses an array.</p>
+
<pre>
-_.reverse({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="string">'d'</span>}) <span class="comment">-- =&gt; "{'d',3,2,1}"</span>
+M.reverse({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="string">'d'</span>}) <span class="comment">-- =&gt; "{'d',3,2,1}"</span>
</pre>
-<h3>fill (array, value, i, j)</h3>
+<h3>fill (array, value [, i = 1 [, j = #array]])</h3>
<p>Replaces all elements in a given array with a given value.</p>
+
<pre>
-<span class="keyword">local</span> array = _.range(<span class="number">1</span>,<span class="number">5</span>)
-_.fill(array, <span class="number">0</span>) <span class="comment">-- =&gt; {0,0,0,0,0}</span>
+<span class="keyword">local</span> array = M.range(<span class="number">1</span>,<span class="number">5</span>)
+M.fill(array, <span class="number">0</span>) <span class="comment">-- =&gt; {0,0,0,0,0}</span>
</pre>
<p>It can start replacing value at a specific index.</p>
+
<pre>
-<span class="keyword">local</span> array = _.range(<span class="number">1</span>,<span class="number">5</span>)
-_.fill(array,<span class="number">0</span>,<span class="number">3</span>) <span class="comment">-- =&gt; {1,2,0,0,0}</span>
+<span class="keyword">local</span> array = M.range(<span class="number">1</span>,<span class="number">5</span>)
+M.fill(array,<span class="number">0</span>,<span class="number">3</span>) <span class="comment">-- =&gt; {1,2,0,0,0}</span>
</pre>
<p>It can replace only values within a specific range.</p>
+
<pre>
-<span class="keyword">local</span> array = _.range(<span class="number">1</span>,<span class="number">5</span>)
-_.fill(array,<span class="number">0</span>,<span class="number">2</span>,<span class="number">4</span>) <span class="comment">-- =&gt; {1,0,0,0,5}</span>
+<span class="keyword">local</span> array = M.range(<span class="number">1</span>,<span class="number">5</span>)
+M.fill(array,<span class="number">0</span>,<span class="number">2</span>,<span class="number">4</span>) <span class="comment">-- =&gt; {1,0,0,0,5}</span>
</pre>
<p>In case the upper bound index i greather than the array size, it will enlarge the array.</p>
+
<pre>
-<span class="keyword">local</span> array = _.range(<span class="number">1</span>,<span class="number">5</span>)
-_.fill(array,<span class="number">0</span>,<span class="number">5</span>,<span class="number">10</span>) <span class="comment">-- =&gt; {1,2,3,4,0,0,0,0,0,0}</span>
+<span class="keyword">local</span> array = M.range(<span class="number">1</span>,<span class="number">5</span>)
+M.fill(array,<span class="number">0</span>,<span class="number">5</span>,<span class="number">10</span>) <span class="comment">-- =&gt; {1,2,3,4,0,0,0,0,0,0}</span>
</pre>
-<h3>selectWhile (array, f, &hellip;</h3>
+<h3>zeros (n)</h3>
+
+<p>Returns an array of <code>n</code> zeros.</p>
-<p><em>Aliases: <code>_.takeWhile</code></em>.</p>
+
+<pre>
+M.zeros(<span class="number">4</span>) <span class="comment">-- =&gt; {0,0,0,0}</span>
+</pre>
+
+
+<h3>ones (n)</h3>
+
+<p>Returns an array of <code>n</code> 1's.</p>
+
+
+<pre>
+M.ones(<span class="number">3</span>) <span class="comment">-- =&gt; {1,1,1}</span>
+</pre>
+
+
+<h3>vector (value, n)</h3>
+
+<p>Returns an array of <code>n</code> times a given value.</p>
+
+
+<pre>
+M.vector(<span class="number">10</span>, <span class="number">4</span>) <span class="comment">-- =&gt; {10,10,10,10}</span>
+</pre>
+
+
+<h3>selectWhile (array, f [, ...])</h3>
+<p>*Aliases: <code>takeWhile</code>*.</p>
<p>Collects values as long as they pass a given test. Stops on the first non-passing test.</p>
+
<pre>
-_.selectWhile({<span class="number">2</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">8</span>}, <span class="keyword">function</span>(i,v)
+M.selectWhile({<span class="number">2</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">8</span>}, <span class="keyword">function</span>(v)
<span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span>
<span class="keyword">end</span>) <span class="comment">-- =&gt; "{2,4}"</span>
</pre>
-<h3>dropWhile (array, f, &hellip;</h3>
-
-<p><em>Aliases: <code>_.rejectWhile</code></em>.</p>
+<h3>dropWhile (array, f [, ...])</h3>
+<p>*Aliases: <code>rejectWhile</code>*.</p>
<p>Removes values as long as they pass a given test. Stops on the first non-passing test.</p>
+
<pre>
-_.dropWhile({<span class="number">2</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">8</span>}, <span class="keyword">function</span>(i,v)
+M.dropWhile({<span class="number">2</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">8</span>}, <span class="keyword">function</span>(v)
<span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span>
<span class="keyword">end</span>) <span class="comment">-- =&gt; "{5,8}"</span>
</pre>
-<h3>sortedIndex (array, value, comp, sort)</h3>
+<h3>sortedIndex (array, value [, comp = math.min [, sort = nil]])</h3>
<p>Returns the index at which a value should be inserted to preserve order.</p>
+
<pre>
-_.sortedIndex({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="number">4</span>) <span class="comment">-- =&gt; 4</span>
+M.sortedIndex({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="number">4</span>) <span class="comment">-- =&gt; 4</span>
</pre>
<p>Can take a custom comparison functions.</p>
+
<pre>
<span class="keyword">local</span> comp = <span class="keyword">function</span>(a,b) <span class="keyword">return</span> a&lt;b <span class="keyword">end</span>
-_.sortedIndex({-<span class="number">5</span>,<span class="number">0</span>,<span class="number">4</span>,<span class="number">4</span>},<span class="number">3</span>,comp) <span class="comment">-- =&gt; 3</span>
+M.sortedIndex({-<span class="number">5</span>,<span class="number">0</span>,<span class="number">4</span>,<span class="number">4</span>},<span class="number">3</span>,comp) <span class="comment">-- =&gt; 3</span>
</pre>
@@ -934,8 +1016,9 @@ _.sortedIndex({-<span class="number">5</span>,<span class="number">0</span>,<spa
<p>Returns the index of a value in an array.</p>
+
<pre>
-_.indexOf({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="number">2</span>) <span class="comment">-- =&gt; 2</span>
+M.indexOf({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="number">2</span>) <span class="comment">-- =&gt; 2</span>
</pre>
@@ -943,164 +1026,190 @@ _.indexOf({<span class="number">1</span>,<span class="number">2</span>,<span cla
<p>Returns the index of the last occurence of a given value in an array.</p>
+
<pre>
-_.lastIndexOf({<span class="number">1</span>,<span class="number">2</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="number">2</span>) <span class="comment">-- =&gt; 3</span>
+M.lastIndexOf({<span class="number">1</span>,<span class="number">2</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="number">2</span>) <span class="comment">-- =&gt; 3</span>
</pre>
-<h3>findIndex (array, predicate, &hellip;)</h3>
+<h3>findIndex (array, predicate [, ...])</h3>
<p>Returns the first index at which a predicate passes a truth test.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}
-<span class="keyword">local</span> <span class="keyword">function</span> multipleOf3(__,v) <span class="keyword">return</span> v%<span class="number">3</span>==<span class="number">0</span> <span class="keyword">end</span>
-_.findIndex(array, multipleOf3) <span class="comment">-- =&gt; 3</span>
+<span class="keyword">local</span> <span class="keyword">function</span> multipleOf3(v) <span class="keyword">return</span> v%<span class="number">3</span>==<span class="number">0</span> <span class="keyword">end</span>
+M.findIndex(array, multipleOf3) <span class="comment">-- =&gt; 3</span>
</pre>
-<h3>findLastIndex (array, predicate, &hellip;)</h3>
+<h3>findLastIndex (array, predicate [, ...])</h3>
+
+<p>Returns the last index at which a predicate passes a truthy test.</p>
-<p>Returns the last index at which a predicate passes a truth test.</p>
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}
-<span class="keyword">local</span> <span class="keyword">function</span> multipleOf3(__,v) <span class="keyword">return</span> v%<span class="number">3</span>==<span class="number">0</span> <span class="keyword">end</span>
-_.findLastIndex(array, multipleOf3) <span class="comment">-- =&gt; 6</span>
+<span class="keyword">local</span> <span class="keyword">function</span> multipleOf3(v) <span class="keyword">return</span> v%<span class="number">3</span>==<span class="number">0</span> <span class="keyword">end</span>
+M.findLastIndex(array, multipleOf3) <span class="comment">-- =&gt; 6</span>
</pre>
-<h3>addTop (array, &hellip;)</h3>
+<h3>addTop (array, ...)</h3>
<p>Adds given values at the top of an array. The latter values bubbles at the top.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>}
-_.addTop(array,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>) <span class="comment">-- =&gt; "{4,3,2,1,1}"</span>
+M.addTop(array,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>) <span class="comment">-- =&gt; "{4,3,2,1,1}"</span>
</pre>
-<h3>push (array, &hellip;)</h3>
+<h3>prepend (array, ...)</h3>
+
+<p>Adds given values at the top of an array, preserving the order at which elements are passed-in.</p>
+
+
+<pre>
+<span class="keyword">local</span> array = {<span class="string">'old_val'</span>}
+M.prepend(array,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>) <span class="comment">-- =&gt; "{1,2,3,4,'old_val'}"</span>
+</pre>
+
+
+<h3>push (array, ...)</h3>
<p>Adds given values at the end of an array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>}
-_.push(array,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>) <span class="comment">-- =&gt; "{1,1,2,3,4}"</span>
+M.push(array,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>) <span class="comment">-- =&gt; "{1,1,2,3,4}"</span>
</pre>
-<h3>pop (array, n)</h3>
-
-<p><em>Aliases: <code>_.shift</code></em>.</p>
+<h3>shift (array [, n = 1])</h3>
+<p>*Aliases: <code>pop</code>*.</p>
<p>Removes and returns the first value in an array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
-<span class="keyword">local</span> pop = _.pop(array) <span class="comment">-- =&gt; "pop = 1", "array = {2,3}"</span>
+<span class="keyword">local</span> shift = M.shift(array) <span class="comment">-- =&gt; "shift = 1", "array = {2,3}"</span>
</pre>
+<p>If <code>n</code> is supplied, returns <code>n</code> values.</p>
-<h3>unshift (array, n)</h3>
+
+<pre>
+<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}
+<span class="keyword">local</span> a, b = M.shift(array, <span class="number">2</span>) <span class="comment">-- =&gt; "a = 1, b = 2", "array = {3,4,5}"</span>
+</pre>
+
+
+<h3>unshift (array [, n = 1])</h3>
<p>Removes and returns the last value in an array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
-<span class="keyword">local</span> value = _.unshift(array) <span class="comment">-- =&gt; "value = 3", "array = {1,2}"</span>
+<span class="keyword">local</span> value = M.unshift(array) <span class="comment">-- =&gt; "value = 3", "array = {1,2}"</span>
</pre>
-<h3>pull (array, &hellip;)</h3>
-
-<p><em>Aliases: <code>_.remove</code></em>.</p>
+<h3>pull (array, ...)</h3>
+<p>*Aliases: <code>remove</code>*.</p>
<p>Removes all provided values from a given array.</p>
+
<pre>
-_.pull({<span class="number">1</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">3</span>},<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>) <span class="comment">-- =&gt; "{4}"</span>
+M.pull({<span class="number">1</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">3</span>},<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>) <span class="comment">-- =&gt; "{4}"</span>
</pre>
-<h3>removeRange (array, start, finish)</h3>
-
-<p><em>Aliases: <code>_.rmRange</code>, <code>_.chop</code></em>.</p>
+<h3>removeRange (array [, start = 1 [, finish = #array]])</h3>
+<p>*Aliases: <code>rmRange</code>, <code>M.chop</code>*.</p>
<p>Trims out all values index within a range.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>}
-_.removeRange(array, <span class="number">3</span>,<span class="number">8</span>) <span class="comment">-- =&gt; "{1,2,9}"</span>
+M.removeRange(array, <span class="number">3</span>,<span class="number">8</span>) <span class="comment">-- =&gt; "{1,2,9}"</span>
</pre>
-<h3>chunk (array, f, &hellip;)</h3>
+<h3>chunk (array, f [, ...])</h3>
+
+<p>Iterates over an array aggregating consecutive values in subsets tables, on the basis of the return value of <code>f(v, k, ...)</code>. Consecutive elements which return the same value are chunked together.</p>
-<p>Iterates over an array aggregating consecutive values in subsets tables, on the basis of the return
-value of <code>f(key,value,&hellip;)</code>. Consecutive elements which return the same value are aggregated together.</p>
<pre>
<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">4</span>}
-_.chunk(t, <span class="keyword">function</span>(k,v) <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">end</span>) <span class="comment">-- =&gt; "{{1,1},{2},{3,3},{4}}"</span>
+M.chunk(t, <span class="keyword">function</span>(v) <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">end</span>) <span class="comment">-- =&gt; "{{1,1},{2},{3,3},{4}}"</span>
</pre>
-<h3>slice (array, start, finish)</h3>
-
-<p><em>Aliases: <code>_.sub</code></em>.</p>
+<h3>slice (array [, start = 1 [, finish = #array]])</h3>
+<p>*Aliases: <a href="index.html#operator.sub">sub</a>*.</p>
<p>Slices and returns a part of an array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>}
-_.slice(array, <span class="number">3</span>,<span class="number">6</span>) <span class="comment">-- =&gt; "{3,4,5,6}"</span>
+M.slice(array, <span class="number">3</span>,<span class="number">6</span>) <span class="comment">-- =&gt; "{3,4,5,6}"</span>
</pre>
-<h3>first (array, n)</h3>
-
-<p><em>Aliases: <code>_.head</code>, <code>_.take</code></em>.</p>
+<h3>first (array [, n = 1])</h3>
+<p>*Aliases: <code>head</code>, <code>M.take</code>*.</p>
<p>Returns the first N elements in an array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>}
-_.first(array,<span class="number">3</span>) <span class="comment">-- =&gt; "{1,2,3}"</span>
+M.first(array,<span class="number">3</span>) <span class="comment">-- =&gt; "{1,2,3}"</span>
</pre>
-<h3>initial (array, n)</h3>
+<h3>initial (array [, n = #array])</h3>
<p>Excludes the last N elements in an array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>}
-_.initial(array,<span class="number">5</span>) <span class="comment">-- =&gt; "{1,2,3,4}"</span>
+M.initial(array,<span class="number">5</span>) <span class="comment">-- =&gt; "{1,2,3,4}"</span>
</pre>
-<h3>last (array, n)</h3>
-
-<p><em>Aliases: <code>_.skip</code></em>.</p>
+<h3>last (array [, n = #array])</h3>
+<p>*Aliases: <code>skip</code>*.</p>
<p>Returns the last N elements in an array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>}
-_.last(array,<span class="number">3</span>) <span class="comment">-- =&gt; "{7,8,9}"</span>
+M.last(array,<span class="number">3</span>) <span class="comment">-- =&gt; "{7,8,9}"</span>
</pre>
-<h3>rest (array, index)</h3>
+<h3>rest (array [, index = 1])</h3>
+<p>*Aliases: <code>tail</code>*.</p>
-<p><em>Aliases: <code>_.tail</code></em>.</p>
+<p>Returns all values after <em>index</em>, including the given <em>index</em> itself.</p>
-<p>Trims out all values indexed before <em>index</em>.</p>
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>}
-_.rest(array,<span class="number">6</span>) <span class="comment">-- =&gt; "{6,7,8,9}"</span>
+M.rest(array,<span class="number">6</span>) <span class="comment">-- =&gt; "{6,7,8,9}"</span>
</pre>
@@ -1108,9 +1217,10 @@ _.rest(array,<span class="number">6</span>) <span class="comment">-- =&gt; "{6,7
<p>Returns the value at <em>index</em>.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}
-_.nth(array,<span class="number">3</span>) <span class="comment">-- =&gt; "3"</span>
+M.nth(array,<span class="number">3</span>) <span class="comment">-- =&gt; "3"</span>
</pre>
@@ -1118,109 +1228,133 @@ _.nth(array,<span class="number">3</span>) <span class="comment">-- =&gt; "3"</s
<p>Trims out all falsy values.</p>
+
<pre>
-_.compact {a,<span class="string">'aa'</span>,<span class="keyword">false</span>,<span class="string">'bb'</span>,<span class="keyword">true</span>} <span class="comment">-- =&gt; "{'aa','bb',true}"</span>
+M.compact {a,<span class="string">'aa'</span>,<span class="keyword">false</span>,<span class="string">'bb'</span>,<span class="keyword">true</span>} <span class="comment">-- =&gt; "{'aa','bb',true}"</span>
</pre>
-<h3>flatten (array, shallow)</h3>
+<h3>flatten (array [, shallow = false])</h3>
<p>Flattens a nested array.</p>
+
<pre>
-_.flatten({<span class="number">1</span>,{<span class="number">2</span>,<span class="number">3</span>},{<span class="number">4</span>,<span class="number">5</span>,{<span class="number">6</span>,<span class="number">7</span>}}}) <span class="comment">-- =&gt; "{1,2,3,4,5,6,7}"</span>
+M.flatten({<span class="number">1</span>,{<span class="number">2</span>,<span class="number">3</span>},{<span class="number">4</span>,<span class="number">5</span>,{<span class="number">6</span>,<span class="number">7</span>}}}) <span class="comment">-- =&gt; "{1,2,3,4,5,6,7}"</span>
</pre>
-<p>When given arg &ldquo;shallow&rdquo;, flatten only at the first level.</p>
+<p>When given arg <code>shallow</code>, flatten only at the first level.</p>
+
<pre>
-_.flatten({<span class="number">1</span>,{<span class="number">2</span>},{{<span class="number">3</span>}}},<span class="keyword">true</span>) <span class="comment">-- =&gt; "{1,{2},{{3}}}"</span>
+M.flatten({<span class="number">1</span>,{<span class="number">2</span>},{{<span class="number">3</span>}}},<span class="keyword">true</span>) <span class="comment">-- =&gt; "{1,{2},{{3}}}"</span>
</pre>
<h3>difference (array, array2)</h3>
-
-<p><em>Aliases: <code>_.without</code>, <code>_.diff</code></em>.</p>
+<p>*Aliases: <code>without</code>, <code>diff</code>*.</p>
<p>Returns values in the given array not present in a second array.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="string">'a'</span>,<span class="number">4</span>,<span class="number">5</span>}
-_.difference(array,{<span class="number">1</span>,<span class="string">'a'</span>}) <span class="comment">-- =&gt; "{2,4,5}"</span>
+M.difference(array,{<span class="number">1</span>,<span class="string">'a'</span>}) <span class="comment">-- =&gt; "{2,4,5}"</span>
</pre>
-<h3>union (&hellip;)</h3>
+<h3>union (...)</h3>
<p>Produces a duplicate-free union of all passed-in arrays.</p>
+
<pre>
<span class="keyword">local</span> A = {<span class="string">'a'</span>}
<span class="keyword">local</span> B = {<span class="string">'a'</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
<span class="keyword">local</span> C = {<span class="number">2</span>,<span class="number">10</span>}
-_.union(A,B,C) <span class="comment">-- =&gt; "{'a',1,2,3,10}"</span>
+M.union(A,B,C) <span class="comment">-- =&gt; "{'a',1,2,3,10}"</span>
</pre>
-<h3>intersection (array, &hellip;)</h3>
+<h3>intersection (array, ...)</h3>
<p>Returns the intersection (common-part) of all passed-in arrays:</p>
+
<pre>
<span class="keyword">local</span> A = {<span class="string">'a'</span>}
<span class="keyword">local</span> B = {<span class="string">'a'</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
<span class="keyword">local</span> C = {<span class="number">2</span>,<span class="number">10</span>,<span class="number">1</span>,<span class="string">'a'</span>}
-_.intersection(A,B,C) <span class="comment">-- =&gt; "{'a',2,1}"</span>
+M.intersection(A,B,C) <span class="comment">-- =&gt; "{'a',2,1}"</span>
</pre>
<h3>symmetricDifference (array, array2)</h3>
-
-<p><em>Aliases: <code>_.symdiff</code>,<code>_.xor</code></em>.</p>
+<p>*Aliases: <code>symdiff</code>,<code>xor</code>*.</p>
<p>Returns values in the first array not present in the second and also values in the second array not present in the first one.</p>
+
<pre>
<span class="keyword">local</span> array = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
<span class="keyword">local</span> array2 = {<span class="number">1</span>,<span class="number">4</span>,<span class="number">5</span>}
-_.symmetricDifference(array, array2) <span class="comment">-- =&gt; "{2,3,4,5}"</span>
+M.symmetricDifference(array, array2) <span class="comment">-- =&gt; "{2,3,4,5}"</span>
</pre>
<h3>unique (array)</h3>
-
-<p><em>Aliases: <code>_.uniq</code></em>.</p>
+<p>*Aliases: <code>uniq</code>*.</p>
<p>Makes an array duplicate-free.</p>
+
<pre>
-_.unique {<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">4</span>,<span class="number">4</span>,<span class="number">5</span>} <span class="comment">-- =&gt; "{1,2,3,4,5}"</span>
+M.unique {<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">4</span>,<span class="number">4</span>,<span class="number">5</span>} <span class="comment">-- =&gt; "{1,2,3,4,5}"</span>
</pre>
<h3>isunique (array)</h3>
-
-<p><em>Aliases: <code>_.isuniq</code></em>.</p>
+<p>*Aliases: <code>isuniq</code>*.</p>
<p>Checks if a given array contains no duplicate value.</p>
+
<pre>
-_.isunique({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; true
-</span>_.isunique({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">4</span>}) <span class="comment">-- =&gt; false</span>
+M.isunique({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; true
+</span>M.isunique({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">4</span>}) <span class="comment">-- =&gt; false</span>
</pre>
-<h3>zip (&hellip;)</h3>
-
-<p><em>Aliases: <code>_.transpose</code></em>.</p>
+<h3>zip (...)</h3>
+<p>*Aliases: <code>transpose</code>*.</p>
<p>Zips values from different arrays, on the basis on their common keys.</p>
+
<pre>
<span class="keyword">local</span> names = {<span class="string">'Bob'</span>,<span class="string">'Alice'</span>,<span class="string">'James'</span>}
<span class="keyword">local</span> ages = {<span class="number">22</span>, <span class="number">23</span>}
-_.zip(names,ages) <span class="comment">-- =&gt; "{{'Bob',22},{'Alice',23},{'James'}}"</span>
+M.zip(names,ages) <span class="comment">-- =&gt; "{{'Bob',22},{'Alice',23},{'James'}}"</span>
+</pre>
+
+
+<h3>zipWith (f, ...)</h3>
+<p>*Aliases: <code>transposeWith</code>*.</p>
+
+<p>Merges values using a given function. Only values indexed with the same key in the given arrays are merged in the same subset.
+Function <code>f</code> is used to combine values.</p>
+
+
+<pre>
+<span class="keyword">local</span> names = {<span class="string">'Bob'</span>,<span class="string">'Alice'</span>,<span class="string">'James'</span>}; <span class="keyword">local</span> ages = {<span class="number">22</span>, <span class="number">23</span>, <span class="number">25</span>}
+<span class="keyword">local</span> <span class="keyword">function</span> introduce(name, age) <span class="keyword">return</span> <span class="string">'I am '</span>..name..<span class="string">' and I am '</span>..age..<span class="string">' years old.'</span> <span class="keyword">end</span>
+<span class="keyword">local</span> t = M.zipWith(introduce,names,ages)
+<span class="comment">-- =&gt; {
+</span><span class="comment">-- =&gt; 'I am Bob and I am 22 years old.'
+</span><span class="comment">-- =&gt; 'I am Alice and I am 23 years old.'
+</span><span class="comment">-- =&gt; 'I am James and I am 25 years old.'
+</span><span class="comment">-- =&gt; }</span>
</pre>
@@ -1228,51 +1362,67 @@ _.zip(names,ages) <span class="comment">-- =&gt; "{{'Bob',22},{'Alice',23},{'Jam
<p>Appends two arrays.</p>
+
<pre>
-_.append({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="string">'a'</span>,<span class="string">'b'</span>}) <span class="comment">-- =&gt; "{1,2,3,'a','b'}"</span>
+M.append({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="string">'a'</span>,<span class="string">'b'</span>}) <span class="comment">-- =&gt; "{1,2,3,'a','b'}"</span>
</pre>
-<h3>interleave (&hellip;)</h3>
+<h3>interleave (...)</h3>
<p>Interleaves values from passed-in arrays.</p>
+
<pre>
t1 = {<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>}
t2 = {<span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>}
-_.interleave(t1, t2) <span class="comment">-- =&gt; "{1,'a',2,'b',3,'c'}"</span>
+M.interleave(t1, t2) <span class="comment">-- =&gt; "{1,'a',2,'b',3,'c'}"</span>
</pre>
-<h3>interpose (value, array)</h3>
+<h3>interpose (array, value)</h3>
+<p>*Aliases: <code>intersperce</code>*.</p>
<p>Interposes a value between consecutive values in an arrays.</p>
+
<pre>
-_.interleave(<span class="string">'a'</span>, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; "{1,'a',2,'a',3}"</span>
+M.interleave(<span class="string">'a'</span>, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; "{1,'a',2,'a',3}"</span>
</pre>
-<h3>range (&hellip;)</h3>
+<h3>range ([from [, to [, step]]])</h3>
<p>Generates an arithmetic sequence.</p>
+
<pre>
-_.range(<span class="number">1</span>,<span class="number">4</span>) <span class="comment">-- =&gt; "{1,2,3,4}"</span>
+M.range(<span class="number">1</span>,<span class="number">4</span>) <span class="comment">-- =&gt; "{1,2,3,4}"</span>
</pre>
-<p>In case a single value is provided, it generates a sequence from 0 to that value.</p>
+<p>In case a single value is provided, it generates a sequence from 1 to that value.</p>
+
<pre>
-_.range(<span class="number">3</span>) <span class="comment">-- =&gt; "{0,1,2,3}"</span>
+M.range(<span class="number">3</span>) <span class="comment">-- =&gt; "{1,2,3}"</span>
</pre>
<p>The incremental step can also be provided as third argument.</p>
+
<pre>
-_.range(<span class="number">0</span>,<span class="number">2</span>,<span class="number">0.7</span>) <span class="comment">-- =&gt; "{0,0.7,1.4}"</span>
+M.range(<span class="number">0</span>,<span class="number">2</span>,<span class="number">0.7</span>) <span class="comment">-- =&gt; "{0,0.7,1.4}"</span>
+</pre>
+
+
+<p>It also handles negative progressions.</p>
+
+
+<pre>
+M.range(-<span class="number">5</span>) <span class="comment">-- =&gt; "{-1,-2,-3,-4,-5}"
+</span>M.range(<span class="number">5</span>,<span class="number">1</span>) <span class="comment">-- =&gt; "{5,4,3,2,1}"</span>
</pre>
@@ -1280,20 +1430,31 @@ _.range(<span class="number">0</span>,<span class="number">2</span>,<span class=
<p>Generates a list of n repetitions of a value.</p>
+
<pre>
-_.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="comment">-- =&gt; "{4,4,4}"</span>
+M.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="comment">-- =&gt; "{4,4,4}"</span>
</pre>
-<h3>partition (array, n, pad)</h3>
+<h3>powerset (array)</h3>
-<p><em>Aliases: <code>_.part</code></em>.</p>
+<p>Returns the powerset of an array.</p>
+
+
+<pre>
+M.powerset {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">-- =&gt; "{{1},{2},{3},{1,2},{2,3},{1,2,3}}"</span>
+</pre>
+
+
+<h3>partition (array [, n = 1 [, pad]])</h3>
+<p>*Aliases: <code>part</code>*.</p>
<p>Returns an iterator function for partitions of a given array.</p>
+
<pre>
<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}
-<span class="keyword">for</span> p <span class="keyword">in</span> _.partition(t,<span class="number">2</span>) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.partition(t,<span class="number">2</span>) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p, <span class="string">','</span>))
<span class="keyword">end</span>
@@ -1302,7 +1463,7 @@ _.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="
</span><span class="comment">-- =&gt; 5,6
</span>
<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}
-<span class="keyword">for</span> p <span class="keyword">in</span> _.partition(t,<span class="number">4</span>) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.partition(t,<span class="number">4</span>) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p, <span class="string">','</span>))
<span class="keyword">end</span>
@@ -1313,9 +1474,10 @@ _.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="
<p>In case the last partition has less elements than desired, a 3rd argument can be supplied to adjust the partition size.</p>
+
<pre>
<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}
-<span class="keyword">for</span> p <span class="keyword">in</span> _.partition(t,<span class="number">4</span>,<span class="number">0</span>) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.partition(t,<span class="number">4</span>,<span class="number">0</span>) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p, <span class="string">','</span>))
<span class="keyword">end</span>
@@ -1324,13 +1486,14 @@ _.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="
</pre>
-<h3>sliding (array, n, pad)</h3>
+<h3>overlapping (array [, n = 2 [, pad]])</h3>
<p>Returns an iterator function which provides overlapping subsequences of a given array.</p>
+
<pre>
<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}
-<span class="keyword">for</span> p <span class="keyword">in</span> _.sliding(t,<span class="number">3</span>) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.overlapping(t,<span class="number">3</span>) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p,<span class="string">','</span>))
<span class="keyword">end</span>
@@ -1338,14 +1501,14 @@ _.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="
</span><span class="comment">-- =&gt; 3,4,5
</span><span class="comment">-- =&gt; 5,6,7
</span>
-<span class="keyword">for</span> p <span class="keyword">in</span> _.sliding(t,<span class="number">4</span>) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.overlapping(t,<span class="number">4</span>) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p,<span class="string">','</span>))
<span class="keyword">end</span>
<span class="comment">-- =&gt; 1,2,3,4
</span><span class="comment">-- =&gt; 4,5,6,7
</span>
-<span class="keyword">for</span> p <span class="keyword">in</span> _.sliding(t,<span class="number">5</span>) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.overlapping(t,<span class="number">5</span>) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p,<span class="string">','</span>))
<span class="keyword">end</span>
@@ -1356,9 +1519,10 @@ _.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="
<p>In case the last subsequence wil not match the exact desired length, it can be adjusted with a 3rd argument <code>pad</code>.</p>
+
<pre>
<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>}
-<span class="keyword">for</span> p <span class="keyword">in</span> _.sliding(t,<span class="number">5</span>,<span class="number">0</span>) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.overlapping(t,<span class="number">5</span>,<span class="number">0</span>) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p,<span class="string">','</span>))
<span class="keyword">end</span>
@@ -1367,15 +1531,58 @@ _.rep(<span class="number">4</span>,<span class="number">3</span>) <span class="
</pre>
-<h3>permutation (array)</h3>
+<h3>aperture (array [, n = 2])</h3>
+<p>*Aliases: <code>sliding</code>*.</p>
+
+<p>Returns an iterator function which provides sliding partitions of a given array.</p>
+
+
+<pre>
+<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}
+<span class="keyword">for</span> p <span class="keyword">in</span> M.aperture(t,<span class="number">4</span>) <span class="keyword">do</span>
+ <span class="global">print</span>(<span class="global">table</span>.concat(p,<span class="string">','</span>))
+<span class="keyword">end</span>
+
+<span class="comment">-- =&gt; 1,2,3,4
+</span><span class="comment">-- =&gt; 2,3,4,5
+</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.aperture(t,<span class="number">3</span>) <span class="keyword">do</span>
+ <span class="global">print</span>(<span class="global">table</span>.concat(p,<span class="string">','</span>))
+<span class="keyword">end</span>
+
+<span class="comment">-- =&gt; 1,2,3
+</span><span class="comment">-- =&gt; 2,3,4
+</span><span class="comment">-- =&gt; 3,4,5</span>
+</pre>
-<p><em>Aliases: <code>_.perm</code></em>.</p>
+
+<h3>pairwise (array)</h3>
+
+<p>Iterator returning sliding pairs of an array.</p>
+
+
+<pre>
+<span class="keyword">local</span> t = M.range(<span class="number">5</span>)
+<span class="keyword">for</span> p <span class="keyword">in</span> pairwise(t) <span class="keyword">do</span>
+ <span class="global">print</span>(<span class="global">table</span>.concat(p,<span class="string">','</span>))
+<span class="keyword">end</span>
+
+<span class="comment">-- =&gt; 1,2
+</span><span class="comment">-- =&gt; 2,3
+</span><span class="comment">-- =&gt; 3,4
+</span><span class="comment">-- =&gt; 4,5</span>
+</pre>
+
+
+<h3>permutation (array)</h3>
+<p>*Aliases: <code>perm</code>*.</p>
<p>Returns an iterator function for permutations of a given array.</p>
+
<pre>
t = {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>}
-<span class="keyword">for</span> p <span class="keyword">in</span> _.permutation(t) <span class="keyword">do</span>
+<span class="keyword">for</span> p <span class="keyword">in</span> M.permutation(t) <span class="keyword">do</span>
<span class="global">print</span>(<span class="global">table</span>.concat(p))
<span class="keyword">end</span>
@@ -1389,39 +1596,91 @@ t = {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class
<h3>invert (array)</h3>
-
-<p><em>Aliases: <code>_.mirror</code></em>.</p>
+<p>*Aliases: <code>mirror</code>*.</p>
<p>Switches <tt>key-value</tt> pairs:</p>
+
<pre>
-_.invert {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>} <span class="comment">-- =&gt; "{a=1, b=2, c=3}"</span>
+M.invert {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>} <span class="comment">-- =&gt; "{a=1, b=2, c=3}"</span>
</pre>
-<h3>concat (array, sep, i, j)</h3>
-
-<p><em>Aliases: <code>_.join</code></em>.</p>
+<h3>concat (array [, sep = '' [, i = 1 [, j = #array]]])</h3>
+<p>*Aliases: <code>join</code>*.</p>
<p>Concatenates a given array values:</p>
+
<pre>
-_.concat({<span class="string">'a'</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="string">'b'</span>}) <span class="comment">-- =&gt; 'a101b'</span>
+M.concat({<span class="string">'a'</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="string">'b'</span>}) <span class="comment">-- =&gt; 'a101b'</span>
+</pre>
+
+
+<h3>xprod (array, array2)</h3>
+
+<p>Returns all possible pairs built from given arrays.</p>
+
+
+<pre>
+<span class="keyword">local</span> t = M.xprod({<span class="number">1</span>,<span class="number">2</span>},{<span class="string">'a'</span>,<span class="string">'b'</span>})
+<span class="comment">-- =&gt; {{1,'a'},{1,'b'},{2,'a'},{2,'b'}}</span>
+</pre>
+
+
+<h3>sum (array)</h3>
+
+<p>Returns the sum of array values.</p>
+
+
+<pre>
+M.sum({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; 15</span>
+</pre>
+
+
+<h3>product (array)</h3>
+
+<p>Returns the product of array values.</p>
+
+
+<pre>
+M.product({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; 120</span>
+</pre>
+
+
+<h3>mean (array)</h3>
+
+<p>Returns the mean of array values.</p>
+
+
+<pre>
+M.mean({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; 3</span>
+</pre>
+
+
+<h3>median (array)</h3>
+
+<p>Returns the median of array values.</p>
+
+
+<pre>
+M.median({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}) <span class="comment">-- =&gt; 3
+</span>M.median({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>}) <span class="comment">-- =&gt; 2.5</span>
</pre>
<p><strong><a href="#TOC">[⬆]</a></strong></p>
<p><a name="_a_name__utility__Utility_functions__a_"></a></p>
-
<h2><a name='utility'>Utility functions</a></h2>
<h3>noop ()</h3>
<p>The no-operation function. Takes nothing, returns nothing. It is being used internally.</p>
+
<pre>
-_.noop() <span class="comment">-- =&gt; nil</span>
+M.noop() <span class="comment">-- =&gt; nil</span>
</pre>
@@ -1430,47 +1689,91 @@ _.noop() <span class="comment">-- =&gt; nil</span>
<p>Returns the passed-in value. <br/>
This function is internally used as a default transformation function.</p>
+
<pre>
-_.identity(<span class="number">1</span>)<span class="comment">-- =&gt; 1
-</span>_.identity(<span class="keyword">false</span>) <span class="comment">-- =&gt; false
-</span>_.identity(<span class="string">'hello!'</span>) <span class="comment">-- =&gt; 'hello!'</span>
+M.identity(<span class="number">1</span>)<span class="comment">-- =&gt; 1
+</span>M.identity(<span class="keyword">false</span>) <span class="comment">-- =&gt; false
+</span>M.identity(<span class="string">'hello!'</span>) <span class="comment">-- =&gt; 'hello!'</span>
</pre>
<h3>constant (value)</h3>
-<p>Creates a constant function. This function will constinuously yield the same output.</p>
+<p>Creates a constant function. This function will continuously yield the same output.</p>
+
<pre>
-<span class="keyword">local</span> pi = _.constant(<span class="global">math</span>.pi)
+<span class="keyword">local</span> pi = M.constant(<span class="global">math</span>.pi)
pi(<span class="number">1</span>) <span class="comment">-- =&gt; 3.1415926535898
</span>pi(<span class="number">2</span>) <span class="comment">-- =&gt; 3.1415926535898
</span>pi(<span class="global">math</span>.pi) <span class="comment">-- =&gt; 3.1415926535898</span>
</pre>
-<h3>memoize (f, hash)</h3>
+<h3>applySpec (specs)</h3>
-<p><em>Aliases: <code>_.cache</code></em>.</p>
+<p>Returns a function which applies <code>specs</code> on args. This function will produce an object having the same structure than <code>specs</code> by mapping each property to the result of calling its associated function with the supplied arguments.</p>
+
+
+<pre>
+<span class="keyword">local</span> stats = M.applySpec({
+ min = <span class="keyword">function</span>(...) <span class="keyword">return</span> <span class="global">math</span>.min(...) <span class="keyword">end</span>,
+ max = <span class="keyword">function</span>(...) <span class="keyword">return</span> <span class="global">math</span>.max(...) <span class="keyword">end</span>,
+})
+
+stats(<span class="number">5</span>,<span class="number">4</span>,<span class="number">10</span>,<span class="number">1</span>,<span class="number">8</span>) <span class="comment">-- =&gt; {min = 1, max = 10}</span>
+</pre>
+
+
+<h3>memoize (f [, hash])</h3>
+<p>*Aliases: <code>cache</code>*.</p>
<p>Memoizes a slow-running function. It caches the result for a specific input, so that the next time the function is called with the same input, it will lookup the result in its cache, instead of running again the function body.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> fibonacci(n)
<span class="keyword">return</span> n &lt; <span class="number">2</span> <span class="keyword">and</span> n <span class="keyword">or</span> fibonacci(n-<span class="number">1</span>)+fibonacci(n-<span class="number">2</span>)
<span class="keyword">end</span>
-<span class="keyword">local</span> mem_fibonacci = _.memoize(fibonacci)
+<span class="keyword">local</span> mem_fibonacci = M.memoize(fibonacci)
fibonacci(<span class="number">20</span>) <span class="comment">-- =&gt; 6765 (but takes some time)
</span>mem_fibonacci(<span class="number">20</span>) <span class="comment">-- =&gt; 6765 (takes less time)</span>
</pre>
+<p>Can take a <code>hash</code> function as an optional arg to evaluate unique keys depending on the inputs when caching intermediate results.</p>
+
+
+<pre>
+<span class="keyword">local</span> <span class="keyword">function</span> hash(a) <span class="keyword">return</span> (a^<span class="number">13</span>) <span class="keyword">end</span>
+<span class="keyword">local</span> <span class="keyword">function</span> fact(a)
+ <span class="keyword">return</span> a &lt;= <span class="number">1</span> <span class="keyword">and</span> <span class="number">1</span> <span class="keyword">or</span> a*fact(a-<span class="number">1</span>)
+<span class="keyword">end</span>
+<span class="keyword">local</span> mfact = M.memoize(fact,hash)
+mfact(<span class="number">20</span>) <span class="comment">-- =&gt; 6765</span>
+</pre>
+
+
+<h3>unfold (f, seed)</h3>
+
+<p>Builds a list from a seed value. Accepts an iterator function, which returns either nil to stop iteration or two values : the value to add to the list of results and the seed to be used in the next call to the iterator function.</p>
+
+
+<pre>
+<span class="keyword">local</span> <span class="keyword">function</span> f(v)
+ <span class="keyword">if</span> v &lt; <span class="number">100</span> <span class="keyword">then</span> <span class="keyword">return</span> v, v * <span class="number">2</span> <span class="keyword">end</span>
+<span class="keyword">end</span>
+<span class="keyword">local</span> t = M.unfold(f, <span class="number">10</span>) <span class="comment">-- =&gt; {10,20,40,80}</span>
+</pre>
+
+
<h3>once (f)</h3>
<p>Produces a function that runs only once. Successive calls to this function will still yield the same input.</p>
+
<pre>
-<span class="keyword">local</span> sq = _.once(<span class="keyword">function</span>(a) <span class="keyword">return</span> a*a <span class="keyword">end</span>)
+<span class="keyword">local</span> sq = M.once(<span class="keyword">function</span>(a) <span class="keyword">return</span> a*a <span class="keyword">end</span>)
sq(<span class="number">1</span>) <span class="comment">-- =&gt; 1
</span>sq(<span class="number">2</span>) <span class="comment">-- =&gt; 1
</span>sq(<span class="number">3</span>) <span class="comment">-- =&gt; 1
@@ -1481,11 +1784,12 @@ sq(<span class="number">1</span>) <span class="comment">-- =&gt; 1
<h3>before (f, count)</h3>
-<p>Returns a version of <code>f</code> that will run no more than <a href="../index.html#count">count</a> times. Next calls will keep yielding the results of the (n-th)-1 call.</p>
+<p>Returns a version of <code>f</code> that will run no more than <a href="index.html#count">count</a> times. Next calls will keep yielding the results of the (n-th)-1 call.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> greet(someone) <span class="keyword">return</span> <span class="string">'hello '</span>..someone <span class="keyword">end</span>
-<span class="keyword">local</span> greetOnly3people = _.before(greet, <span class="number">3</span>)
+<span class="keyword">local</span> greetOnly3people = M.before(greet, <span class="number">3</span>)
greetOnly3people(<span class="string">'John'</span>) <span class="comment">-- =&gt; 'hello John'
</span>greetOnly3people(<span class="string">'Moe'</span>) <span class="comment">-- =&gt; 'hello Moe'
</span>greetOnly3people(<span class="string">'James'</span>) <span class="comment">-- =&gt; 'hello James'
@@ -1498,8 +1802,9 @@ greetOnly3people(<span class="string">'John'</span>) <span class="comment">-- =&
<p>Produces a function that will respond only after a given number of calls.</p>
+
<pre>
-<span class="keyword">local</span> f = _.after(_.identity,<span class="number">3</span>)
+<span class="keyword">local</span> f = M.after(M.identity,<span class="number">3</span>)
f(<span class="number">1</span>) <span class="comment">-- =&gt; nil
</span>f(<span class="number">2</span>) <span class="comment">-- =&gt; nil
</span>f(<span class="number">3</span>) <span class="comment">-- =&gt; 3
@@ -1507,30 +1812,32 @@ f(<span class="number">1</span>) <span class="comment">-- =&gt; nil
</pre>
-<h3>compose (&hellip;)</h3>
+<h3>compose (...)</h3>
<p>Composes functions. Each function consumes the return value of the one that follows.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> f(x) <span class="keyword">return</span> x^<span class="number">2</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> g(x) <span class="keyword">return</span> x+<span class="number">1</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> h(x) <span class="keyword">return</span> x/<span class="number">2</span> <span class="keyword">end</span>
-<span class="keyword">local</span> compositae = _.compose(f,g,h)
+<span class="keyword">local</span> compositae = M.compose(f,g,h)
compositae(<span class="number">10</span>) <span class="comment">-- =&gt; 36
</span>compositae(<span class="number">20</span>) <span class="comment">-- =&gt; 121</span>
</pre>
-<h3>pipe (value, &hellip;)</h3>
+<h3>pipe (value, ...)</h3>
<p>Pipes a value through a series of functions.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> f(x) <span class="keyword">return</span> x^<span class="number">2</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> g(x) <span class="keyword">return</span> x+<span class="number">1</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> h(x) <span class="keyword">return</span> x/<span class="number">2</span> <span class="keyword">end</span>
-_.pipe(<span class="number">10</span>,f,g,h) <span class="comment">-- =&gt; 36
-</span>_.pipe(<span class="number">20</span>,f,g,h) <span class="comment">-- =&gt; 121</span>
+M.pipe(<span class="number">10</span>,f,g,h) <span class="comment">-- =&gt; 36
+</span>M.pipe(<span class="number">20</span>,f,g,h) <span class="comment">-- =&gt; 121</span>
</pre>
@@ -1538,22 +1845,23 @@ _.pipe(<span class="number">10</span>,f,g,h) <span class="comment">-- =&gt; 36
<p>Returns a function which returns the logical complement of a given function.</p>
+
<pre>
-_.complement(<span class="keyword">function</span>() <span class="keyword">return</span> <span class="keyword">true</span> <span class="keyword">end</span>)() <span class="comment">-- =&gt; false</span>
+M.complement(<span class="keyword">function</span>() <span class="keyword">return</span> <span class="keyword">true</span> <span class="keyword">end</span>)() <span class="comment">-- =&gt; false</span>
</pre>
-<h3>juxtapose (value, &hellip;)</h3>
-
-<p><em>Aliases: <code>_.juxt</code></em>.</p>
+<h3>juxtapose (value, ...)</h3>
+<p>*Aliases: <code>juxt</code>*.</p>
<p>Calls a sequence of functions with the same input.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> f(x) <span class="keyword">return</span> x^<span class="number">2</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> g(x) <span class="keyword">return</span> x+<span class="number">1</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> h(x) <span class="keyword">return</span> x/<span class="number">2</span> <span class="keyword">end</span>
-_.juxtapose(<span class="number">10</span>, f, g, h) <span class="comment">-- =&gt; 100, 11, 5</span>
+M.juxtapose(<span class="number">10</span>, f, g, h) <span class="comment">-- =&gt; 100, 11, 5</span>
</pre>
@@ -1561,9 +1869,10 @@ _.juxtapose(<span class="number">10</span>, f, g, h) <span class="comment">-- =&
<p>Wraps a function inside a wrapper. Allows the wrapper to execute code before and after function run.</p>
+
<pre>
<span class="keyword">local</span> greet = <span class="keyword">function</span>(name) <span class="keyword">return</span> <span class="string">"hi: "</span> .. name <span class="keyword">end</span>
-<span class="keyword">local</span> greet_backwards = _.wrap(greet, <span class="keyword">function</span>(f,arg)
+<span class="keyword">local</span> greet_backwards = M.wrap(greet, <span class="keyword">function</span>(f,arg)
<span class="keyword">return</span> f(arg) ..<span class="string">'\nhi: '</span> .. arg:reverse()
<span class="keyword">end</span>)
greet_backwards(<span class="string">'John'</span>)
@@ -1573,13 +1882,14 @@ greet_backwards(<span class="string">'John'</span>)
</pre>
-<h3>times (n, iter, &hellip;)</h3>
+<h3>times (iter [, n [, ...]])</h3>
<p>Calls a given function <code>n</code> times.</p>
+
<pre>
<span class="keyword">local</span> f = (<span class="string">'Lua programming'</span>):gmatch(<span class="string">'.'</span>)
-_.times(<span class="number">3</span>,f) <span class="comment">-- =&gt; {'L','u','a'}</span>
+M.times(f, <span class="number">3</span>) <span class="comment">-- =&gt; {'L','u','a'}</span>
</pre>
@@ -1587,8 +1897,9 @@ _.times(<span class="number">3</span>,f) <span class="comment">-- =&gt; {'L','u'
<p>Binds a value to be the first argument to a function.</p>
+
<pre>
-<span class="keyword">local</span> sqrt2 = _.bind(<span class="global">math</span>.sqrt,<span class="number">2</span>)
+<span class="keyword">local</span> sqrt2 = M.bind(<span class="global">math</span>.sqrt,<span class="number">2</span>)
sqrt2() <span class="comment">-- =&gt; 1.4142135623731</span>
</pre>
@@ -1597,35 +1908,38 @@ sqrt2() <span class="comment">-- =&gt; 1.4142135623731</span>
<p>Binds a value to be the second argument to a function.</p>
+
<pre>
-<span class="keyword">local</span> last2 = _.bind(_.last,<span class="number">2</span>)
+<span class="keyword">local</span> last2 = M.bind(M.last,<span class="number">2</span>)
last2({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}) <span class="comment">-- =&gt; {5,6}</span>
</pre>
-<h3>bindn (f, &hellip;)</h3>
+<h3>bindn (f, ...)</h3>
<p>Binds a variable number of values to be the first arguments to a function.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> out(...) <span class="keyword">return</span> <span class="global">table</span>.concat {...} <span class="keyword">end</span>
-<span class="keyword">local</span> out = _.bindn(out,<span class="string">'OutPut'</span>,<span class="string">':'</span>,<span class="string">' '</span>)
+<span class="keyword">local</span> out = M.bindn(out,<span class="string">'OutPut'</span>,<span class="string">':'</span>,<span class="string">' '</span>)
out(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>) <span class="comment">-- =&gt; OutPut: 123
</span>out(<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>) <span class="comment">-- =&gt; OutPut: abcd</span>
</pre>
-<h3>bindAll (obj, &hellip;)</h3>
+<h3>bindall (obj, ...)</h3>
<p>Binds methods to object. As such, when calling any of these methods, they will receive object as a first argument.</p>
+
<pre>
<span class="keyword">local</span> window = {
setPos = <span class="keyword">function</span>(w,x,y) w.x, w.y = x, y <span class="keyword">end</span>,
setName = <span class="keyword">function</span>(w,name) w.name = name <span class="keyword">end</span>,
getName = <span class="keyword">function</span>(w) <span class="keyword">return</span> w.name <span class="keyword">end</span>,
}
-window = _.bindAll(window, <span class="string">'setPos'</span>, <span class="string">'setName'</span>, <span class="string">'getName'</span>)
+window = M.bindall(window, <span class="string">'setPos'</span>, <span class="string">'setName'</span>, <span class="string">'getName'</span>)
window.setPos(<span class="number">10</span>,<span class="number">15</span>)
<span class="global">print</span>(window.x, window.y) <span class="comment">-- =&gt; 10,15
</span>
@@ -1636,56 +1950,118 @@ window.setName(<span class="string">'fooApp'</span>)
</pre>
-<h3>uniqueId (template, &hellip;)</h3>
+<h3>cond (conds)</h3>
-<p><em>Aliases: <code>_.uid</code></em>.</p>
+<p>Returns a function which iterate over an array list of conditions. It invokes each predicate, passing it given values. It returns the value of the corresponding function of the first predicate to return a non-nil value</p>
+
+
+<pre>
+<span class="keyword">local</span> multipleOf = M.cond({
+ {<span class="keyword">function</span>(v) <span class="keyword">return</span> v%<span class="number">2</span>==<span class="number">0</span> <span class="keyword">end</span>, <span class="keyword">function</span>(v) <span class="keyword">return</span> v..<span class="string">' is multiple of 2'</span> <span class="keyword">end</span>},
+ {<span class="keyword">function</span>(v) <span class="keyword">return</span> v%<span class="number">3</span>==<span class="number">0</span> <span class="keyword">end</span>, <span class="keyword">function</span>(v) <span class="keyword">return</span> v..<span class="string">' is multiple of 3'</span> <span class="keyword">end</span>},
+ {<span class="keyword">function</span>(v) <span class="keyword">return</span> v%<span class="number">5</span>==<span class="number">0</span> <span class="keyword">end</span>, <span class="keyword">function</span>(v) <span class="keyword">return</span> v..<span class="string">' is multiple of 5'</span> <span class="keyword">end</span>},
+ {<span class="keyword">function</span>() <span class="keyword">return</span> <span class="keyword">true</span> <span class="keyword">end</span>, <span class="keyword">function</span>(v) <span class="keyword">return</span> <span class="string">'could not find an answer for '</span>..v <span class="keyword">end</span>}
+})
+<span class="keyword">for</span> i = <span class="number">15</span>, <span class="number">20</span> <span class="keyword">do</span>
+ <span class="global">print</span>(multipleOf(i))
+<span class="keyword">end</span>
+
+<span class="comment">-- =&gt; 15 is multiple of 3
+</span><span class="comment">-- =&gt; 16 is multiple of 2
+</span><span class="comment">-- =&gt; could not find an answer for 17
+</span><span class="comment">-- =&gt; 18 is multiple of 2
+</span><span class="comment">-- =&gt; could not find an answer for 19
+</span><span class="comment">-- =&gt; 20 is multiple of 2</span>
+</pre>
+
+
+<h3>uniqueId ([template [, ...]])</h3>
+<p>*Aliases: <code>uid</code>*.</p>
<p>Returns an unique integer ID.</p>
+
<pre>
-_.uniqueId() <span class="comment">-- =&gt; 1</span>
+M.uniqueId() <span class="comment">-- =&gt; 1</span>
</pre>
<p>Can handle string templates for formatted output.</p>
+
<pre>
-_.uniqueId(<span class="string">'ID%s'</span>) <span class="comment">-- =&gt; 'ID2'</span>
+M.uniqueId(<span class="string">'ID%s'</span>) <span class="comment">-- =&gt; 'ID2'</span>
</pre>
<p>Or a function, for the same purpose.</p>
+
<pre>
<span class="keyword">local</span> formatter = <span class="keyword">function</span>(ID) <span class="keyword">return</span> <span class="string">'$'</span>..ID..<span class="string">'$'</span> <span class="keyword">end</span>
-_.uniqueId(formatter) <span class="comment">-- =&gt; '$ID1$'</span>
+M.uniqueId(formatter) <span class="comment">-- =&gt; '$ID1$'</span>
</pre>
-<h3>iterator(f, x)</h3>
+<h3>iterator(f, value [, n])</h3>
+<p>*Aliases: <code>iter</code>*.</p>
-<p><em>Aliases: <code>_.iter</code></em>.</p>
+<p>Returns an iterator function which constinuously applies a function <code>f</code> onto an input <a href="index.html#obj:value">value</a>.
+For example, let us go through the powers of two using <a href="index.html#iterator">iterator</a>.</p>
-<p>Returns an iterator function which constinuously applies a function <code>f</code> onto an input <code>x</code>.
-For example, let us go through the powers of two.</p>
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> po2(x) <span class="keyword">return</span> x*<span class="number">2</span> <span class="keyword">end</span>
-<span class="keyword">local</span> <span class="keyword">function</span> iter_po2 = _.iterator(po2, <span class="number">1</span>)
+<span class="keyword">local</span> <span class="keyword">function</span> iter_po2 = M.iterator(po2, <span class="number">1</span>)
iter_po2() <span class="comment">-- =&gt; 2
</span>iter_po2() <span class="comment">-- =&gt; 4
</span>iter_po2() <span class="comment">-- =&gt; 8</span>
</pre>
-<h3>array (&hellip;)</h3>
+<p>if <code>n</code> is supplied, it will run at maximum <code>n</code> times.</p>
+
+
+<pre>
+<span class="keyword">local</span> <span class="keyword">function</span> po2(x) <span class="keyword">return</span> x*<span class="number">2</span> <span class="keyword">end</span>
+<span class="keyword">local</span> <span class="keyword">function</span> iter_po2 = M.iterator(po2, <span class="number">1</span>, <span class="number">3</span>)
+iter_po2() <span class="comment">-- =&gt; 2
+</span>iter_po2() <span class="comment">-- =&gt; 4
+</span>iter_po2() <span class="comment">-- =&gt; 8
+</span>iter_po2() <span class="comment">-- =&gt; nil</span>
+</pre>
+
+
+<h3>array (...)</h3>
+<p>*Aliases: <code>tabulate</code>*.</p>
<p>Iterates a given iterator function and returns its values packed in an array.</p>
+
<pre>
<span class="keyword">local</span> text = <span class="string">'letters'</span>
<span class="keyword">local</span> chars = <span class="global">string</span>.gmatch(text, <span class="string">'.'</span>)
-<span class="keyword">local</span> letters = _.array(chars) <span class="comment">-- =&gt; {'l','e','t','t','e','r','s'}</span>
+<span class="keyword">local</span> letters = M.array(chars) <span class="comment">-- =&gt; {'l','e','t','t','e','r','s'}</span>
+</pre>
+
+
+<h3>castArray (value)</h3>
+
+<p>Casts the passed-in value to an array containing the value itself.</p>
+
+
+<pre>
+M.castArray(<span class="keyword">true</span>) <span class="comment">-- =&gt; {true}
+</span>M.castArray(<span class="number">2</span>) <span class="comment">-- =&gt; {2}</span>
+</pre>
+
+
+<p>It leaves the given value untouched in case it is already a table.</p>
+
+
+<pre>
+<span class="keyword">local</span> t = {<span class="number">1</span>}
+<span class="global">print</span>(M.castArray(t) == t) <span class="comment">-- =&gt; true</span>
</pre>
@@ -1693,28 +2069,96 @@ iter_po2() <span class="comment">-- =&gt; 2
<p>Creates a function of <code>f</code> with arguments flipped in reverse order.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> f(...) <span class="keyword">return</span> <span class="global">table</span>.concat({...}) <span class="keyword">end</span>
-<span class="keyword">local</span> flipped = _.flip(f)
+<span class="keyword">local</span> flipped = M.flip(f)
flipped(<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; 'cba'</span>
</pre>
-<h3>over (&hellip;)</h3>
+<h3>nthArg(n)</h3>
+
+<p>Returns a function that gets the nth argument. </p>
+
+
+<pre>
+<span class="keyword">local</span> f = M.nthArg(<span class="number">3</span>)
+f(<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; 'c'</span>
+</pre>
+
+
+<p>If n is negative, the nth argument from the end is returned.</p>
+
+
+<pre>
+<span class="keyword">local</span> f = M.nthArg(-<span class="number">2</span>)
+f(<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; 'b'</span>
+</pre>
+
+
+<h3>unary (f)</h3>
+
+<p>Returns a function which accepts up to one argument. It ignores any additional arguments. </p>
+
+
+<pre>
+<span class="keyword">local</span> f = M.unary(<span class="keyword">function</span> (...) <span class="keyword">return</span> ... <span class="keyword">end</span>)
+f(<span class="string">'a'</span>) - ==&gt; <span class="string">'a'</span>
+f(<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; 'a'</span>
+</pre>
+
+
+<h3>ary (f [, n = 1])</h3>
+<p>*Aliases: <code>nAry</code>*.</p>
+
+<p>Returns a function which accepts up to <code>n</code> args. It ignores any additional arguments.</p>
+
+
+<pre>
+<span class="keyword">local</span> f = M.ary(<span class="keyword">function</span> (...) <span class="keyword">return</span> ... <span class="keyword">end</span>, <span class="number">2</span>)
+f(<span class="number">1</span>,<span class="number">2</span>) - ==&gt; <span class="number">1</span>,<span class="number">2</span>
+f(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>) <span class="comment">-- =&gt; 1,2</span>
+</pre>
+
+
+<p>If <code>n</code> is not given, it defaults to <code>1</code>.</p>
+
+
+<pre>
+<span class="keyword">local</span> f = M.unary(<span class="keyword">function</span> (...) <span class="keyword">return</span> ... <span class="keyword">end</span>)
+f(<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; 'a'</span>
+</pre>
+
+
+<h3>rearg (f, indexes)</h3>
+
+<p>Returns a function which runs with arguments arranged according to given <code>indexes</code>.</p>
+
+
+<pre>
+<span class="keyword">local</span> f = M.rearg(<span class="keyword">function</span> (...) <span class="keyword">return</span> ... <span class="keyword">end</span>, {<span class="number">5</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">1</span>})
+f(<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>,<span class="string">'e'</span>) <span class="comment">-- =&gt; 'e','d','c','b','a'</span>
+</pre>
+
+
+<h3>over (...)</h3>
<p>Creates a function that invokes a set of transforms with the arguments it receives.<br/>
One can use use for example to get the tuple of min and max values from a set of values</p>
+
<pre>
-<span class="keyword">local</span> minmax = _.over(<span class="global">math</span>.min, <span class="global">math</span>.max)
+<span class="keyword">local</span> minmax = M.over(<span class="global">math</span>.min, <span class="global">math</span>.max)
minmax(<span class="number">5</span>,<span class="number">10</span>,<span class="number">12</span>,<span class="number">4</span>,<span class="number">3</span>) <span class="comment">-- =&gt; {3,12}</span>
</pre>
-<h3>overEvery (&hellip;)</h3>
+<h3>overEvery (...)</h3>
<p>Creates a validation function. The returned function checks if all of the given predicates return truthy when invoked with the arguments it receives.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> alleven(...)
<span class="keyword">for</span> i, v <span class="keyword">in</span> <span class="global">ipairs</span>({...}) <span class="keyword">do</span>
@@ -1730,7 +2174,7 @@ minmax(<span class="number">5</span>,<span class="number">10</span>,<span class=
<span class="keyword">return</span> <span class="keyword">true</span>
<span class="keyword">end</span>
-<span class="keyword">local</span> allok = _.overEvery(alleven, allpositive)
+<span class="keyword">local</span> allok = M.overEvery(alleven, allpositive)
allok(<span class="number">2</span>,<span class="number">4</span>,-<span class="number">1</span>,<span class="number">8</span>) <span class="comment">-- =&gt; false
</span>allok(<span class="number">10</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">6</span>) <span class="comment">-- =&gt; false
@@ -1738,10 +2182,11 @@ allok(<span class="number">2</span>,<span class="number">4</span>,-<span class="
</pre>
-<h3>overSome (&hellip;)</h3>
+<h3>overSome (...)</h3>
<p>Creates a validation function. The returned function checks if any of the given predicates return truthy when invoked with the arguments it receives.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> alleven(...)
<span class="keyword">for</span> i, v <span class="keyword">in</span> <span class="global">ipairs</span>({...}) <span class="keyword">do</span>
@@ -1757,7 +2202,7 @@ allok(<span class="number">2</span>,<span class="number">4</span>,-<span class="
<span class="keyword">return</span> <span class="keyword">true</span>
<span class="keyword">end</span>
-<span class="keyword">local</span> anyok = _.overSome(alleven,allpositive)
+<span class="keyword">local</span> anyok = M.overSome(alleven,allpositive)
anyok(<span class="number">2</span>,<span class="number">4</span>,-<span class="number">1</span>,<span class="number">8</span>) <span class="comment">-- =&gt; false
</span>anyok(<span class="number">10</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">6</span>) <span class="comment">-- =&gt; true
@@ -1765,15 +2210,16 @@ anyok(<span class="number">2</span>,<span class="number">4</span>,-<span class="
</pre>
-<h3>overArgs (f, &hellip;)</h3>
+<h3>overArgs (f, ...)</h3>
<p>Creates a function that invokes <code>f</code> with its arguments transformed</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> f(x, y) <span class="keyword">return</span> x, y <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> triple(x) retun x*<span class="number">3</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> square(x) retun x^<span class="number">2</span> <span class="keyword">end</span>
-<span class="keyword">local</span> new_f = _.overArgs(f, triple, square)
+<span class="keyword">local</span> new_f = M.overArgs(f, triple, square)
new_f(<span class="number">1</span>,<span class="number">2</span>) <span class="comment">-- =&gt; 3, 4
</span>new_f(<span class="number">10</span>,<span class="number">10</span>) <span class="comment">-- =&gt; 30, 100</span>
@@ -1782,50 +2228,68 @@ new_f(<span class="number">1</span>,<span class="number">2</span>) <span class="
<p>In case the number of arguments is greater than the number of transforms, the remaining args will be left as-is.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> f(x, y, z) <span class="keyword">return</span> x, y, z <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> triple(x) retun x*<span class="number">3</span> <span class="keyword">end</span>
<span class="keyword">local</span> <span class="keyword">function</span> square(x) retun x^<span class="number">2</span> <span class="keyword">end</span>
-<span class="keyword">local</span> new_f = _.overArgs(f, triple, square)
+<span class="keyword">local</span> new_f = M.overArgs(f, triple, square)
new_f(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>) <span class="comment">-- =&gt; 3, 4, 3
</span>new_f(<span class="number">10</span>,<span class="number">10</span>,<span class="number">10</span>) <span class="comment">-- =&gt; 30, 100, 10</span>
</pre>
-<h3>partial (f, &hellip;)</h3>
+<h3>converge (f, g, h)</h3>
+
+<p>Converges two functions into one.</p>
+
+
+<pre>
+<span class="keyword">local</span> <span class="keyword">function</span> pow2(x) <span class="keyword">return</span> x*x <span class="keyword">end</span>
+<span class="keyword">local</span> <span class="keyword">function</span> pow3(x) <span class="keyword">return</span> x*x*x <span class="keyword">end</span>
+<span class="keyword">local</span> <span class="keyword">function</span> sum(a,b) <span class="keyword">return</span> a+b <span class="keyword">end</span>
+<span class="keyword">local</span> poly = M.converge(sum, pow2, pow3)
+poly(<span class="number">5</span>) <span class="comment">-- =&gt; 150 (ie. 5*5 + 5*5*5)</span>
+</pre>
+
+
+<h3>partial (f, ...)</h3>
<p>Partially apply a function by filling in any number of its arguments. </p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> diff(a, b) <span class="keyword">return</span> a - b <span class="keyword">end</span>
-<span class="keyword">local</span> diffFrom20 = _.partial(diff, <span class="number">20</span>) <span class="comment">-- arg 'a' will be 20 by default
+<span class="keyword">local</span> diffFrom20 = M.partial(diff, <span class="number">20</span>) <span class="comment">-- arg 'a' will be 20 by default
</span>diffFrom20(<span class="number">5</span>) <span class="comment">-- =&gt; 15</span>
</pre>
<p>The string <code>&apos;_&apos;</code> can be used as a placeholder in the list of arguments to specify an argument that should not be pre-filled, but is rather left open to be supplied at call-time.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> diff(a, b) <span class="keyword">return</span> a - b <span class="keyword">end</span>
-<span class="keyword">local</span> remove5 = _.partial(diff, <span class="string">'_'</span>, <span class="number">5</span>) <span class="comment">-- arg 'a' will be given at call-time, but 'b' is set to 5
+<span class="keyword">local</span> remove5 = M.partial(diff, <span class="string">'_'</span>, <span class="number">5</span>) <span class="comment">-- arg 'a' will be given at call-time, but 'b' is set to 5
</span>remove5(<span class="number">20</span>) <span class="comment">-- =&gt; 15</span>
</pre>
-<h3>partialRight (f, &hellip;)</h3>
+<h3>partialRight (f, ...)</h3>
+
+<p>Like <code>M.partial</code>, it partially applies a function by filling in any number of its arguments, but from the right.</p>
-<p>Like <code>_.partial</code>, it partially applies a function by filling in any number of its arguments, but from the right.</p>
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> concat(...) <span class="keyword">return</span> <span class="global">table</span>.concat({...},<span class="string">','</span>) <span class="keyword">end</span>
-<span class="keyword">local</span> concat_right = _.partialRight(concat,<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>)
+<span class="keyword">local</span> concat_right = M.partialRight(concat,<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>)
concat_right(<span class="string">'d'</span>) <span class="comment">-- =&gt; d,a,b,c
</span>
-concat_right = _.partialRight(concat,<span class="string">'a'</span>,<span class="string">'b'</span>)
+concat_right = M.partialRight(concat,<span class="string">'a'</span>,<span class="string">'b'</span>)
concat_right(<span class="string">'c'</span>,<span class="string">'d'</span>) <span class="comment">-- =&gt; c,d,a,b
</span>
-concat_right = _.partialRight(concat,<span class="string">'a'</span>)
+concat_right = M.partialRight(concat,<span class="string">'a'</span>)
concat_right(<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>) <span class="comment">-- =&gt; b,c,d,a</span>
</pre>
@@ -1833,27 +2297,29 @@ concat_right(<span class="string">'b'</span>,<span class="string">'c'</span>,<sp
<p>The string <code>&apos;_&apos;</code>, as always, can be used as a placeholder in the list of arguments to specify an argument that should not be pre-filled, but is rather left open to be supplied at call-time.
In that case, the first args supplied at runtime will be used to fill the initial list of args while the remaining will be prepended.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> concat(...) <span class="keyword">return</span> <span class="global">table</span>.concat({...},<span class="string">','</span>) <span class="keyword">end</span>
-<span class="keyword">local</span> concat_right = _.partialRight(concat,<span class="string">'a'</span>,<span class="string">'_'</span>,<span class="string">'c'</span>)
+<span class="keyword">local</span> concat_right = M.partialRight(concat,<span class="string">'a'</span>,<span class="string">'_'</span>,<span class="string">'c'</span>)
concat_right(<span class="string">'d'</span>,<span class="string">'b'</span>) <span class="comment">-- =&gt; b,a,d,c
</span>
-concat_right = _.partialRight(concat,<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'_'</span>)
+concat_right = M.partialRight(concat,<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'_'</span>)
concat_right(<span class="string">'c'</span>,<span class="string">'d'</span>) <span class="comment">-- =&gt; d,a,b,c
</span>
-concat_right = _.partialRight(concat,<span class="string">'_'</span>,<span class="string">'a'</span>)
+concat_right = M.partialRight(concat,<span class="string">'_'</span>,<span class="string">'a'</span>)
concat_right(<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>) <span class="comment">-- =&gt; c,d,b,a</span>
</pre>
-<h3>curry (f, n_args)</h3>
+<h3>curry (f [, n_args = 2])</h3>
<p>Curries a function. If the given function <code>f</code> takes multiple arguments, it returns another version of <code>f</code> that takes a single argument
(the first of the arguments to the original function) and returns a new function that takes the remainder of the arguments and returns the result.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> sumOf3args(x,y,z) <span class="keyword">return</span> x + y + z <span class="keyword">end</span>
-<span class="keyword">local</span> curried_sumOf3args = _.curry(sumOf3args, <span class="number">3</span>)
+<span class="keyword">local</span> curried_sumOf3args = M.curry(sumOf3args, <span class="number">3</span>)
sumOf3args(<span class="number">1</span>)(<span class="number">2</span>)(<span class="number">3</span>)) <span class="comment">-- =&gt; 6
</span>sumOf3args(<span class="number">0</span>)(<span class="number">6</span>)(<span class="number">9</span>)) <span class="comment">-- =&gt; 15</span>
</pre>
@@ -1861,18 +2327,20 @@ sumOf3args(<span class="number">1</span>)(<span class="number">2</span>)(<span c
<p><code>n_args</code> defaults to 2.</p>
+
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> product(x,y) <span class="keyword">return</span> x * y <span class="keyword">end</span>
-<span class="keyword">local</span> curried_product = _.curry(product)
+<span class="keyword">local</span> curried_product = M.curry(product)
curried_product(<span class="number">5</span>)(<span class="number">4</span>) <span class="comment">-- =&gt; 20
</span>curried_product(<span class="number">3</span>)(-<span class="number">5</span>) <span class="comment">-- =&gt; -15
</span>curried_product(<span class="number">0</span>)(<span class="number">1</span>) <span class="comment">-- =&gt; 0</span>
</pre>
-<h3>time (f, &hellip;)</h3>
+<h3>time (f [, ...])</h3>
+
+<p>Returns the execution time of <code>f (...)</code> in seconds and its results.</p>
-<p>Returns the execution time of <code>f (&hellip;)</code> in seconds and its results.</p>
<pre>
<span class="keyword">local</span> <span class="keyword">function</span> wait_count(n)
@@ -1881,24 +2349,24 @@ curried_product(<span class="number">5</span>)(<span class="number">4</span>) <s
<span class="keyword">return</span> i
<span class="keyword">end</span>
-<span class="keyword">local</span> time, i = _.time(wait_count, <span class="number">1e6</span>) <span class="comment">-- =&gt; 0.002 1000000
-</span><span class="keyword">local</span> time, i = _.time(wait_count, <span class="number">1e7</span>) <span class="comment">-- =&gt; 0.018 10000000</span>
+<span class="keyword">local</span> time, i = M.time(wait_count, <span class="number">1e6</span>) <span class="comment">-- =&gt; 0.002 1000000
+</span><span class="keyword">local</span> time, i = M.time(wait_count, <span class="number">1e7</span>) <span class="comment">-- =&gt; 0.018 10000000</span>
</pre>
<p><strong><a href="#TOC">[⬆]</a></strong></p>
<p><a name="_a_name__object__Object_functions__a_"></a></p>
-
<h2><a name='object'>Object functions</a></h2>
<h3>keys (obj)</h3>
<p>Collects the names of an object attributes.</p>
+
<pre>
-_.keys({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; "{1,2,3}"
-</span>_.keys({x = <span class="number">0</span>, y = <span class="number">1</span>}) <span class="comment">-- =&gt; "{'y','x'}"</span>
+M.keys({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; "{1,2,3}"
+</span>M.keys({x = <span class="number">0</span>, y = <span class="number">1</span>}) <span class="comment">-- =&gt; "{'y','x'}"</span>
</pre>
@@ -1906,9 +2374,33 @@ _.keys({<span class="number">1</span>,<span class="number">2</span>,<span class=
<p>Collects the values of an object attributes.</p>
+
+<pre>
+M.values({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; "{1,2,3}"
+</span>M.values({x = <span class="number">0</span>, y = <span class="number">1</span>}) <span class="comment">-- =&gt; "{1,0}"</span>
+</pre>
+
+
+<h3>path (obj, ...)</h3>
+
+<p>Returns the value at a given path in an object.</p>
+
+
<pre>
-_.values({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; "{1,2,3}"
-</span>_.values({x = <span class="number">0</span>, y = <span class="number">1</span>}) <span class="comment">-- =&gt; "{1,0}"</span>
+<span class="keyword">local</span> entity = {
+ pos = {x = <span class="number">1</span>, y = <span class="number">2</span>},
+ engine = {
+ left = {status = <span class="string">'active'</span>, damage = <span class="number">5</span>},
+ right = {status = <span class="string">'off'</span>, damage = <span class="number">10</span>}
+ },
+ boost = <span class="keyword">false</span>
+}
+
+M.path(entity,<span class="string">'pos'</span>,<span class="string">'x'</span>) <span class="comment">-- =&gt; 1
+</span>M.path(entity,<span class="string">'pos'</span>,<span class="string">'y'</span>) <span class="comment">-- =&gt; 2
+</span>M.path(entity,<span class="string">'engine'</span>,<span class="string">'left'</span>,<span class="string">'status'</span>) <span class="comment">-- =&gt; 'active'
+</span>M.path(entity,<span class="string">'engine'</span>,<span class="string">'right'</span>,<span class="string">'damage'</span>) <span class="comment">-- =&gt; 10
+</span>M.path(entity,<span class="string">'boost'</span>) <span class="comment">-- =&gt; false</span>
</pre>
@@ -1916,9 +2408,10 @@ _.values({<span class="number">1</span>,<span class="number">2</span>,<span clas
<p>Converts an object to an array-list of key-value pairs.</p>
+
<pre>
<span class="keyword">local</span> obj = {x = <span class="number">1</span>, y = <span class="number">2</span>, z = <span class="number">3</span>}
-_.each(_.kvpairs(obj), <span class="keyword">function</span>(k,v)
+M.each(M.kvpairs(obj), <span class="keyword">function</span>(v,k)
<span class="global">print</span>(k, <span class="global">table</span>.concat(v,<span class="string">','</span>))
<span class="keyword">end</span>)
@@ -1928,13 +2421,14 @@ _.each(_.kvpairs(obj), <span class="keyword">function</span>(k,v)
</pre>
-<h3>toObj</h3>
+<h3>toObj (kvpairs)</h3>
+
+<p>Converts an array list of <a href="index.html#kvpairs">kvpairs</a> to an object where keys are taken from the 1rst column in the <a href="index.html#kvpairs">kvpairs</a> sequence, associated with values in the 2nd column.</p>
-<p>Converts an array list of <a href="../index.html#kvpairs">kvpairs</a> to an object where keys are taken from the 1rst column in the <a href="../index.html#kvpairs">kvpairs</a> sequence, associated with values in the 2nd column.</p>
<pre>
<span class="keyword">local</span> list_pairs = {{<span class="string">'x'</span>,<span class="number">1</span>},{<span class="string">'y'</span>,<span class="number">2</span>},{<span class="string">'z'</span>,<span class="number">3</span>}}
-obj = _.toObj(list_pairs)
+obj = M.toObj(list_pairs)
<span class="comment">-- =&gt; {x = 1, y = 2, z = 3}</span>
</pre>
@@ -1944,8 +2438,9 @@ obj = _.toObj(list_pairs)
<p>Returns a function that will return the key property of any passed-in object.</p>
+
<pre>
-<span class="keyword">local</span> who = _.property(<span class="string">'name'</span>)
+<span class="keyword">local</span> who = M.property(<span class="string">'name'</span>)
<span class="keyword">local</span> people = {name = <span class="string">'Henry'</span>}
who(people) <span class="comment">-- =&gt; 'Henry'</span>
</pre>
@@ -1955,9 +2450,10 @@ who(people) <span class="comment">-- =&gt; 'Henry'</span>
<p>Returns a function that will return the key property of any passed-in object.</p>
+
<pre>
<span class="keyword">local</span> people = {name = <span class="string">'Henry'</span>}
-<span class="global">print</span>(_.propertyOf(people)(<span class="string">'name'</span>)) <span class="comment">-- =&gt; 'Henry'</span>
+<span class="global">print</span>(M.propertyOf(people)(<span class="string">'name'</span>)) <span class="comment">-- =&gt; 'Henry'</span>
</pre>
@@ -1965,58 +2461,74 @@ who(people) <span class="comment">-- =&gt; 'Henry'</span>
<p>Converts a given value to a boolean.</p>
+
<pre>
-_.toBoolean(<span class="keyword">true</span>) <span class="comment">-- =&gt; true
-</span>_.toBoolean(<span class="keyword">false</span>) <span class="comment">-- =&gt; false
-</span>_.toBoolean(<span class="keyword">nil</span>) <span class="comment">-- =&gt; false
-</span>_.toBoolean({}) <span class="comment">-- =&gt; true
-</span>_.toBoolean(<span class="number">1</span>) <span class="comment">-- =&gt; true</span>
+M.toBoolean(<span class="keyword">true</span>) <span class="comment">-- =&gt; true
+</span>M.toBoolean(<span class="keyword">false</span>) <span class="comment">-- =&gt; false
+</span>M.toBoolean(<span class="keyword">nil</span>) <span class="comment">-- =&gt; false
+</span>M.toBoolean({}) <span class="comment">-- =&gt; true
+</span>M.toBoolean(<span class="number">1</span>) <span class="comment">-- =&gt; true</span>
</pre>
-<h3>extend (destObj, &hellip;)</h3>
+<h3>extend (destObj, ...)</h3>
<p>Extends a destination object with the properties of some source objects.</p>
+
<pre>
-_.extend({},{a = <span class="string">'b'</span>, c = <span class="string">'d'</span>}) <span class="comment">-- =&gt; "{a = 'b', c = 'd'}"</span>
+M.extend({},{a = <span class="string">'b'</span>, c = <span class="string">'d'</span>}) <span class="comment">-- =&gt; "{a = 'b', c = 'd'}"</span>
</pre>
-<h3>functions (obj, recurseMt)</h3>
-
-<p><em>Aliases: <code>_.methods</code></em>.</p>
+<h3>functions (obj [, recurseMt])</h3>
+<p>*Aliases: <code>methods</code>*.</p>
<p>Returns all functions names within an object.</p>
+
+<pre>
+M.functions(<span class="global">coroutine</span>)
+<span class="comment">-- =&gt; "{'yield','wrap','status','resume','running','create'}"</span>
+</pre>
+
+
+<p>When given <code>recurseMt</code>, will also include <code>obj</code> metatable's functions.</p>
+
+
<pre>
-_.functions(<span class="global">coroutine</span>) <span class="comment">-- =&gt; "{'create','resume','running','status','wrap','yield'}"</span>
+<span class="keyword">local</span> mt = {<span class="global">print</span> = <span class="global">print</span>}
+<span class="keyword">local</span> t = {<span class="global">assert</span> = <span class="global">assert</span>}
+<span class="global">setmetatable</span>(t, {__index = mt})
+M.functions(t, <span class="keyword">true</span>) <span class="comment">-- =&gt; "{'assert','print'}"</span>
</pre>
-<h3>clone (obj, shallow)</h3>
+<h3>clone (obj [, shallow])</h3>
<p>Clones a given object.</p>
+
<pre>
<span class="keyword">local</span> obj = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
-<span class="keyword">local</span> obj2 = _.clone(obj)
+<span class="keyword">local</span> obj2 = M.clone(obj)
<span class="global">print</span>(obj2 == obj) <span class="comment">-- =&gt; false
-</span><span class="global">print</span>(_.isEqual(obj2, obj)) <span class="comment">-- =&gt; true</span>
+</span><span class="global">print</span>(M.isEqual(obj2, obj)) <span class="comment">-- =&gt; true</span>
</pre>
-<h3>tap (obj, f, &hellip;)</h3>
+<h3>tap (obj, f [, ...])</h3>
<p>Invokes a given interceptor function on some object, and then returns the object itself. Useful to tap into method chaining to hook intermediate results.
-The pased-interceptor is prototyped as <code>f(obj,&hellip;)</code>.</p>
+The passed-in interceptor should be prototyped as <code>f(obj,...)</code>.</p>
+
<pre>
-<span class="keyword">local</span> v = _.chain({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>,<span class="number">10</span>)
- :filter(<span class="keyword">function</span>(k,v) <span class="keyword">return</span> v%<span class="number">2</span>~=<span class="number">0</span> <span class="keyword">end</span>) <span class="comment">-- filters even values
-</span> :tap(<span class="keyword">function</span>(v) <span class="global">print</span>(<span class="string">'Max is'</span>, _.max(v) <span class="keyword">end</span>) <span class="comment">-- Tap max values
-</span> :map(<span class="keyword">function</span>(k,v) <span class="keyword">return</span> k^<span class="number">2</span>)
- :value() <span class="comment">-- =&gt; Max is 9</span>
+<span class="keyword">local</span> v = M.chain({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>,<span class="number">10</span>})
+ :filter(<span class="keyword">function</span>(v) <span class="keyword">return</span> v%<span class="number">2</span>~=<span class="number">0</span> <span class="keyword">end</span>) <span class="comment">-- retain odd values
+</span> :tap(<span class="keyword">function</span>(v) <span class="global">print</span>(<span class="string">'Max is'</span>, M.max(v) <span class="keyword">end</span>) <span class="comment">-- Tap max value
+</span> :map(<span class="keyword">function</span>(v) <span class="keyword">return</span> v^<span class="number">2</span> <span class="keyword">end</span>)
+ :value() <span class="comment">-- =&gt; Max is 89</span>
</pre>
@@ -2024,70 +2536,72 @@ The pased-interceptor is prototyped as <code>f(obj,&hellip;)</code>.</p>
<p>Checks if an object has a given attribute.</p>
+
<pre>
-_.has(_,<span class="string">'has'</span>) <span class="comment">-- =&gt; true
-</span>_.has(<span class="global">coroutine</span>,<span class="string">'resume'</span>) <span class="comment">-- =&gt; true
-</span>_.has(<span class="global">math</span>,<span class="string">'random'</span>) <span class="comment">-- =&gt; true</span>
+M.has(_,<span class="string">'has'</span>) <span class="comment">-- =&gt; true
+</span>M.has(<span class="global">coroutine</span>,<span class="string">'resume'</span>) <span class="comment">-- =&gt; true
+</span>M.has(<span class="global">math</span>,<span class="string">'random'</span>) <span class="comment">-- =&gt; true</span>
</pre>
-<h3>pick (obj, &hellip;)</h3>
-
-<p><em>Aliases: <code>_.choose</code></em>.</p>
+<h3>pick (obj, ...)</h3>
+<p>*Aliases: <code>choose</code>*.</p>
<p>Collects whilelisted properties of a given object.</p>
+
<pre>
<span class="keyword">local</span> object = {a = <span class="number">1</span>, b = <span class="number">2</span>, c = <span class="number">3</span>}
-_.pick(object,<span class="string">'a'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; "{a = 1, c = 3}"</span>
+M.pick(object,<span class="string">'a'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; "{a = 1, c = 3}"</span>
</pre>
-<h3>omit (obj, &hellip;)</h3>
-
-<p><em>Aliases: <code>_.drop</code></em>.</p>
+<h3>omit (obj, ...)</h3>
+<p>*Aliases: <code>drop</code>*.</p>
<p>Omits blacklisted properties of a given object.</p>
+
<pre>
<span class="keyword">local</span> object = {a = <span class="number">1</span>, b = <span class="number">2</span>, c = <span class="number">3</span>}
-_.omit(object,<span class="string">'a'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; "{b = 2}"</span>
+M.omit(object,<span class="string">'a'</span>,<span class="string">'c'</span>) <span class="comment">-- =&gt; "{b = 2}"</span>
</pre>
-<h3>template (obj, template)</h3>
-
-<p><em>Aliases: <code>_.defaults</code></em>.</p>
+<h3>template (obj [, template])</h3>
+<p>*Aliases: <code>defaults</code>*.</p>
<p>Applies a template on an object, preserving existing properties.</p>
+
<pre>
<span class="keyword">local</span> obj = {a = <span class="number">0</span>}
-_.template(obj,{a = <span class="number">1</span>, b = <span class="number">2</span>, c = <span class="number">3</span>}) <span class="comment">-- =&gt; "{a=0, c=3, b=2}"</span>
+M.template(obj,{a = <span class="number">1</span>, b = <span class="number">2</span>, c = <span class="number">3</span>}) <span class="comment">-- =&gt; "{a=0, c=3, b=2}"</span>
</pre>
-<h3>isEqual (objA, objB, useMt)</h3>
-
-<p><em>Aliases: <code>_.compare</code></em>.</p>
+<h3>isEqual (objA, objB [, useMt])</h3>
+<p>*Aliases: <code>compare</code>, <code>M.matches</code>*.</p>
<p>Compares objects:</p>
+
<pre>
-_.isEqual(<span class="number">1</span>,<span class="number">1</span>) <span class="comment">-- =&gt; true
-</span>_.isEqual(<span class="keyword">true</span>,<span class="keyword">false</span>) <span class="comment">-- =&gt; false
-</span>_.isEqual(<span class="number">3.14</span>,<span class="global">math</span>.pi) <span class="comment">-- =&gt; false
-</span>_.isEqual({<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>},{<span class="number">3</span>,<span class="number">4</span>,{<span class="number">5</span>}}) <span class="comment">-- =&gt; false</span>
+M.isEqual(<span class="number">1</span>,<span class="number">1</span>) <span class="comment">-- =&gt; true
+</span>M.isEqual(<span class="keyword">true</span>,<span class="keyword">false</span>) <span class="comment">-- =&gt; false
+</span>M.isEqual(<span class="number">3.14</span>,<span class="global">math</span>.pi) <span class="comment">-- =&gt; false
+</span>M.isEqual({<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>},{<span class="number">3</span>,<span class="number">4</span>,{<span class="number">5</span>}}) <span class="comment">-- =&gt; false</span>
</pre>
-<h3>result (obj, method, &hellip;)</h3>
+<h3>result (obj, method [, ...])</h3>
<p>Calls an object method, passing it as a first argument the object itself.</p>
+
<pre>
-_.result(<span class="string">'abc'</span>,<span class="string">'len'</span>) <span class="comment">-- =&gt; 3
-</span>_.result({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>},<span class="global">table</span>.concat) <span class="comment">-- =&gt; 'abc'</span>
+M.result(<span class="string">'abc'</span>,<span class="string">'len'</span>) <span class="comment">-- =&gt; 3
+</span>M.result({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>},<span class="global">table</span>.concat) <span class="comment">-- =&gt; 'abc'</span>
</pre>
@@ -2095,10 +2609,11 @@ _.result(<span class="string">'abc'</span>,<span class="string">'len'</span>) <s
<p>Is the given argument an object (i.e a table) ?</p>
+
<pre>
-_.isTable({}) <span class="comment">-- =&gt; true
-</span>_.isTable(<span class="global">math</span>) <span class="comment">-- =&gt; true
-</span>_.isTable(<span class="global">string</span>) <span class="comment">-- =&gt; true</span>
+M.isTable({}) <span class="comment">-- =&gt; true
+</span>M.isTable(<span class="global">math</span>) <span class="comment">-- =&gt; true
+</span>M.isTable(<span class="global">string</span>) <span class="comment">-- =&gt; true</span>
</pre>
@@ -2106,11 +2621,12 @@ _.isTable({}) <span class="comment">-- =&gt; true
<p>Is the given argument callable ?</p>
+
<pre>
-_.isCallable(<span class="global">print</span>) <span class="comment">-- =&gt; true
-</span>_.isCallable(<span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; true
-</span>_.isCallable(<span class="global">setmetatable</span>({},{__index = <span class="global">string</span>}).upper) <span class="comment">-- =&gt; true
-</span>_.isCallable(<span class="global">setmetatable</span>({},{__call = <span class="keyword">function</span>() <span class="keyword">return</span> <span class="keyword">end</span>})) <span class="comment">-- =&gt; true</span>
+M.isCallable(<span class="global">print</span>) <span class="comment">-- =&gt; true
+</span>M.isCallable(<span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; true
+</span>M.isCallable(<span class="global">setmetatable</span>({},{__index = <span class="global">string</span>}).upper) <span class="comment">-- =&gt; true
+</span>M.isCallable(<span class="global">setmetatable</span>({},{__call = <span class="keyword">function</span>() <span class="keyword">return</span> <span class="keyword">end</span>})) <span class="comment">-- =&gt; true</span>
</pre>
@@ -2118,10 +2634,11 @@ _.isCallable(<span class="global">print</span>) <span class="comment">-- =&gt; t
<p>Is the given argument an array (i.e. a sequence) ?</p>
+
<pre>
-_.isArray({}) <span class="comment">-- =&gt; true
-</span>_.isArray({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; true
-</span>_.isArray({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>}) <span class="comment">-- =&gt; true</span>
+M.isArray({}) <span class="comment">-- =&gt; true
+</span>M.isArray({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) <span class="comment">-- =&gt; true
+</span>M.isArray({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>}) <span class="comment">-- =&gt; true</span>
</pre>
@@ -2129,22 +2646,24 @@ _.isArray({}) <span class="comment">-- =&gt; true
<p>Checks if the given object is iterable with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a>.</p>
+
<pre>
-_.isIterable({}) <span class="comment">-- =&gt; true
-</span>_.isIterable(<span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; false
-</span>_.isIterable(<span class="keyword">false</span>) <span class="comment">-- =&gt; false
-</span>_.isIterable(<span class="number">1</span>) <span class="comment">-- =&gt; false</span>
+M.isIterable({}) <span class="comment">-- =&gt; true
+</span>M.isIterable(<span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; false
+</span>M.isIterable(<span class="keyword">false</span>) <span class="comment">-- =&gt; false
+</span>M.isIterable(<span class="number">1</span>) <span class="comment">-- =&gt; false</span>
</pre>
-<h3>isEmpty (obj)</h3>
+<h3>isEmpty ([obj])</h3>
<p>Is the given argument empty ?</p>
+
<pre>
-_.isEmpty(<span class="string">''</span>) <span class="comment">-- =&gt; true
-</span>_.isEmpty({}) <span class="comment">-- =&gt; true
-</span>_.isEmpty({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>}) <span class="comment">-- =&gt; false</span>
+M.isEmpty(<span class="string">''</span>) <span class="comment">-- =&gt; true
+</span>M.isEmpty({}) <span class="comment">-- =&gt; true
+</span>M.isEmpty({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>}) <span class="comment">-- =&gt; false</span>
</pre>
@@ -2152,10 +2671,11 @@ _.isEmpty(<span class="string">''</span>) <span class="comment">-- =&gt; true
<p>Is the given argument a string ?</p>
+
<pre>
-_.isString(<span class="string">''</span>) <span class="comment">-- =&gt; true
-</span>_.isString(<span class="string">'Hello'</span>) <span class="comment">-- =&gt; false
-</span>_.isString({}) <span class="comment">-- =&gt; false</span>
+M.isString(<span class="string">''</span>) <span class="comment">-- =&gt; true
+</span>M.isString(<span class="string">'Hello'</span>) <span class="comment">-- =&gt; false
+</span>M.isString({}) <span class="comment">-- =&gt; false</span>
</pre>
@@ -2163,10 +2683,11 @@ _.isString(<span class="string">''</span>) <span class="comment">-- =&gt; true
<p>Is the given argument a function ?</p>
+
<pre>
-_.isFunction(<span class="global">print</span>) <span class="comment">-- =&gt; true
-</span>_.isFunction(<span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; true
-</span>_.isFunction({}) <span class="comment">-- =&gt; false</span>
+M.isFunction(<span class="global">print</span>) <span class="comment">-- =&gt; true
+</span>M.isFunction(<span class="keyword">function</span>() <span class="keyword">end</span>) <span class="comment">-- =&gt; true
+</span>M.isFunction({}) <span class="comment">-- =&gt; false</span>
</pre>
@@ -2174,10 +2695,11 @@ _.isFunction(<span class="global">print</span>) <span class="comment">-- =&gt; t
<p>Is the given argument nil ?</p>
+
<pre>
-_.isNil(<span class="keyword">nil</span>) <span class="comment">-- =&gt; true
-</span>_.isNil() <span class="comment">-- =&gt; true
-</span>_.isNil({}) <span class="comment">-- =&gt; false</span>
+M.isNil(<span class="keyword">nil</span>) <span class="comment">-- =&gt; true
+</span>M.isNil() <span class="comment">-- =&gt; true
+</span>M.isNil({}) <span class="comment">-- =&gt; false</span>
</pre>
@@ -2185,11 +2707,12 @@ _.isNil(<span class="keyword">nil</span>) <span class="comment">-- =&gt; true
<p>Is the given argument a number ?</p>
+
<pre>
-_.isNumber(<span class="global">math</span>.pi) <span class="comment">-- =&gt; true
-</span>_.isNumber(<span class="global">math</span>.huge) <span class="comment">-- =&gt; true
-</span>_.isNumber(<span class="number">0</span>/<span class="number">0</span>) <span class="comment">-- =&gt; true
-</span>_.isNumber() <span class="comment">-- =&gt; false</span>
+M.isNumber(<span class="global">math</span>.pi) <span class="comment">-- =&gt; true
+</span>M.isNumber(<span class="global">math</span>.huge) <span class="comment">-- =&gt; true
+</span>M.isNumber(<span class="number">0</span>/<span class="number">0</span>) <span class="comment">-- =&gt; true
+</span>M.isNumber() <span class="comment">-- =&gt; false</span>
</pre>
@@ -2197,9 +2720,10 @@ _.isNumber(<span class="global">math</span>.pi) <span class="comment">-- =&gt; t
<p>Is the given argument NaN ?</p>
+
<pre>
-_.isNaN(<span class="number">1</span>) <span class="comment">-- =&gt; false
-</span>_.isNaN(<span class="number">0</span>/<span class="number">0</span>) <span class="comment">-- =&gt; true</span>
+M.isNaN(<span class="number">1</span>) <span class="comment">-- =&gt; false
+</span>M.isNaN(<span class="number">0</span>/<span class="number">0</span>) <span class="comment">-- =&gt; true</span>
</pre>
@@ -2207,12 +2731,13 @@ _.isNaN(<span class="number">1</span>) <span class="comment">-- =&gt; false
<p>Is the given argument a finite number ?</p>
+
<pre>
-_.isFinite(<span class="number">99e99</span>) <span class="comment">-- =&gt; true
-</span>_.isFinite(<span class="global">math</span>.pi) <span class="comment">-- =&gt; true
-</span>_.isFinite(<span class="global">math</span>.huge) <span class="comment">-- =&gt; false
-</span>_.isFinite(<span class="number">1</span>/<span class="number">0</span>) <span class="comment">-- =&gt; false
-</span>_.isFinite(<span class="number">0</span>/<span class="number">0</span>) <span class="comment">-- =&gt; false</span>
+M.isFinite(<span class="number">99e99</span>) <span class="comment">-- =&gt; true
+</span>M.isFinite(<span class="global">math</span>.pi) <span class="comment">-- =&gt; true
+</span>M.isFinite(<span class="global">math</span>.huge) <span class="comment">-- =&gt; false
+</span>M.isFinite(<span class="number">1</span>/<span class="number">0</span>) <span class="comment">-- =&gt; false
+</span>M.isFinite(<span class="number">0</span>/<span class="number">0</span>) <span class="comment">-- =&gt; false</span>
</pre>
@@ -2220,11 +2745,12 @@ _.isFinite(<span class="number">99e99</span>) <span class="comment">-- =&gt; tru
<p>Is the given argument a boolean ?</p>
+
<pre>
-_.isBoolean(<span class="keyword">true</span>) <span class="comment">-- =&gt; true
-</span>_.isBoolean(<span class="keyword">false</span>) <span class="comment">-- =&gt; true
-</span>_.isBoolean(<span class="number">1</span>==<span class="number">1</span>) <span class="comment">-- =&gt; true
-</span>_.isBoolean(<span class="global">print</span>) <span class="comment">-- =&gt; false</span>
+M.isBoolean(<span class="keyword">true</span>) <span class="comment">-- =&gt; true
+</span>M.isBoolean(<span class="keyword">false</span>) <span class="comment">-- =&gt; true
+</span>M.isBoolean(<span class="number">1</span>==<span class="number">1</span>) <span class="comment">-- =&gt; true
+</span>M.isBoolean(<span class="global">print</span>) <span class="comment">-- =&gt; false</span>
</pre>
@@ -2232,23 +2758,26 @@ _.isBoolean(<span class="keyword">true</span>) <span class="comment">-- =&gt; tr
<p>Is the given argument an integer ?</p>
+
<pre>
-_.isInteger(<span class="global">math</span>.pi) <span class="comment">-- =&gt; false
-</span>_.isInteger(<span class="number">1</span>) <span class="comment">-- =&gt; true
-</span>_.isInteger(-<span class="number">1</span>) <span class="comment">-- =&gt; true</span>
+M.isInteger(<span class="global">math</span>.pi) <span class="comment">-- =&gt; false
+</span>M.isInteger(<span class="number">1</span>) <span class="comment">-- =&gt; true
+</span>M.isInteger(-<span class="number">1</span>) <span class="comment">-- =&gt; true</span>
</pre>
<p><strong><a href="#TOC">[⬆]</a></strong></p>
<p><a name="_a_name__chaining__Chaining__a_"></a></p>
-
<h2><a name='chaining'>Chaining</a></h2>
<p><em>Method chaining</em> (also known as <em>name parameter idiom</em>), is a technique for invoking consecutively method calls in object-oriented style.
-Each method returns an object, and methods calls are chained together.
-Moses offers chaining for your perusal. <br/>
-Let&rsquo;s use chaining to get the count of evey single word in some lyrics (case won&rsquo;t matter here).</p>
+Each method returns an object, and method calls are chained together.
+Moses offers chaining for your perusal. <br/></p>
+
+<p>Let's use chaining to get the count of evey single word in some lyrics (case won't matter here).</p>
+
+
<pre>
<span class="keyword">local</span> lyrics = {
@@ -2258,16 +2787,17 @@ Let&rsquo;s use chaining to get the count of evey single word in some lyrics (ca
<span class="string">"He sleeps all night and he works all day"</span>
}
-<span class="keyword">local</span> stats = _.chain(lyrics)
- :map(<span class="keyword">function</span>(k,line)
- <span class="keyword">local</span> t = {}
- <span class="keyword">for</span> w <span class="keyword">in</span> line:gmatch(<span class="string">'(%w+)'</span>) <span class="keyword">do</span>
- t[#t+<span class="number">1</span>] = w
- <span class="keyword">end</span>
- <span class="keyword">return</span> t
- <span class="keyword">end</span>)
+<span class="comment">-- split a text into words
+</span><span class="keyword">local</span> <span class="keyword">function</span> words(line)
+ <span class="keyword">local</span> t = {}
+ <span class="keyword">for</span> w <span class="keyword">in</span> line:gmatch(<span class="string">'(%w+)'</span>) <span class="keyword">do</span> t[#t+<span class="number">1</span>] = w <span class="keyword">end</span>
+ <span class="keyword">return</span> t
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> stats = M.chain(lyrics)
+ :map(words)
:flatten()
- :countBy(<span class="keyword">function</span>(i,v) <span class="keyword">return</span> v:lower() <span class="keyword">end</span>)
+ :countBy(<span class="global">string</span>.lower)
:value()
<span class="comment">-- =&gt; "{
@@ -2278,10 +2808,11 @@ Let&rsquo;s use chaining to get the count of evey single word in some lyrics (ca
</pre>
-<p>For convenience, you can also use <code>_(value)</code> to start chaining methods, instead of <code>_.chain(value)</code>.</p>
+<p>For convenience, you can also use <code>_(value)</code> to start chaining methods, instead of <code>M.chain(value)</code>.</p>
<p>Note that one can use <code>:value()</code> to unwrap a chained object.</p>
+
<pre>
<span class="keyword">local</span> t = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
<span class="global">print</span>(_(t):value() == t) <span class="comment">-- =&gt; true</span>
@@ -2291,14 +2822,14 @@ Let&rsquo;s use chaining to get the count of evey single word in some lyrics (ca
<p><strong><a href="#TOC">[⬆]</a></strong></p>
<p><a name="_a_name__import__Import__a_"></a></p>
-
<h2><a name='import'>Import</a></h2>
-<p>All library functions can be imported in a context using <a href="../index.html#import">import</a> into a specified context.</p>
+<p>All library functions can be imported in a context using <a href="index.html#import">import</a> into a specified context.</p>
+
<pre>
<span class="keyword">local</span> context = {}
-_.import(context)
+M.import(context)
context.each({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="global">print</span>)
@@ -2308,10 +2839,11 @@ context.each({<span class="number">1</span>,<span class="number">2</span>,<span
</pre>
-<p>When no <code>context</code> was provided, it defaults to the global environment <code>_G</code>.</p>
+<p>When no <code>context</code> was provided, it defaults to the current environment, <code>_ENV</code> or <code>_G</code>.</p>
+
<pre>
-_.import()
+M.import()
each({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="global">print</span>)
@@ -2323,9 +2855,10 @@ each({<span class="number">1</span>,<span class="number">2</span>,<span class="n
<p>Passing <code>noConflict</code> argument leaves untouched conflicting keys while importing into the context.</p>
+
<pre>
<span class="keyword">local</span> context = {each = <span class="number">1</span>}
-_.import(context, <span class="keyword">true</span>)
+M.import(context, <span class="keyword">true</span>)
<span class="global">print</span>(context.each) <span class="comment">-- =&gt; 1
</span>context.eachi({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},<span class="global">print</span>)
@@ -2342,7 +2875,7 @@ _.import(context, <span class="keyword">true</span>)
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
-<i style="float:right;">Last updated 2017-04-27 15:26:55 </i>
+<i style="float:right;">Last updated 2018-08-22 18:44:44 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 9dce2d3..bb3a38d 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -1,10 +1,11 @@
*Moses: a utility-belt library for functional programming in Lua*
__Moses__ is a Lua utility library which provides support for functional programming.
-It complements built-in Lua functions, making easier common operations on tables, arrays, lists, collections, objects, and a lot more.<br/>
-__Moses__ was deeply inspired by [Underscore.js](http://documentcloud.github.com/underscore/).
+It complements built-in Lua functions, making easier common operations on tables, arrays, lists, collections, objects, and a lot more.
+<br/>
+<br/>
-# <a name='TOC'>Table of Contents</a>
+# <a name='TOC'>Sections</a>
* [Adding *Moses* to your project](#adding)
@@ -14,23 +15,21 @@ __Moses__ was deeply inspired by [Underscore.js](http://documentcloud.github.com
* [Object functions](#object)
* [Chaining](#chaining)
* [Import](#import)
-
+<br/><br/>
# <a name='adding'>Adding *Moses* to your project</a>
Drop the file [moses.lua](http://github.com/Yonaba/Moses/blob/master/moses.lua) into your project and add it to your code with the *require* function:
```lua
-local _ = require ("moses")
+local M = require ("moses")
````
-*Note: Lua purists tend to use "\_" to design a "dummy variable". Here, the usage of this underscore is quite idiomatic and refers to the name [Underscore](http://documentcloud.github.com/underscore/), the JS library from which *Moses* takes inspiration*.
-
-*Moses*' provides a large set of functions that can be classified into four categories:
+*Moses* provides a large set of functions that can be classified into four categories:
-* __Table functions__, which are mostly meant for tables, i.e Lua tables which contains both an array-part and a hash-part,
-* __Array functions__, meant for array lists (or sequences),
-* __Utility functions__,
-* __Object functions__.
+* [__Table functions__](#table), which are mostly meant for tables, i.e Lua tables which contains both an array-part and a hash-part,
+* [__Array functions__](#array), meant for array lists (or sequences),
+* [__Utility functions__](#utility),
+* [__Object functions__](#object).
**[[⬆]](#TOC)**
@@ -38,198 +37,208 @@ local _ = require ("moses")
### clear (t)
-Clears a table. All its values becomes nil. It returns the passed-in table.
+Clears a table. All its values becomes nil. Returns the passed-in table.
```lua
-local t = _.clear({1,2,'hello',true}) -- => {}
+M.clear({1,2,'hello',true}) -- => {}
````
-### each (t, f, ...)
-*Aliases: `_.forEach`*.
+### each (t, f [, ...])
+*Aliases: `forEach`*.
-Iterates over each key-value pair in table.
+Iterates over each value-key pair in the passed-in table.
```lua
-_.each({1,2,3},print)
+M.each({4,2,1},print)
--- => 1 1
+-- => 4 1
-- => 2 2
--- => 3 3
+-- => 1 3
````
-The table can be map-like (array part and hash-part).
+The table can be map-like (both array part and hash part).
```lua
-_.each({one = 1, two = 2, three = 3},print)
+M.each({one = 1, two = 2, three = 3},print)
--- => one 1
--- => two 2
--- => three 3
+-- => 1 one
+-- => 2 two
+-- => 3 three
````
Can index and assign in an outer table or in the passed-in table:
```lua
t = {'a','b','c'}
-_.each(t,function(i,v)
+M.each(t,function(v,i)
t[i] = v:rep(2)
print(t[i])
end)
--- => 1 aa
--- => 2 bb
--- => 3 cc
+-- => aa
+-- => bb
+-- => cc
````
-### eachi (t, f, ...)
-*Aliases: `_.forEachi`*.
+### eachi (t, f [, ...])
+*Aliases: `forEachi`*.
-Iterates only on integer keys in a sparse array table.
+Iterates only on integer keys in an array table. It returns value-key pairs.
```lua
-_.eachi({1,2,3},print)
+M.eachi({4,2,1},print)
--- => 1 1
+-- => 4 1
-- => 2 2
--- => 3 3
+-- => 1 3
````
The given array can be sparse, or even have a hash-like part.
```lua
local t = {a = 1, b = 2, [0] = 1, [-1] = 6, 3, x = 4, 5}
-_.eachi(t,function(i,v)
- print(i,v)
-end)
+M.eachi(t,print)
--- => -1 6
--- => 0 1
--- => 1 3
--- => 2 5
+-- => 6 -1
+-- => 1 0
+-- => 3 1
+-- => 5 2
````
### at (t, ...)
-Collects all values at some specific keys and returns them in an array.
+Collects values at given keys and returns them in an array.
```lua
local t = {4,5,6}
-_.at(t,1,3) -- => "{4,6}"
+M.at(t,1,3) -- => "{4,6}"
local t = {a = 4, bb = true, ccc = false}
-_.at(t,'a', 'ccc') -- => "{4, false}"
+M.at(t,'a', 'ccc') -- => "{4, false}"
+````
+
+### adjust (t, key, f [, ...])
+
+Adjusts the value at a given key using a function or a value. In case `f` is a function, it should be prototyped `f(v, ...)`. It does not mutate the given table, but rather returns a new array.
+
+```lua
+local t = {1,2,3}
+M.adjust(t, 2, math.sin) -- => {1, 0.90929, 3}
+
+local v = {x = 1}
+ M.adjust(t, 'x', 4) -- => {x = 4}
````
-### count (t, value)
+In case the given `key` does not exist in `t`, it throws an error.
+
+### count (t [, val])
Counts the number of occurences of a given value in a table.
```lua
-_.count({1,1,2,3,3,3,2,4,3,2},1) -- => 2
-_.count({1,1,2,3,3,3,2,4,3,2},2) -- => 2
-_.count({1,1,2,3,3,3,2,4,3,2},3) -- => 4
-_.count({false, false, true},false) -- => 2
-_.count({false, false, true},true) -- => 1
+M.count({1,1,2,3,3,3,2,4,3,2},1) -- => 2
+M.count({1,1,2,3,3,3,2,4,3,2},2) -- => 3
+M.count({1,1,2,3,3,3,2,4,3,2},3) -- => 4
+M.count({false, false, true},false) -- => 2
+M.count({false, false, true},true) -- => 1
````
Returns the size of the list in case no value was provided.
```lua
-_.count({1,1,2,3,3}) -- => 5
+M.count({1,1,2,3,3}) -- => 5
````
-### countf (t, f, ...)
+### countf (t, f [, ...])
-Count the number of occurences of all values passing an iterator test.
+Counts the number of values passing an iterator test.
```lua
-_.countf({1,2,3,4,5,6}, function(i,v)
+M.countf({1,2,3,4,5,6}, function(v)
return v%2==0
end) -- => 3
-_.countf({print, pairs, os, assert, ipairs}, function(i,v)
+M.countf({print, pairs, os, assert, ipairs}, function(v)
return type(v)=='function'
end) -- => 4
````
-### cycle (t, n)
-*Aliases: `_.loop`*.
+### cycle (t [, n = 1])
+*Aliases: `loop`*.
-Returns a function which iterates on each key-value pair in a given table (similarly to `_.each`), except that it restarts iterating again `n` times.
+Returns a function which iterates on each value-key pair in a given table (similarly to `M.each`), except that it restarts iterating again `n` times.
If `n` is not provided, it defaults to 1.
```lua
local t = {'a','b','c'}
-for k,v in _.cycle(t, 2) do
- print(k,v)
+for v in M.cycle(t, 2) do
+ print(v)
end
--- => 1 'a'
--- => 2 'b'
--- => 3 'c'
--- => 1 'a'
--- => 2 'b'
--- => 3 'c'
+-- => 'a'
+-- => 'b'
+-- => 'c'
+-- => 'a'
+-- => 'b'
+-- => 'c'
````
Supports array-like tables and map-like tables.
```lua
local t = {x = 1, y = 2, z = 3}
-for k,v in _.cycle(t) do
- print(k,v)
+for v in M.cycle(t) do
+ print(v)
end
--- => y 2
--- => x 1
--- => z 3
+-- => 2
+-- => 1
+-- => 3
````
-### map (t, f, ...)
-*Aliases: `_.collect`*.
+### map (t, f [, ...])
+*Aliases: `collect`*.
-Executes a function on each key-value pairs.
+Executes a function on each value in a given array.
```lua
-_.map({1,2,3},function(i,v)
+M.map({1,2,3},function(v)
return v+10
end) -- => "{11,12,13}"
````
```lua
-_.map({a = 1, b = 2},function(k,v)
+M.map({a = 1, b = 2},function(v, k)
return k..v
end) -- => "{a = 'a1', b = 'b2'}"
````
-It also maps key-value pairs to key-value pairs
+It also maps both keys and values.
```lua
-_.map({a = 1, b = 2},function(k,v)
+M.map({a = 1, b = 2},function(v, k)
return k..k, v*2
end) -- => "{aa = 2, bb = 4}"
````
-### reduce (t, f, state)
-*Aliases: `_.inject`, `_.foldl`*.
+### reduce (t, f [, state = next(t)])
+*Aliases: `inject`, `foldl`*.
-Can sums all values in a table.
+Can sum all values in a table. In case `state` is not provided, it defaults to the first value in the given table `t`.
```lua
-_.reduce({1,2,3,4},function(memo,v)
- return memo+v
-end) -- => 10
+local function add(a,b) return a+b end
+M.reduce({1,2,3,4},add) -- => 10
````
Or concatenates all values.
-```lua
-_.reduce({'a','b','c','d'},function(memo,v)
- return memo..v
-end) -- => abcd
+```lua
+local function concat(a,b) return a..b end
+M.reduce({'a','b','c','d'},concat) -- => abcd
````
-### reduceby (t, f, state, pred, ...)
+### reduceby (t, f, pred [, state = next(t) [, ...]])
Reduces a table considering only values matching a predicate.
For example,let us define a set of values.
@@ -237,85 +246,87 @@ For example,let us define a set of values.
```lua
local val = {-1, 8, 0, -6, 3, -1, 7, 1, -9}
````
+
+And a reduction function which will add up values.
+
+```lua
+local function add(a,b) return a+b end
+````
+
We can also define some predicate functions.
```lua
-- predicate for negative values
-local function neg(_, v) return v<=0 end
+local function neg(v) return v<=0 end
-- predicate for positive values
-local function pos(_, v) return v>=0 end
+local function pos(v) return v>=0 end
````
-Then we can perform reduction considering only negative values :
+Then we can perform reduction considering only negative or positive values :
```lua
-_.reduceby(val, function(memo,v)
- return memo+v
-end, 0, neg) -- => -17
+M.reduceby(val, add, neg) -- => -17
+M.reduceby(val, add, pos) -- => 19
````
-Or only positive values :
+An initial state can be passed in.
```lua
-_.reduceby(val, function(memo,v)
- return memo+v
-end, 0, pos) -- => 19
+M.reduceby(val, add, neg, 17) -- => 0
+M.reduceby(val, add, pos, -19) -- => 0
````
-### reduceRight (t, f, state)
-*Aliases: `_.injectr`, `_.foldr`*.
+### reduceRight (t, f [, state = next(t)])
+*Aliases: `injectr`, `foldr`*.
-Similar to `_.reduce`, but performs from right to left.
+Similar to `M.reduce`, but performs from right to left.
```lua
local initial_state = 256
-_.reduceRight({1,2,4,16},function(memo,v)
- return memo/v
-end,initial_state) -- => 2
+local function div(a,b) return a/b end
+M.reduceRight({1,2,4,16},div,initial_state) -- => 2
````
-### mapReduce (t, f, state)
-*Aliases: `_.mapr`*.
+### mapReduce (t, f [, state = next(t)])
+*Aliases: `mapr`*.
Reduces while saving intermediate states.
```lua
-_.mapReduce({'a','b','c'},function(memo,v)
- return memo..v
-end) -- => "{'a', 'ab', 'abc'}"
+local function concat(a,b) return a..b end
+M.mapReduce({'a','b','c'},concat) -- => "{'a', 'ab', 'abc'}"
````
-### mapReduceRight (t, f, state)
-*Aliases: `_.maprr`*.
+### mapReduceRight (t, f [, state = next(t)])
+*Aliases: `maprr`*.
Reduces from right to left, while saving intermediate states.
```lua
-_.mapReduceRight({'a','b','c'},function(memo,v)
- return memo..v
-end) -- => "{'c', 'cb', 'cba'}"
+local function concat(a,b) return a..b end
+M.mapReduceRight({'a','b','c'},concat) -- => "{'c', 'cb', 'cba'}"
````
### include (t, value)
-*Aliases: `_.any`, `_.some`, `_.contains`*.
+*Aliases: `any`, `some`, `contains`*.
Looks for a value in a table.
```lua
-_.include({6,8,10,16,29},16) -- => true
-_.include({6,8,10,16,29},1) -- => false
+M.include({6,8,10,16,29},16) -- => true
+M.include({6,8,10,16,29},1) -- => false
local complex_table = {18,{2,{3}}}
local collection = {6,{18,{2,6}},10,{18,{2,{3}}},29}
-_.include(collection, complex_table) -- => true
+M.include(collection, complex_table) -- => true
````
Handles iterator functions.
```lua
local function isUpper(v) return v:upper()== v end
-_.include({'a','B','c'},isUpper) -- => true
+M.include({'a','B','c'},isUpper) -- => true
````
### detect (t, value)
@@ -323,12 +334,12 @@ _.include({'a','B','c'},isUpper) -- => true
Returns the index of a value in a table.
```lua
-_.detect({6,8,10,16},8) -- => 2
-_.detect({nil,true,0,true,true},false) -- => nil
+M.detect({6,8,10,16},8) -- => 2
+M.detect({nil,true,0,true,true},false) -- => nil
local complex_table = {18,{2,6}}
local collection = {6,{18,{2,6}},10,{18,{2,{3}}},29}
-_.detect(collection, complex_table) -- => 2
+M.detect(collection, complex_table) -- => 2
````
Handles iterator functions.
@@ -337,7 +348,7 @@ Handles iterator functions.
local function isUpper(v)
return v:upper()==v
end
-_.detect({'a','B','c'},isUpper) -- => 2
+M.detect({'a','B','c'},isUpper) -- => 2
````
### where (t, props)
@@ -345,94 +356,79 @@ _.detect({'a','B','c'},isUpper) -- => 2
Looks through a table and returns all the values that matches all of the key-value pairs listed in `props`.
```lua
-local tA = {a = 1, b = 2, c = 0}
-local tB = {a = 1, b = 4, c = 1}
-local tC = {a = 4, b = 4, c = 3}
-local tD = {a = 1, b = 2, c = 3}
-local found = _.where({tA, tB, tC, tD}, {a = 1})
-
--- => found = {tA, tB, tD}
-
-found = _.where({tA, tB, tC, tD}, {b = 4})
-
--- => found = {tB, tC}
-
-found = _.where({tA, tB, tC, tD}, {b = 4, c = 3})
-
--- => found = {tC}
+local items = {
+ {height = 10, weight = 8, price = 500},
+ {height = 10, weight = 15, price = 700},
+ {height = 15, weight = 15, price = 3000},
+ {height = 10, weight = 8, price = 3000},
+}
+M.where(items, {height = 10}) -- => {items[1], items[2], items[4]}
+M.where(items, {weight = 15}) -- => {items[2], items[3]}
+M.where(items, {prince = 3000}) -- => {items[3], items[4]}
+M.where(items, {height = 10, weight = 15, prince = 700}) -- => {items[2]}
````
### findWhere (t, props)
-Looks through a table and returns the first value that matches all of the key-value pairs listed in `props`.
+Looks through a table and returns the first value found that matches all of the key-value pairs listed in `props`.
```lua
local a = {a = 1, b = 2, c = 3}
local b = {a = 2, b = 3, d = 4}
local c = {a = 3, b = 4, e = 5}
-_.findWhere({a, b, c}, {a = 3, b = 4}) == c -- => true
+M.findWhere({a, b, c}, {a = 3, b = 4}) == c -- => true
````
-### select (t, f, ...)
-*Aliases: `_.filter`*.
+### select (t, f [, ...])
+*Aliases: `filter`*.
Collects values passing a validation test.
```lua
--- Even values
-_.select({1,2,3,4,5,6,7}, function(key,value)
- return (value%2==0)
-end) -- => "{2,4,6}"
+local function isEven(v) return v%2==0 end
+local function isOdd(v) return v%2~=0 end
--- Odd values
-_.select({1,2,3,4,5,6,7}, function(key,value)
- return (value%2~=0)
-end) -- => "{1,3,5,7}"
+M.select({1,2,3,4,5,6,7}, isEven) -- => "{2,4,6}"
+M.select({1,2,3,4,5,6,7}, isOdd) -- => "{1,3,5,7}"
````
-### reject (t, f, ...)
-*Aliases: `_.reject`*.
+### reject (t, f [, ...])
+*Aliases: `reject`*.
-Removes all values failing a validation test:
+Removes all values failing (returning false or nil) a validation test:
```lua
-_.reject({1,2,3,4,5,6,7}, function(key,value)
- return (value%2==0)
-end) -- => "{1,3,5,7}"
+local function isEven(v) return v%2==0 end
+local function isOdd(v) return v%2~=0 end
-_.reject({1,2,3,4,5,6,7}, function(key,value)
- return (value%2~=0)
-end) -- => "{2,4,6}"
+M.reject({1,2,3,4,5,6,7}, isEven) -- => "{1,3,5,7}"
+M.reject({1,2,3,4,5,6,7}, isOdd) -- => "{2,4,6}"
````
-### all (t, f, ...)
-*Aliases: `_.every`*.
+### all (t, f [, ...])
+*Aliases: `every`*.
Checks whether or not all elements pass a validation test.
```lua
-_.all({2,4,6}, function(key,value)
- return (value%2==0)
-end) -- => true
+local function isEven(v) return v%2==0 end
+M.all({2,4,6}, isEven) -- => true
````
-### invoke (t, method, ...)
+### invoke (t, method [, ...])
-Invokes a given function on each value in a table
+Invokes a given function on each value in a table.
```lua
-_.invoke({'a','bea','cdhza'},string.len) -- => "{1,3,5}"
+M.invoke({'a','bea','cdhza'},string.len) -- => "{1,3,5}"
````
Can reference the method of the same name in each value.
```lua
-local a = {}
-function a:call() return 'a' end
-local b, c, d = {}, {}, {}
-b.call, c.call, d.call = a.call, a.call, a.call
-
-_.invoke({a,b,c,d},'call') -- => "{'a','a','a','a'}"
+local a, b, c, d = {id = 'a'}, {id = 'b'}, {id = 'c'}, {id = 'd'}
+local function call(self) return self.id end
+M.invoke({a,b,c,d},call) -- => "{'a','b','c','d'}"
````
### pluck (t, property)
@@ -444,17 +440,17 @@ local peoples = {
{name = 'John', age = 23},{name = 'Peter', age = 17},
{name = 'Steve', age = 15},{age = 33}}
-_.pluck(peoples,'age') -- => "{23,17,15,33}"
-_.pluck(peoples,'name') -- => "{'John', 'Peter', 'Steve'}"
+M.pluck(peoples,'age') -- => "{23,17,15,33}"
+M.pluck(peoples,'name') -- => "{'John', 'Peter', 'Steve'}"
````
-### max (t, transform, ...)
+### max (t [, transform [, ...]])
Returns the maximum value in a collection.
```lua
-_.max {1,2,3} -- => 3
-_.max {'a','b','c'} -- => 'c'
+M.max {1,2,3} -- => 3
+M.max {'a','b','c'} -- => 'c'
````
Can take an iterator function to extract a specific property.
@@ -463,16 +459,16 @@ Can take an iterator function to extract a specific property.
local peoples = {
{name = 'John', age = 23},{name = 'Peter', age = 17},
{name = 'Steve', age = 15},{age = 33}}
-_.max(peoples,function(people) return people.age end) -- => 33
+M.max(peoples,function(people) return people.age end) -- => 33
````
-### min (t, transform, ...)
+### min (t [, transform [, ...]])
Returns the minimum value in a collection.
```lua
-_.min {1,2,3} -- => 1
-_.min {'a','b','c'} -- => 'a'
+M.min {1,2,3} -- => 1
+M.min {'a','b','c'} -- => 'a'
````
Can take an iterator function to extract a specific property.
@@ -481,16 +477,7 @@ Can take an iterator function to extract a specific property.
local peoples = {
{name = 'John', age = 23},{name = 'Peter', age = 17},
{name = 'Steve', age = 15},{age = 33}}
-_.min(peoples,function(people) return people.age end) -- => 15
-````
-
-### shuffle (t, seed)
-
-Shuffles a collection.
-
-```lua
-local list = _.shuffle {1,2,3,4,5,6} -- => "{3,2,6,4,1,5}"
-_.each(list,print)
+M.min(peoples,function(people) return people.age end) -- => 15
````
### same (a, b)
@@ -500,34 +487,34 @@ Tests whether or not all values in each of the passed-in tables exists in both t
```lua
local a = {'a','b','c','d'}
local b = {'b','a','d','c'}
-_.same(a,b) -- => true
+M.same(a,b) -- => true
b[#b+1] = 'e'
-_.same(a,b) -- => false
+M.same(a,b) -- => false
````
-### sort (t, comp)
+### sort (t [, comp = math.min])
Sorts a collection.
```lua
-_.sort({'b','a','d','c'}) -- => "{'a','b','c','d'}"
+M.sort({'b','a','d','c'}) -- => "{'a','b','c','d'}"
````
Handles custom comparison functions.
```lua
-_.sort({'b','a','d','c'}, function(a,b)
+M.sort({'b','a','d','c'}, function(a,b)
return a:byte() > b:byte()
end) -- => "{'d','c','b','a'}"
````
-### sortBy (t, transform, comp)
+### sortBy (t [, transform [, comp = math.min]])
Sorts items in a collection based on the result of running a transform function through every item in the collection.
```lua
-local r = _.sortBy({1,2,3,4,5}, math.sin)
+local r = M.sortBy({1,2,3,4,5}, math.sin)
print(table.concat(r,','))
-- => {5,4,3,1,2}
@@ -536,14 +523,14 @@ print(table.concat(r,','))
The transform function can also be a string name property.
```lua
-local people ={
+local people = {
{name = 'albert', age = 40},
{name = 'louis', age = 55},
{name = 'steve', age = 35},
{name = 'henry', age = 19},
}
-local r = _.sortBy(people, 'age')
-_.each(r, function(__,v) print(v.age, v.name) end)
+local r = M.sortBy(people, 'age')
+M.each(r, function(v) print(v.age, v.name) end)
-- => 19 henry
-- => 35 steve
@@ -551,18 +538,17 @@ _.each(r, function(__,v) print(v.age, v.name) end)
-- => 55 louis
````
-As seen above, the defaut comparison function is the '<' operator. For example, let us supply a different one to sort
-the list of people by decreasing age order :
+As seen above, the defaut comparison function is the '<' operator. For example, let us supply a different one to sort the list of people by decreasing age order :
```lua
-local people ={
+local people = {
{name = 'albert', age = 40},
{name = 'louis', age = 55},
{name = 'steve', age = 35},
{name = 'henry', age = 19},
}
-local r = _.sortBy(people, 'age', function(a,b) return a > b end)
-_.each(r, function(__,v) print(v.age, v.name) end)
+local r = M.sortBy(people, 'age', function(a,b) return a > b end)
+M.each(r, function(v) print(v.age, v.name) end)
-- => 55 louis
-- => 40 albert
@@ -570,36 +556,36 @@ _.each(r, function(__,v) print(v.age, v.name) end)
-- => 19 henry
````
-The `transform` function defaults to `_.indentity` and in that case, `_.sortBy` behaves like `_.sort`.
+The `transform` function defaults to `M.indentity` and in that case, `M.sortBy` behaves like `M.sort`.
```lua
-local r = _.sortBy({1,2,3,4,5})
+local r = M.sortBy({1,2,3,4,5})
print(table.concat(r,','))
-- => {1,2,3,4,5}
````
-### groupBy (t, iter, ...)
+### groupBy (t, iter [, ...])
Groups values in a collection depending on their return value when passed to a predicate test.
```lua
-_.groupBy({0,1,2,3,4,5,6},function(i,value)
- return value%2==0 and 'even' or 'odd'
-end) -- => "{odd = {1,3,5}, even = {0,2,4,6}}"
+M.groupBy({0,1,2,3,4,5,6},function(v)
+ return v%2==0 and 'even' or 'odd'
+end)
+-- => "{odd = {1,3,5}, even = {0,2,4,6}}"
-_.groupBy({0,'a',true, false,nil,b,0.5},function(i,value)
- return type(value)
-end) -- => "{number = {0,0.5}, string = {'a'}, boolean = {true, false}}"
+M.groupBy({0,'a',true, false,nil,b,0.5},type)
+-- => "{number = {0,0.5}, string = {'a'}, boolean = {true, false}}"
````
-### countBy (t, iter, ...)
+### countBy (t [, iter [, ...]])
Splits a table in subsets and provide the count for each subset.
```lua
-_.countBy({0,1,2,3,4,5,6},function(i,value)
- return value%2==0 and 'even' or 'odd'
+M.countBy({0,1,2,3,4,5,6},function(v)
+ return v%2==0 and 'even' or 'odd'
end) -- => "{odd = 3, even = 4}"
````
@@ -608,15 +594,15 @@ end) -- => "{odd = 3, even = 4}"
When given a table, provides the count for the very number of values in that table.
```lua
-_.size {1,2,3} -- => 3
-_.size {one = 1, two = 2} -- => 2
+M.size {1,2,3} -- => 3
+M.size {one = 1, two = 2} -- => 2
````
-When given a vararg list of argument, returns the count of these arguments.
+When given a vararg list of arguments, returns the count of these arguments.
```lua
-_.size(1,2,3) -- => 3
-_.size('a','b',{}, function() end) -- => 4
+M.size(1,2,3) -- => 3
+M.size('a','b',{}, function() end) -- => 4
````
### containsKeys (t, other)
@@ -624,9 +610,9 @@ _.size('a','b',{}, function() end) -- => 4
Checks whether a table has all the keys existing in another table.
```lua
-_.contains({1,2,3,4},{1,2,3}) -- => true
-_.contains({1,2,'d','b'},{1,2,3,5}) -- => true
-_.contains({x = 1, y = 2, z = 3},{x = 1, y = 2}) -- => true
+M.contains({1,2,3,4},{1,2,3}) -- => true
+M.contains({1,2,'d','b'},{1,2,3,5}) -- => true
+M.contains({x = 1, y = 2, z = 3},{x = 1, y = 2}) -- => true
````
### sameKeys (tA, tB)
@@ -634,22 +620,22 @@ _.contains({x = 1, y = 2, z = 3},{x = 1, y = 2}) -- => true
Checks whether both tables features the same keys:
```lua
-_.sameKeys({1,2,3,4},{1,2,3}) -- => false
-_.sameKeys({1,2,'d','b'},{1,2,3,5}) -- => true
-_.sameKeys({x = 1, y = 2, z = 3},{x = 1, y = 2}) -- => false
+M.sameKeys({1,2,3,4},{1,2,3}) -- => false
+M.sameKeys({1,2,'d','b'},{1,2,3,5}) -- => true
+M.sameKeys({x = 1, y = 2, z = 3},{x = 1, y = 2}) -- => false
````
**[[⬆]](#TOC)**
## <a name='array'>Array functions</a>
-### sample (array, n, seed)
+### sample (array [, n = 1 [, seed]])
Samples `n` values from array.
```lua
-local array = _.range(1,20)
-local sample = _.sample(array, 3)
+local array = M.range(1,20)
+local sample = M.sample(array, 3)
print(table.concat(sample,','))
-- => {12,11,15}
@@ -658,8 +644,8 @@ print(table.concat(sample,','))
`n` defaults to 1. In that case, a single value will be returned.
```lua
-local array = _.range(1,20)
-local sample = _.sample(array)
+local array = M.range(1,20)
+local sample = M.sample(array)
print(sample)
-- => 12
@@ -667,45 +653,55 @@ print(sample)
An optional 3rd argument `seed` can be passed for deterministic random sampling.
-### sampleProb (array, prob, seed)
+### sampleProb (array, prob [, seed])
Returns an array of values randomly selected from a given array.
In case `seed` is provided, it is used for deterministic sampling.
```lua
-local array = _.range(1,20)
-local sample = _.sampleProb(array, 0.2)
+local array = M.range(1,20)
+local sample = M.sampleProb(array, 0.2)
print(table.concat(sample,','))
-- => 5,11,12,15
-sample = _.sampleProb(array, 0.2, os.time())
+sample = M.sampleProb(array, 0.2, os.time())
print(table.concat(sample,','))
-- => 1,6,10,12,15,20 (or similar)
````
+### shuffle (array [, seed])
+
+Shuffles a given array.
+
+```lua
+local list = M.shuffle {1,2,3,4,5,6} -- => "{3,2,6,4,1,5}"
+M.each(list,print)
+````
+
### toArray (...)
Converts a vararg list of arguments to an array.
```lua
-_.toArray(1,2,8,'d','a',0) -- => "{1,2,8,'d','a',0}"
+M.toArray(1,2,8,'d','a',0) -- => "{1,2,8,'d','a',0}"
````
-### find (array, value, from)
+### find (array, value [, from = 1])
Looks for a value in a given array and returns the position of the first occurence.
```lua
-_.find({{4},{3},{2},{1}},{3}) -- => 2
+local value = {3}
+M.find({{4},{3},{2},{1}},value) -- => 2
````
It can also start the search at a specific position in the array:
```lua
-- search value 4 starting from index 3
-_.find({1,4,2,3,4,5},4,3) -- => 5
+M.find({1,4,2,3,4,5},4,3) -- => 5
````
### reverse (array)
@@ -713,74 +709,98 @@ _.find({1,4,2,3,4,5},4,3) -- => 5
Reverses an array.
```lua
-_.reverse({1,2,3,'d'}) -- => "{'d',3,2,1}"
+M.reverse({1,2,3,'d'}) -- => "{'d',3,2,1}"
````
-### fill (array, value, i, j)
+### fill (array, value [, i = 1 [, j = #array]])
Replaces all elements in a given array with a given value.
```lua
-local array = _.range(1,5)
-_.fill(array, 0) -- => {0,0,0,0,0}
+local array = M.range(1,5)
+M.fill(array, 0) -- => {0,0,0,0,0}
````
It can start replacing value at a specific index.
```lua
-local array = _.range(1,5)
-_.fill(array,0,3) -- => {1,2,0,0,0}
+local array = M.range(1,5)
+M.fill(array,0,3) -- => {1,2,0,0,0}
````
It can replace only values within a specific range.
```lua
-local array = _.range(1,5)
-_.fill(array,0,2,4) -- => {1,0,0,0,5}
+local array = M.range(1,5)
+M.fill(array,0,2,4) -- => {1,0,0,0,5}
````
In case the upper bound index i greather than the array size, it will enlarge the array.
```lua
-local array = _.range(1,5)
-_.fill(array,0,5,10) -- => {1,2,3,4,0,0,0,0,0,0}
+local array = M.range(1,5)
+M.fill(array,0,5,10) -- => {1,2,3,4,0,0,0,0,0,0}
+````
+
+### zeros (n)
+
+Returns an array of `n` zeros.
+
+```lua
+M.zeros(4) -- => {0,0,0,0}
+````
+
+### ones (n)
+
+Returns an array of `n` 1's.
+
+```lua
+M.ones(3) -- => {1,1,1}
````
-### selectWhile (array, f, ...
-*Aliases: `_.takeWhile`*.
+### vector (value, n)
+
+Returns an array of `n` times a given value.
+
+```lua
+M.vector(10, 4) -- => {10,10,10,10}
+````
+
+### selectWhile (array, f [, ...])
+*Aliases: `takeWhile`*.
Collects values as long as they pass a given test. Stops on the first non-passing test.
```lua
-_.selectWhile({2,4,5,8}, function(i,v)
+M.selectWhile({2,4,5,8}, function(v)
return v%2==0
end) -- => "{2,4}"
````
-### dropWhile (array, f, ...
-*Aliases: `_.rejectWhile`*.
+### dropWhile (array, f [, ...])
+*Aliases: `rejectWhile`*.
Removes values as long as they pass a given test. Stops on the first non-passing test.
```lua
-_.dropWhile({2,4,5,8}, function(i,v)
+M.dropWhile({2,4,5,8}, function(v)
return v%2==0
end) -- => "{5,8}"
````
-### sortedIndex (array, value, comp, sort)
+### sortedIndex (array, value [, comp = math.min [, sort = nil]])
Returns the index at which a value should be inserted to preserve order.
```lua
-_.sortedIndex({1,2,3},4) -- => 4
+M.sortedIndex({1,2,3},4) -- => 4
````
Can take a custom comparison functions.
```lua
local comp = function(a,b) return a<b end
-_.sortedIndex({-5,0,4,4},3,comp) -- => 3
+M.sortedIndex({-5,0,4,4},3,comp) -- => 3
````
### indexOf (array, value)
@@ -788,7 +808,7 @@ _.sortedIndex({-5,0,4,4},3,comp) -- => 3
Returns the index of a value in an array.
```lua
-_.indexOf({1,2,3},2) -- => 2
+M.indexOf({1,2,3},2) -- => 2
````
### lastIndexOf (array, value)
@@ -796,27 +816,27 @@ _.indexOf({1,2,3},2) -- => 2
Returns the index of the last occurence of a given value in an array.
```lua
-_.lastIndexOf({1,2,2,3},2) -- => 3
+M.lastIndexOf({1,2,2,3},2) -- => 3
````
-### findIndex (array, predicate, ...)
+### findIndex (array, predicate [, ...])
Returns the first index at which a predicate passes a truth test.
```lua
local array = {1,2,3,4,5,6}
-local function multipleOf3(__,v) return v%3==0 end
-_.findIndex(array, multipleOf3) -- => 3
+local function multipleOf3(v) return v%3==0 end
+M.findIndex(array, multipleOf3) -- => 3
````
-### findLastIndex (array, predicate, ...)
+### findLastIndex (array, predicate [, ...])
-Returns the last index at which a predicate passes a truth test.
+Returns the last index at which a predicate passes a truthy test.
```lua
local array = {1,2,3,4,5,6}
-local function multipleOf3(__,v) return v%3==0 end
-_.findLastIndex(array, multipleOf3) -- => 6
+local function multipleOf3(v) return v%3==0 end
+M.findLastIndex(array, multipleOf3) -- => 6
````
### addTop (array, ...)
@@ -825,7 +845,16 @@ Adds given values at the top of an array. The latter values bubbles at the top.
```lua
local array = {1}
-_.addTop(array,1,2,3,4) -- => "{4,3,2,1,1}"
+M.addTop(array,1,2,3,4) -- => "{4,3,2,1,1}"
+````
+
+### prepend (array, ...)
+
+Adds given values at the top of an array, preserving the order at which elements are passed-in.
+
+```lua
+local array = {'old_val'}
+M.prepend(array,1,2,3,4) -- => "{1,2,3,4,'old_val'}"
````
### push (array, ...)
@@ -834,104 +863,109 @@ Adds given values at the end of an array.
```lua
local array = {1}
-_.push(array,1,2,3,4) -- => "{1,1,2,3,4}"
+M.push(array,1,2,3,4) -- => "{1,1,2,3,4}"
````
-### pop (array, n)
-*Aliases: `_.shift`*.
+### shift (array [, n = 1])
+*Aliases: `pop`*.
Removes and returns the first value in an array.
```lua
local array = {1,2,3}
-local pop = _.pop(array) -- => "pop = 1", "array = {2,3}"
+local shift = M.shift(array) -- => "shift = 1", "array = {2,3}"
````
+If `n` is supplied, returns `n` values.
-### unshift (array, n)
+```lua
+local array = {1,2,3,4,5}
+local a, b = M.shift(array, 2) -- => "a = 1, b = 2", "array = {3,4,5}"
+````
+
+### unshift (array [, n = 1])
Removes and returns the last value in an array.
```lua
local array = {1,2,3}
-local value = _.unshift(array) -- => "value = 3", "array = {1,2}"
+local value = M.unshift(array) -- => "value = 3", "array = {1,2}"
````
### pull (array, ...)
-*Aliases: `_.remove`*.
+*Aliases: `remove`*.
Removes all provided values from a given array.
```lua
-_.pull({1,2,1,2,3,4,3},1,2,3) -- => "{4}"
+M.pull({1,2,1,2,3,4,3},1,2,3) -- => "{4}"
````
-### removeRange (array, start, finish)
-*Aliases: `_.rmRange`, `_.chop`*.
+### removeRange (array [, start = 1 [, finish = #array]])
+*Aliases: `rmRange`, `M.chop`*.
Trims out all values index within a range.
```lua
local array = {1,2,3,4,5,6,7,8,9}
-_.removeRange(array, 3,8) -- => "{1,2,9}"
+M.removeRange(array, 3,8) -- => "{1,2,9}"
````
-### chunk (array, f, ...)
+### chunk (array, f [, ...])
-Iterates over an array aggregating consecutive values in subsets tables, on the basis of the return
-value of `f(key,value,...)`. Consecutive elements which return the same value are aggregated together.
+Iterates over an array aggregating consecutive values in subsets tables, on the basis of the return value of `f(v, k, ...)`. Consecutive elements which return the same value are chunked together.
```lua
local t = {1,1,2,3,3,4}
-_.chunk(t, function(k,v) return v%2==0 end) -- => "{{1,1},{2},{3,3},{4}}"
+M.chunk(t, function(v) return v%2==0 end) -- => "{{1,1},{2},{3,3},{4}}"
````
-### slice (array, start, finish)
-*Aliases: `_.sub`*.
+### slice (array [, start = 1 [, finish = #array]])
+*Aliases: `sub`*.
Slices and returns a part of an array.
```lua
local array = {1,2,3,4,5,6,7,8,9}
-_.slice(array, 3,6) -- => "{3,4,5,6}"
+M.slice(array, 3,6) -- => "{3,4,5,6}"
````
-### first (array, n)
-*Aliases: `_.head`, `_.take`*.
+### first (array [, n = 1])
+*Aliases: `head`, `M.take`*.
Returns the first N elements in an array.
```lua
local array = {1,2,3,4,5,6,7,8,9}
-_.first(array,3) -- => "{1,2,3}"
+M.first(array,3) -- => "{1,2,3}"
````
-### initial (array, n)
+### initial (array [, n = #array])
Excludes the last N elements in an array.
```lua
local array = {1,2,3,4,5,6,7,8,9}
-_.initial(array,5) -- => "{1,2,3,4}"
+M.initial(array,5) -- => "{1,2,3,4}"
````
-### last (array, n)
-*Aliases: `_.skip`*.
+### last (array [, n = #array])
+*Aliases: `skip`*.
Returns the last N elements in an array.
```lua
local array = {1,2,3,4,5,6,7,8,9}
-_.last(array,3) -- => "{7,8,9}"
+M.last(array,3) -- => "{7,8,9}"
````
-### rest (array, index)
-*Aliases: `_.tail`*.
+### rest (array [, index = 1])
+*Aliases: `tail`*.
-Trims out all values indexed before *index*.
+Returns all values after *index*, including the given *index* itself.
```lua
local array = {1,2,3,4,5,6,7,8,9}
-_.rest(array,6) -- => "{6,7,8,9}"
+M.rest(array,6) -- => "{6,7,8,9}"
````
### nth (array, index)
@@ -940,7 +974,7 @@ Returns the value at *index*.
```lua
local array = {1,2,3,4,5,6}
-_.nth(array,3) -- => "3"
+M.nth(array,3) -- => "3"
````
### compact (array)
@@ -948,31 +982,31 @@ _.nth(array,3) -- => "3"
Trims out all falsy values.
```lua
-_.compact {a,'aa',false,'bb',true} -- => "{'aa','bb',true}"
+M.compact {a,'aa',false,'bb',true} -- => "{'aa','bb',true}"
````
-### flatten (array, shallow)
+### flatten (array [, shallow = false])
Flattens a nested array.
```lua
-_.flatten({1,{2,3},{4,5,{6,7}}}) -- => "{1,2,3,4,5,6,7}"
+M.flatten({1,{2,3},{4,5,{6,7}}}) -- => "{1,2,3,4,5,6,7}"
````
-When given arg "shallow", flatten only at the first level.
+When given arg `shallow`, flatten only at the first level.
```lua
-_.flatten({1,{2},{{3}}},true) -- => "{1,{2},{{3}}}"
+M.flatten({1,{2},{{3}}},true) -- => "{1,{2},{{3}}}"
````
### difference (array, array2)
-*Aliases: `_.without`, `_.diff`*.
+*Aliases: `without`, `diff`*.
Returns values in the given array not present in a second array.
```lua
local array = {1,2,'a',4,5}
-_.difference(array,{1,'a'}) -- => "{2,4,5}"
+M.difference(array,{1,'a'}) -- => "{2,4,5}"
````
### union (...)
@@ -983,7 +1017,7 @@ Produces a duplicate-free union of all passed-in arrays.
local A = {'a'}
local B = {'a',1,2,3}
local C = {2,10}
-_.union(A,B,C) -- => "{'a',1,2,3,10}"
+M.union(A,B,C) -- => "{'a',1,2,3,10}"
````
### intersection (array, ...)
@@ -994,48 +1028,65 @@ Returns the intersection (common-part) of all passed-in arrays:
local A = {'a'}
local B = {'a',1,2,3}
local C = {2,10,1,'a'}
-_.intersection(A,B,C) -- => "{'a',2,1}"
+M.intersection(A,B,C) -- => "{'a',2,1}"
````
### symmetricDifference (array, array2)
-*Aliases: `_.symdiff`,`_.xor`*.
+*Aliases: `symdiff`,`xor`*.
Returns values in the first array not present in the second and also values in the second array not present in the first one.
```lua
local array = {1,2,3}
local array2 = {1,4,5}
-_.symmetricDifference(array, array2) -- => "{2,3,4,5}"
+M.symmetricDifference(array, array2) -- => "{2,3,4,5}"
````
### unique (array)
-*Aliases: `_.uniq`*.
+*Aliases: `uniq`*.
Makes an array duplicate-free.
```lua
-_.unique {1,1,2,2,3,3,4,4,4,5} -- => "{1,2,3,4,5}"
+M.unique {1,1,2,2,3,3,4,4,4,5} -- => "{1,2,3,4,5}"
````
### isunique (array)
-*Aliases: `_.isuniq`*.
+*Aliases: `isuniq`*.
Checks if a given array contains no duplicate value.
```lua
-_.isunique({1,2,3,4,5}) -- => true
-_.isunique({1,2,3,4,4}) -- => false
+M.isunique({1,2,3,4,5}) -- => true
+M.isunique({1,2,3,4,4}) -- => false
````
### zip (...)
-*Aliases: `_.transpose`*.
+*Aliases: `transpose`*.
Zips values from different arrays, on the basis on their common keys.
```lua
local names = {'Bob','Alice','James'}
local ages = {22, 23}
-_.zip(names,ages) -- => "{{'Bob',22},{'Alice',23},{'James'}}"
+M.zip(names,ages) -- => "{{'Bob',22},{'Alice',23},{'James'}}"
+````
+
+### zipWith (f, ...)
+*Aliases: `transposeWith`*.
+
+Merges values using a given function. Only values indexed with the same key in the given arrays are merged in the same subset.
+Function `f` is used to combine values.
+
+```lua
+local names = {'Bob','Alice','James'}; local ages = {22, 23, 25}
+local function introduce(name, age) return 'I am '..name..' and I am '..age..' years old.' end
+local t = M.zipWith(introduce,names,ages)
+-- => {
+-- => 'I am Bob and I am 22 years old.'
+-- => 'I am Alice and I am 23 years old.'
+-- => 'I am James and I am 25 years old.'
+-- => }
````
### append (array, other)
@@ -1043,7 +1094,7 @@ _.zip(names,ages) -- => "{{'Bob',22},{'Alice',23},{'James'}}"
Appends two arrays.
```lua
-_.append({1,2,3},{'a','b'}) -- => "{1,2,3,'a','b'}"
+M.append({1,2,3},{'a','b'}) -- => "{1,2,3,'a','b'}"
````
### interleave (...)
@@ -1053,35 +1104,43 @@ Interleaves values from passed-in arrays.
```lua
t1 = {1, 2, 3}
t2 = {'a', 'b', 'c'}
-_.interleave(t1, t2) -- => "{1,'a',2,'b',3,'c'}"
+M.interleave(t1, t2) -- => "{1,'a',2,'b',3,'c'}"
````
-### interpose (value, array)
+### interpose (array, value)
+*Aliases: `intersperce`*.
Interposes a value between consecutive values in an arrays.
```lua
-_.interleave('a', {1,2,3}) -- => "{1,'a',2,'a',3}"
+M.interleave('a', {1,2,3}) -- => "{1,'a',2,'a',3}"
````
-### range (...)
+### range ([from [, to [, step]]])
Generates an arithmetic sequence.
```lua
-_.range(1,4) -- => "{1,2,3,4}"
+M.range(1,4) -- => "{1,2,3,4}"
````
-In case a single value is provided, it generates a sequence from 0 to that value.
+In case a single value is provided, it generates a sequence from 1 to that value.
````
-_.range(3) -- => "{0,1,2,3}"
+M.range(3) -- => "{1,2,3}"
````
The incremental step can also be provided as third argument.
```lua
-_.range(0,2,0.7) -- => "{0,0.7,1.4}"
+M.range(0,2,0.7) -- => "{0,0.7,1.4}"
+````
+
+It also handles negative progressions.
+
+```lua
+M.range(-5) -- => "{-1,-2,-3,-4,-5}"
+M.range(5,1) -- => "{5,4,3,2,1}"
````
### rep (value, n)
@@ -1089,17 +1148,25 @@ _.range(0,2,0.7) -- => "{0,0.7,1.4}"
Generates a list of n repetitions of a value.
```lua
-_.rep(4,3) -- => "{4,4,4}"
+M.rep(4,3) -- => "{4,4,4}"
````
-### partition (array, n, pad)
-*Aliases: `_.part`*.
+### powerset (array)
+
+Returns the powerset of an array.
+
+```lua
+M.powerset {1,2,3} -- => "{{1},{2},{3},{1,2},{2,3},{1,2,3}}"
+````
+
+### partition (array [, n = 1 [, pad]])
+*Aliases: `part`*.
Returns an iterator function for partitions of a given array.
```lua
local t = {1,2,3,4,5,6}
-for p in _.partition(t,2) do
+for p in M.partition(t,2) do
print(table.concat(p, ','))
end
@@ -1108,7 +1175,7 @@ end
-- => 5,6
local t = {1,2,3,4,5,6}
-for p in _.partition(t,4) do
+for p in M.partition(t,4) do
print(table.concat(p, ','))
end
@@ -1120,7 +1187,7 @@ In case the last partition has less elements than desired, a 3rd argument can be
```lua
local t = {1,2,3,4,5,6}
-for p in _.partition(t,4,0) do
+for p in M.partition(t,4,0) do
print(table.concat(p, ','))
end
@@ -1128,13 +1195,13 @@ end
-- => 5,6,0,0
````
-### sliding (array, n, pad)
+### overlapping (array [, n = 2 [, pad]])
Returns an iterator function which provides overlapping subsequences of a given array.
```lua
local t = {1,2,3,4,5,6,7}
-for p in _.sliding(t,3) do
+for p in M.overlapping(t,3) do
print(table.concat(p,','))
end
@@ -1142,14 +1209,14 @@ end
-- => 3,4,5
-- => 5,6,7
-for p in _.sliding(t,4) do
+for p in M.overlapping(t,4) do
print(table.concat(p,','))
end
-- => 1,2,3,4
-- => 4,5,6,7
-for p in _.sliding(t,5) do
+for p in M.overlapping(t,5) do
print(table.concat(p,','))
end
@@ -1161,7 +1228,7 @@ In case the last subsequence wil not match the exact desired length, it can be a
```lua
local t = {1,2,3,4,5,6,7}
-for p in _.sliding(t,5,0) do
+for p in M.overlapping(t,5,0) do
print(table.concat(p,','))
end
@@ -1169,14 +1236,53 @@ end
-- => 5,6,7,0,0
````
+### aperture (array [, n = 2])
+*Aliases: `sliding`*.
+
+Returns an iterator function which provides sliding partitions of a given array.
+
+```lua
+local t = {1,2,3,4,5}
+for p in M.aperture(t,4) do
+ print(table.concat(p,','))
+end
+
+-- => 1,2,3,4
+-- => 2,3,4,5
+
+for p in M.aperture(t,3) do
+ print(table.concat(p,','))
+end
+
+-- => 1,2,3
+-- => 2,3,4
+-- => 3,4,5
+````
+
+### pairwise (array)
+
+Iterator returning sliding pairs of an array.
+
+```lua
+local t = M.range(5)
+for p in pairwise(t) do
+ print(table.concat(p,','))
+end
+
+-- => 1,2
+-- => 2,3
+-- => 3,4
+-- => 4,5
+````
+
### permutation (array)
-*Aliases: `_.perm`*.
+*Aliases: `perm`*.
Returns an iterator function for permutations of a given array.
```lua
t = {'a','b','c'}
-for p in _.permutation(t) do
+for p in M.permutation(t) do
print(table.concat(p))
end
@@ -1189,21 +1295,63 @@ end
````
### invert (array)
-*Aliases: `_.mirror`*.
+*Aliases: `mirror`*.
Switches <tt>key-value</tt> pairs:
```lua
-_.invert {'a','b','c'} -- => "{a=1, b=2, c=3}"
+M.invert {'a','b','c'} -- => "{a=1, b=2, c=3}"
````
-### concat (array, sep, i, j)
-*Aliases: `_.join`*.
+### concat (array [, sep = '' [, i = 1 [, j = #array]]])
+*Aliases: `join`*.
Concatenates a given array values:
```lua
-_.concat({'a',1,0,1,'b'}) -- => 'a101b'
+M.concat({'a',1,0,1,'b'}) -- => 'a101b'
+````
+
+### xprod (array, array2)
+
+Returns all possible pairs built from given arrays.
+
+```lua
+local t = M.xprod({1,2},{'a','b'})
+-- => {{1,'a'},{1,'b'},{2,'a'},{2,'b'}}
+````
+
+### sum (array)
+
+Returns the sum of array values.
+
+```lua
+M.sum({1,2,3,4,5}) -- => 15
+````
+
+### product (array)
+
+Returns the product of array values.
+
+```lua
+M.product({1,2,3,4,5}) -- => 120
+````
+
+### mean (array)
+
+Returns the mean of array values.
+
+```lua
+M.mean({1,2,3,4,5}) -- => 3
+````
+
+### median (array)
+
+Returns the median of array values.
+
+```lua
+M.median({1,2,3,4,5}) -- => 3
+M.median({1,2,3,4}) -- => 2.5
````
**[[⬆]](#TOC)**
@@ -1215,7 +1363,7 @@ _.concat({'a',1,0,1,'b'}) -- => 'a101b'
The no-operation function. Takes nothing, returns nothing. It is being used internally.
```lua
-_.noop() -- => nil
+M.noop() -- => nil
````
### identity (value)
@@ -1224,9 +1372,9 @@ Returns the passed-in value. <br/>
This function is internally used as a default transformation function.
```lua
-_.identity(1)-- => 1
-_.identity(false) -- => false
-_.identity('hello!') -- => 'hello!'
+M.identity(1)-- => 1
+M.identity(false) -- => false
+M.identity('hello!') -- => 'hello!'
````
### constant (value)
@@ -1234,14 +1382,27 @@ _.identity('hello!') -- => 'hello!'
Creates a constant function. This function will continuously yield the same output.
```lua
-local pi = _.constant(math.pi)
+local pi = M.constant(math.pi)
pi(1) -- => 3.1415926535898
pi(2) -- => 3.1415926535898
pi(math.pi) -- => 3.1415926535898
````
-### memoize (f, hash)
-*Aliases: `_.cache`*.
+### applySpec (specs)
+
+Returns a function which applies `specs` on args. This function will produce an object having the same structure than `specs` by mapping each property to the result of calling its associated function with the supplied arguments.
+
+```lua
+local stats = M.applySpec({
+ min = function(...) return math.min(...) end,
+ max = function(...) return math.max(...) end,
+})
+
+stats(5,4,10,1,8) -- => {min = 1, max = 10}
+````
+
+### memoize (f [, hash])
+*Aliases: `cache`*.
Memoizes a slow-running function. It caches the result for a specific input, so that the next time the function is called with the same input, it will lookup the result in its cache, instead of running again the function body.
@@ -1249,17 +1410,39 @@ Memoizes a slow-running function. It caches the result for a specific input, so
local function fibonacci(n)
return n < 2 and n or fibonacci(n-1)+fibonacci(n-2)
end
-local mem_fibonacci = _.memoize(fibonacci)
+local mem_fibonacci = M.memoize(fibonacci)
fibonacci(20) -- => 6765 (but takes some time)
mem_fibonacci(20) -- => 6765 (takes less time)
````
+Can take a `hash` function as an optional arg to evaluate unique keys depending on the inputs when caching intermediate results.
+
+```lua
+local function hash(a) return (a^13) end
+local function fact(a)
+ return a <= 1 and 1 or a*fact(a-1)
+end
+local mfact = M.memoize(fact,hash)
+mfact(20) -- => 6765
+````
+
+### unfold (f, seed)
+
+Builds a list from a seed value. Accepts an iterator function, which returns either nil to stop iteration or two values : the value to add to the list of results and the seed to be used in the next call to the iterator function.
+
+```lua
+local function f(v)
+ if v < 100 then return v, v * 2 end
+end
+local t = M.unfold(f, 10) -- => {10,20,40,80}
+````
+
### once (f)
Produces a function that runs only once. Successive calls to this function will still yield the same input.
```lua
-local sq = _.once(function(a) return a*a end)
+local sq = M.once(function(a) return a*a end)
sq(1) -- => 1
sq(2) -- => 1
sq(3) -- => 1
@@ -1273,7 +1456,7 @@ Returns a version of `f` that will run no more than `count` times. Next calls wi
```lua
local function greet(someone) return 'hello '..someone end
-local greetOnly3people = _.before(greet, 3)
+local greetOnly3people = M.before(greet, 3)
greetOnly3people('John') -- => 'hello John'
greetOnly3people('Moe') -- => 'hello Moe'
greetOnly3people('James') -- => 'hello James'
@@ -1286,7 +1469,7 @@ greetOnly3people('Allan') -- => 'hello James'
Produces a function that will respond only after a given number of calls.
```lua
-local f = _.after(_.identity,3)
+local f = M.after(M.identity,3)
f(1) -- => nil
f(2) -- => nil
f(3) -- => 3
@@ -1301,7 +1484,7 @@ Composes functions. Each function consumes the return value of the one that foll
local function f(x) return x^2 end
local function g(x) return x+1 end
local function h(x) return x/2 end
-local compositae = _.compose(f,g,h)
+local compositae = M.compose(f,g,h)
compositae(10) -- => 36
compositae(20) -- => 121
````
@@ -1314,8 +1497,8 @@ Pipes a value through a series of functions.
local function f(x) return x^2 end
local function g(x) return x+1 end
local function h(x) return x/2 end
-_.pipe(10,f,g,h) -- => 36
-_.pipe(20,f,g,h) -- => 121
+M.pipe(10,f,g,h) -- => 36
+M.pipe(20,f,g,h) -- => 121
````
### complement (f)
@@ -1323,11 +1506,11 @@ _.pipe(20,f,g,h) -- => 121
Returns a function which returns the logical complement of a given function.
```lua
-_.complement(function() return true end)() -- => false
+M.complement(function() return true end)() -- => false
````
### juxtapose (value, ...)
-*Aliases: `_.juxt`*.
+*Aliases: `juxt`*.
Calls a sequence of functions with the same input.
@@ -1335,7 +1518,7 @@ Calls a sequence of functions with the same input.
local function f(x) return x^2 end
local function g(x) return x+1 end
local function h(x) return x/2 end
-_.juxtapose(10, f, g, h) -- => 100, 11, 5
+M.juxtapose(10, f, g, h) -- => 100, 11, 5
````
### wrap (f, wrapper)
@@ -1344,7 +1527,7 @@ Wraps a function inside a wrapper. Allows the wrapper to execute code before and
```lua
local greet = function(name) return "hi: " .. name end
-local greet_backwards = _.wrap(greet, function(f,arg)
+local greet_backwards = M.wrap(greet, function(f,arg)
return f(arg) ..'\nhi: ' .. arg:reverse()
end)
greet_backwards('John')
@@ -1353,13 +1536,13 @@ greet_backwards('John')
-- => hi: nhoJ
````
-### times (n, iter, ...)
+### times (iter [, n [, ...]])
Calls a given function `n` times.
```lua
local f = ('Lua programming'):gmatch('.')
-_.times(3,f) -- => {'L','u','a'}
+M.times(f, 3) -- => {'L','u','a'}
````
### bind (f, v)
@@ -1367,7 +1550,7 @@ _.times(3,f) -- => {'L','u','a'}
Binds a value to be the first argument to a function.
```lua
-local sqrt2 = _.bind(math.sqrt,2)
+local sqrt2 = M.bind(math.sqrt,2)
sqrt2() -- => 1.4142135623731
````
@@ -1376,7 +1559,7 @@ sqrt2() -- => 1.4142135623731
Binds a value to be the second argument to a function.
```lua
-local last2 = _.bind(_.last,2)
+local last2 = M.bind(M.last,2)
last2({1,2,3,4,5,6}) -- => {5,6}
````
@@ -1386,12 +1569,12 @@ Binds a variable number of values to be the first arguments to a function.
```lua
local function out(...) return table.concat {...} end
-local out = _.bindn(out,'OutPut',':',' ')
+local out = M.bindn(out,'OutPut',':',' ')
out(1,2,3) -- => OutPut: 123
out('a','b','c','d') -- => OutPut: abcd
````
-### bindAll (obj, ...)
+### bindall (obj, ...)
Binds methods to object. As such, when calling any of these methods, they will receive object as a first argument.
@@ -1401,7 +1584,7 @@ local window = {
setName = function(w,name) w.name = name end,
getName = function(w) return w.name end,
}
-window = _.bindAll(window, 'setPos', 'setName', 'getName')
+window = M.bindall(window, 'setPos', 'setName', 'getName')
window.setPos(10,15)
print(window.x, window.y) -- => 10,15
@@ -1411,50 +1594,101 @@ print(window.name) -- => 'fooApp'
print(window.getName()) -- => 'fooApp'
````
-### uniqueId (template, ...)
-*Aliases: `_.uid`*.
+### cond (conds)
+
+Returns a function which iterate over an array list of conditions. It invokes each predicate, passing it given values. It returns the value of the corresponding function of the first predicate to return a non-nil value
+
+```lua
+local multipleOf = M.cond({
+ {function(v) return v%2==0 end, function(v) return v..' is multiple of 2' end},
+ {function(v) return v%3==0 end, function(v) return v..' is multiple of 3' end},
+ {function(v) return v%5==0 end, function(v) return v..' is multiple of 5' end},
+ {function() return true end, function(v) return 'could not find an answer for '..v end}
+})
+for i = 15, 20 do
+ print(multipleOf(i))
+end
+
+-- => 15 is multiple of 3
+-- => 16 is multiple of 2
+-- => could not find an answer for 17
+-- => 18 is multiple of 2
+-- => could not find an answer for 19
+-- => 20 is multiple of 2
+````
+
+### uniqueId ([template [, ...]])
+*Aliases: `uid`*.
Returns an unique integer ID.
```lua
-_.uniqueId() -- => 1
+M.uniqueId() -- => 1
````
Can handle string templates for formatted output.
```lua
-_.uniqueId('ID%s') -- => 'ID2'
+M.uniqueId('ID%s') -- => 'ID2'
````
Or a function, for the same purpose.
```lua
local formatter = function(ID) return '$'..ID..'$' end
-_.uniqueId(formatter) -- => '$ID1$'
+M.uniqueId(formatter) -- => '$ID1$'
````
-### iterator(f, x)
-*Aliases: `_.iter`*.
+### iterator(f, value [, n])
+*Aliases: `iter`*.
-Returns an iterator function which constinuously applies a function `f` onto an input `x`.
-For example, let us go through the powers of two.
+Returns an iterator function which constinuously applies a function `f` onto an input `value`.
+For example, let us go through the powers of two using `iterator`.
```lua
local function po2(x) return x*2 end
-local function iter_po2 = _.iterator(po2, 1)
+local function iter_po2 = M.iterator(po2, 1)
iter_po2() -- => 2
iter_po2() -- => 4
iter_po2() -- => 8
````
+if `n` is supplied, it will run at maximum `n` times.
+
+```lua
+local function po2(x) return x*2 end
+local function iter_po2 = M.iterator(po2, 1, 3)
+iter_po2() -- => 2
+iter_po2() -- => 4
+iter_po2() -- => 8
+iter_po2() -- => nil
+````
+
### array (...)
+*Aliases: `tabulate`*.
Iterates a given iterator function and returns its values packed in an array.
```lua
local text = 'letters'
local chars = string.gmatch(text, '.')
-local letters = _.array(chars) -- => {'l','e','t','t','e','r','s'}
+local letters = M.array(chars) -- => {'l','e','t','t','e','r','s'}
+````
+
+### castArray (value)
+
+Casts the passed-in value to an array containing the value itself.
+
+```lua
+M.castArray(true) -- => {true}
+M.castArray(2) -- => {2}
+````
+
+It leaves the given value untouched in case it is already a table.
+
+```lua
+local t = {1}
+print(M.castArray(t) == t) -- => true
````
### flip (f)
@@ -1463,17 +1697,70 @@ Creates a function of `f` with arguments flipped in reverse order.
```lua
local function f(...) return table.concat({...}) end
-local flipped = _.flip(f)
+local flipped = M.flip(f)
flipped('a','b','c') -- => 'cba'
````
+### nthArg(n)
+
+Returns a function that gets the nth argument.
+
+```lua
+local f = M.nthArg(3)
+f('a','b','c') -- => 'c'
+````
+
+If n is negative, the nth argument from the end is returned.
+
+```lua
+local f = M.nthArg(-2)
+f('a','b','c') -- => 'b'
+````
+
+### unary (f)
+
+Returns a function which accepts up to one argument. It ignores any additional arguments.
+
+```lua
+local f = M.unary(function (...) return ... end)
+f('a') - ==> 'a'
+f('a','b','c') -- => 'a'
+````
+
+### ary (f [, n = 1])
+*Aliases: `nAry`*.
+
+Returns a function which accepts up to `n` args. It ignores any additional arguments.
+
+```lua
+local f = M.ary(function (...) return ... end, 2)
+f(1,2) - ==> 1,2
+f(1,2,3,4) -- => 1,2
+````
+
+If `n` is not given, it defaults to `1`.
+
+```lua
+local f = M.unary(function (...) return ... end)
+f('a','b','c') -- => 'a'
+````
+
+### rearg (f, indexes)
+
+Returns a function which runs with arguments arranged according to given `indexes`.
+
+```lua
+local f = M.rearg(function (...) return ... end, {5,4,3,2,1})
+f('a','b','c','d','e') -- => 'e','d','c','b','a'
+````
+
### over (...)
Creates a function that invokes a set of transforms with the arguments it receives.<br/>
One can use use for example to get the tuple of min and max values from a set of values
```lua
-local minmax = _.over(math.min, math.max)
+local minmax = M.over(math.min, math.max)
minmax(5,10,12,4,3) -- => {3,12}
````
@@ -1496,7 +1783,7 @@ local function allpositive(...)
return true
end
-local allok = _.overEvery(alleven, allpositive)
+local allok = M.overEvery(alleven, allpositive)
allok(2,4,-1,8) -- => false
allok(10,3,2,6) -- => false
@@ -1522,7 +1809,7 @@ local function allpositive(...)
return true
end
-local anyok = _.overSome(alleven,allpositive)
+local anyok = M.overSome(alleven,allpositive)
anyok(2,4,-1,8) -- => false
anyok(10,3,2,6) -- => true
@@ -1537,7 +1824,7 @@ Creates a function that invokes `f` with its arguments transformed
local function f(x, y) return x, y end
local function triple(x) retun x*3 end
local function square(x) retun x^2 end
-local new_f = _.overArgs(f, triple, square)
+local new_f = M.overArgs(f, triple, square)
new_f(1,2) -- => 3, 4
new_f(10,10) -- => 30, 100
@@ -1549,19 +1836,31 @@ In case the number of arguments is greater than the number of transforms, the re
local function f(x, y, z) return x, y, z end
local function triple(x) retun x*3 end
local function square(x) retun x^2 end
-local new_f = _.overArgs(f, triple, square)
+local new_f = M.overArgs(f, triple, square)
new_f(1,2,3) -- => 3, 4, 3
new_f(10,10,10) -- => 30, 100, 10
````
+### converge (f, g, h)
+
+Converges two functions into one.
+
+```lua
+local function pow2(x) return x*x end
+local function pow3(x) return x*x*x end
+local function sum(a,b) return a+b end
+local poly = M.converge(sum, pow2, pow3)
+poly(5) -- => 150 (ie. 5*5 + 5*5*5)
+````
+
### partial (f, ...)
Partially apply a function by filling in any number of its arguments.
```lua
local function diff(a, b) return a - b end
-local diffFrom20 = _.partial(diff, 20) -- arg 'a' will be 20 by default
+local diffFrom20 = M.partial(diff, 20) -- arg 'a' will be 20 by default
diffFrom20(5) -- => 15
````
@@ -1569,23 +1868,23 @@ The string `'_'` can be used as a placeholder in the list of arguments to specif
```lua
local function diff(a, b) return a - b end
-local remove5 = _.partial(diff, '_', 5) -- arg 'a' will be given at call-time, but 'b' is set to 5
+local remove5 = M.partial(diff, '_', 5) -- arg 'a' will be given at call-time, but 'b' is set to 5
remove5(20) -- => 15
````
### partialRight (f, ...)
-Like `_.partial`, it partially applies a function by filling in any number of its arguments, but from the right.
+Like `M.partial`, it partially applies a function by filling in any number of its arguments, but from the right.
```lua
local function concat(...) return table.concat({...},',') end
-local concat_right = _.partialRight(concat,'a','b','c')
+local concat_right = M.partialRight(concat,'a','b','c')
concat_right('d') -- => d,a,b,c
-concat_right = _.partialRight(concat,'a','b')
+concat_right = M.partialRight(concat,'a','b')
concat_right('c','d') -- => c,d,a,b
-concat_right = _.partialRight(concat,'a')
+concat_right = M.partialRight(concat,'a')
concat_right('b','c','d') -- => b,c,d,a
```
@@ -1594,24 +1893,24 @@ In that case, the first args supplied at runtime will be used to fill the initia
```lua
local function concat(...) return table.concat({...},',') end
-local concat_right = _.partialRight(concat,'a','_','c')
+local concat_right = M.partialRight(concat,'a','_','c')
concat_right('d','b') -- => b,a,d,c
-concat_right = _.partialRight(concat,'a','b','_')
+concat_right = M.partialRight(concat,'a','b','_')
concat_right('c','d') -- => d,a,b,c
-concat_right = _.partialRight(concat,'_','a')
+concat_right = M.partialRight(concat,'_','a')
concat_right('b','c','d') -- => c,d,b,a
````
-### curry (f, n_args)
+### curry (f [, n_args = 2])
Curries a function. If the given function `f` takes multiple arguments, it returns another version of `f` that takes a single argument
(the first of the arguments to the original function) and returns a new function that takes the remainder of the arguments and returns the result.
```lua
local function sumOf3args(x,y,z) return x + y + z end
-local curried_sumOf3args = _.curry(sumOf3args, 3)
+local curried_sumOf3args = M.curry(sumOf3args, 3)
sumOf3args(1)(2)(3)) -- => 6
sumOf3args(0)(6)(9)) -- => 15
````
@@ -1620,13 +1919,13 @@ sumOf3args(0)(6)(9)) -- => 15
```lua
local function product(x,y) return x * y end
-local curried_product = _.curry(product)
+local curried_product = M.curry(product)
curried_product(5)(4) -- => 20
curried_product(3)(-5) -- => -15
curried_product(0)(1) -- => 0
````
-### time (f, ...)
+### time (f [, ...])
Returns the execution time of `f (...)` in seconds and its results.
@@ -1637,8 +1936,8 @@ local function wait_count(n)
return i
end
-local time, i = _.time(wait_count, 1e6) -- => 0.002 1000000
-local time, i = _.time(wait_count, 1e7) -- => 0.018 10000000
+local time, i = M.time(wait_count, 1e6) -- => 0.002 1000000
+local time, i = M.time(wait_count, 1e7) -- => 0.018 10000000
````
**[[⬆]](#TOC)**
@@ -1650,8 +1949,8 @@ local time, i = _.time(wait_count, 1e7) -- => 0.018 10000000
Collects the names of an object attributes.
```lua
-_.keys({1,2,3}) -- => "{1,2,3}"
-_.keys({x = 0, y = 1}) -- => "{'y','x'}"
+M.keys({1,2,3}) -- => "{1,2,3}"
+M.keys({x = 0, y = 1}) -- => "{'y','x'}"
````
### values (obj)
@@ -1659,8 +1958,29 @@ _.keys({x = 0, y = 1}) -- => "{'y','x'}"
Collects the values of an object attributes.
```lua
-_.values({1,2,3}) -- => "{1,2,3}"
-_.values({x = 0, y = 1}) -- => "{1,0}"
+M.values({1,2,3}) -- => "{1,2,3}"
+M.values({x = 0, y = 1}) -- => "{1,0}"
+````
+
+### path (obj, ...)
+
+Returns the value at a given path in an object.
+
+```lua
+local entity = {
+ pos = {x = 1, y = 2},
+ engine = {
+ left = {status = 'active', damage = 5},
+ right = {status = 'off', damage = 10}
+ },
+ boost = false
+}
+
+M.path(entity,'pos','x') -- => 1
+M.path(entity,'pos','y') -- => 2
+M.path(entity,'engine','left','status') -- => 'active'
+M.path(entity,'engine','right','damage') -- => 10
+M.path(entity,'boost') -- => false
````
### kvpairs (obj)
@@ -1669,7 +1989,7 @@ Converts an object to an array-list of key-value pairs.
```lua
local obj = {x = 1, y = 2, z = 3}
-_.each(_.kvpairs(obj), function(k,v)
+M.each(M.kvpairs(obj), function(v,k)
print(k, table.concat(v,','))
end)
@@ -1678,13 +1998,13 @@ end)
-- => 3 z,3
````
-### toObj
+### toObj (kvpairs)
Converts an array list of `kvpairs` to an object where keys are taken from the 1rst column in the `kvpairs` sequence, associated with values in the 2nd column.
```lua
local list_pairs = {{'x',1},{'y',2},{'z',3}}
-obj = _.toObj(list_pairs)
+obj = M.toObj(list_pairs)
-- => {x = 1, y = 2, z = 3}
````
@@ -1694,7 +2014,7 @@ obj = _.toObj(list_pairs)
Returns a function that will return the key property of any passed-in object.
```lua
-local who = _.property('name')
+local who = M.property('name')
local people = {name = 'Henry'}
who(people) -- => 'Henry'
````
@@ -1705,7 +2025,7 @@ Returns a function that will return the key property of any passed-in object.
```lua
local people = {name = 'Henry'}
-print(_.propertyOf(people)('name')) -- => 'Henry'
+print(M.propertyOf(people)('name')) -- => 'Henry'
````
### toBoolean (value)
@@ -1713,11 +2033,11 @@ print(_.propertyOf(people)('name')) -- => 'Henry'
Converts a given value to a boolean.
```lua
-_.toBoolean(true) -- => true
-_.toBoolean(false) -- => false
-_.toBoolean(nil) -- => false
-_.toBoolean({}) -- => true
-_.toBoolean(1) -- => true
+M.toBoolean(true) -- => true
+M.toBoolean(false) -- => false
+M.toBoolean(nil) -- => false
+M.toBoolean({}) -- => true
+M.toBoolean(1) -- => true
````
### extend (destObj, ...)
@@ -1725,40 +2045,50 @@ _.toBoolean(1) -- => true
Extends a destination object with the properties of some source objects.
```lua
-_.extend({},{a = 'b', c = 'd'}) -- => "{a = 'b', c = 'd'}"
+M.extend({},{a = 'b', c = 'd'}) -- => "{a = 'b', c = 'd'}"
````
-### functions (obj, recurseMt)
-*Aliases: `_.methods`*.
+### functions (obj [, recurseMt])
+*Aliases: `methods`*.
Returns all functions names within an object.
```lua
-_.functions(coroutine) -- => "{'create','resume','running','status','wrap','yield'}"
+M.functions(coroutine)
+-- => "{'yield','wrap','status','resume','running','create'}"
````
-### clone (obj, shallow)
+When given `recurseMt`, will also include `obj` metatable's functions.
+
+````lua
+local mt = {print = print}
+local t = {assert = assert}
+setmetatable(t, {__index = mt})
+M.functions(t, true) -- => "{'assert','print'}"
+````
+
+### clone (obj [, shallow])
Clones a given object.
```lua
local obj = {1,2,3}
-local obj2 = _.clone(obj)
+local obj2 = M.clone(obj)
print(obj2 == obj) -- => false
-print(_.isEqual(obj2, obj)) -- => true
+print(M.isEqual(obj2, obj)) -- => true
````
-### tap (obj, f, ...)
+### tap (obj, f [, ...])
Invokes a given interceptor function on some object, and then returns the object itself. Useful to tap into method chaining to hook intermediate results.
-The pased-interceptor is prototyped as `f(obj,...)`.
+The passed-in interceptor should be prototyped as `f(obj,...)`.
```lua
-local v = _.chain({1,2,3,4,5,6,7,8,9,10)
- :filter(function(k,v) return v%2~=0 end) -- filters even values
- :tap(function(v) print('Max is', _.max(v) end) -- Tap max values
- :map(function(k,v) return k^2)
- :value() -- => Max is 9
+local v = M.chain({1,2,3,4,5,6,7,8,9,10})
+ :filter(function(v) return v%2~=0 end) -- retain odd values
+ :tap(function(v) print('Max is', M.max(v) end) -- Tap max value
+ :map(function(v) return v^2 end)
+ :value() -- => Max is 89
````
### has (obj, key)
@@ -1766,60 +2096,60 @@ local v = _.chain({1,2,3,4,5,6,7,8,9,10)
Checks if an object has a given attribute.
```lua
-_.has(_,'has') -- => true
-_.has(coroutine,'resume') -- => true
-_.has(math,'random') -- => true
+M.has(_,'has') -- => true
+M.has(coroutine,'resume') -- => true
+M.has(math,'random') -- => true
````
### pick (obj, ...)
-*Aliases: `_.choose`*.
+*Aliases: `choose`*.
Collects whilelisted properties of a given object.
```lua
local object = {a = 1, b = 2, c = 3}
-_.pick(object,'a','c') -- => "{a = 1, c = 3}"
+M.pick(object,'a','c') -- => "{a = 1, c = 3}"
````
### omit (obj, ...)
-*Aliases: `_.drop`*.
+*Aliases: `drop`*.
Omits blacklisted properties of a given object.
```lua
local object = {a = 1, b = 2, c = 3}
-_.omit(object,'a','c') -- => "{b = 2}"
+M.omit(object,'a','c') -- => "{b = 2}"
````
-### template (obj, template)
-*Aliases: `_.defaults`*.
+### template (obj [, template])
+*Aliases: `defaults`*.
Applies a template on an object, preserving existing properties.
```lua
local obj = {a = 0}
-_.template(obj,{a = 1, b = 2, c = 3}) -- => "{a=0, c=3, b=2}"
+M.template(obj,{a = 1, b = 2, c = 3}) -- => "{a=0, c=3, b=2}"
````
-### isEqual (objA, objB, useMt)
-*Aliases: `_.compare`*.
+### isEqual (objA, objB [, useMt])
+*Aliases: `compare`, `M.matches`*.
Compares objects:
```lua
-_.isEqual(1,1) -- => true
-_.isEqual(true,false) -- => false
-_.isEqual(3.14,math.pi) -- => false
-_.isEqual({3,4,5},{3,4,{5}}) -- => false
+M.isEqual(1,1) -- => true
+M.isEqual(true,false) -- => false
+M.isEqual(3.14,math.pi) -- => false
+M.isEqual({3,4,5},{3,4,{5}}) -- => false
````
-### result (obj, method, ...)
+### result (obj, method [, ...])
Calls an object method, passing it as a first argument the object itself.
```lua
-_.result('abc','len') -- => 3
-_.result({'a','b','c'},table.concat) -- => 'abc'
+M.result('abc','len') -- => 3
+M.result({'a','b','c'},table.concat) -- => 'abc'
````
### isTable (t)
@@ -1827,9 +2157,9 @@ _.result({'a','b','c'},table.concat) -- => 'abc'
Is the given argument an object (i.e a table) ?
```lua
-_.isTable({}) -- => true
-_.isTable(math) -- => true
-_.isTable(string) -- => true
+M.isTable({}) -- => true
+M.isTable(math) -- => true
+M.isTable(string) -- => true
````
### isCallable (obj)
@@ -1837,10 +2167,10 @@ _.isTable(string) -- => true
Is the given argument callable ?
```lua
-_.isCallable(print) -- => true
-_.isCallable(function() end) -- => true
-_.isCallable(setmetatable({},{__index = string}).upper) -- => true
-_.isCallable(setmetatable({},{__call = function() return end})) -- => true
+M.isCallable(print) -- => true
+M.isCallable(function() end) -- => true
+M.isCallable(setmetatable({},{__index = string}).upper) -- => true
+M.isCallable(setmetatable({},{__call = function() return end})) -- => true
````
### isArray (obj)
@@ -1848,9 +2178,9 @@ _.isCallable(setmetatable({},{__call = function() return end})) -- => true
Is the given argument an array (i.e. a sequence) ?
```lua
-_.isArray({}) -- => true
-_.isArray({1,2,3}) -- => true
-_.isArray({'a','b','c'}) -- => true
+M.isArray({}) -- => true
+M.isArray({1,2,3}) -- => true
+M.isArray({'a','b','c'}) -- => true
````
### isIterable (obj)
@@ -1858,20 +2188,20 @@ _.isArray({'a','b','c'}) -- => true
Checks if the given object is iterable with `pairs`.
```lua
-_.isIterable({}) -- => true
-_.isIterable(function() end) -- => false
-_.isIterable(false) -- => false
-_.isIterable(1) -- => false
+M.isIterable({}) -- => true
+M.isIterable(function() end) -- => false
+M.isIterable(false) -- => false
+M.isIterable(1) -- => false
````
-### isEmpty (obj)
+### isEmpty ([obj])
Is the given argument empty ?
```lua
-_.isEmpty('') -- => true
-_.isEmpty({}) -- => true
-_.isEmpty({'a','b','c'}) -- => false
+M.isEmpty('') -- => true
+M.isEmpty({}) -- => true
+M.isEmpty({'a','b','c'}) -- => false
````
### isString (obj)
@@ -1879,9 +2209,9 @@ _.isEmpty({'a','b','c'}) -- => false
Is the given argument a string ?
```lua
-_.isString('') -- => true
-_.isString('Hello') -- => false
-_.isString({}) -- => false
+M.isString('') -- => true
+M.isString('Hello') -- => false
+M.isString({}) -- => false
````
### isFunction (obj)
@@ -1889,9 +2219,9 @@ _.isString({}) -- => false
Is the given argument a function ?
```lua
-_.isFunction(print) -- => true
-_.isFunction(function() end) -- => true
-_.isFunction({}) -- => false
+M.isFunction(print) -- => true
+M.isFunction(function() end) -- => true
+M.isFunction({}) -- => false
````
### isNil (obj)
@@ -1899,9 +2229,9 @@ _.isFunction({}) -- => false
Is the given argument nil ?
```lua
-_.isNil(nil) -- => true
-_.isNil() -- => true
-_.isNil({}) -- => false
+M.isNil(nil) -- => true
+M.isNil() -- => true
+M.isNil({}) -- => false
````
### isNumber (obj)
@@ -1909,10 +2239,10 @@ _.isNil({}) -- => false
Is the given argument a number ?
```lua
-_.isNumber(math.pi) -- => true
-_.isNumber(math.huge) -- => true
-_.isNumber(0/0) -- => true
-_.isNumber() -- => false
+M.isNumber(math.pi) -- => true
+M.isNumber(math.huge) -- => true
+M.isNumber(0/0) -- => true
+M.isNumber() -- => false
````
### isNaN (obj)
@@ -1920,8 +2250,8 @@ _.isNumber() -- => false
Is the given argument NaN ?
```lua
-_.isNaN(1) -- => false
-_.isNaN(0/0) -- => true
+M.isNaN(1) -- => false
+M.isNaN(0/0) -- => true
````
### isFinite (obj)
@@ -1929,11 +2259,11 @@ _.isNaN(0/0) -- => true
Is the given argument a finite number ?
```lua
-_.isFinite(99e99) -- => true
-_.isFinite(math.pi) -- => true
-_.isFinite(math.huge) -- => false
-_.isFinite(1/0) -- => false
-_.isFinite(0/0) -- => false
+M.isFinite(99e99) -- => true
+M.isFinite(math.pi) -- => true
+M.isFinite(math.huge) -- => false
+M.isFinite(1/0) -- => false
+M.isFinite(0/0) -- => false
````
### isBoolean (obj)
@@ -1941,10 +2271,10 @@ _.isFinite(0/0) -- => false
Is the given argument a boolean ?
```lua
-_.isBoolean(true) -- => true
-_.isBoolean(false) -- => true
-_.isBoolean(1==1) -- => true
-_.isBoolean(print) -- => false
+M.isBoolean(true) -- => true
+M.isBoolean(false) -- => true
+M.isBoolean(1==1) -- => true
+M.isBoolean(print) -- => false
````
### isInteger (obj)
@@ -1952,9 +2282,9 @@ _.isBoolean(print) -- => false
Is the given argument an integer ?
```lua
-_.isInteger(math.pi) -- => false
-_.isInteger(1) -- => true
-_.isInteger(-1) -- => true
+M.isInteger(math.pi) -- => false
+M.isInteger(1) -- => true
+M.isInteger(-1) -- => true
````
**[[⬆]](#TOC)**
@@ -1962,8 +2292,9 @@ _.isInteger(-1) -- => true
## <a name='chaining'>Chaining</a>
*Method chaining* (also known as *name parameter idiom*), is a technique for invoking consecutively method calls in object-oriented style.
-Each method returns an object, and methods calls are chained together.
+Each method returns an object, and method calls are chained together.
Moses offers chaining for your perusal. <br/>
+
Let's use chaining to get the count of evey single word in some lyrics (case won't matter here).
@@ -1975,16 +2306,17 @@ local lyrics = {
"He sleeps all night and he works all day"
}
-local stats = _.chain(lyrics)
- :map(function(k,line)
- local t = {}
- for w in line:gmatch('(%w+)') do
- t[#t+1] = w
- end
- return t
- end)
+-- split a text into words
+local function words(line)
+ local t = {}
+ for w in line:gmatch('(%w+)') do t[#t+1] = w end
+ return t
+end
+
+local stats = M.chain(lyrics)
+ :map(words)
:flatten()
- :countBy(function(i,v) return v:lower() end)
+ :countBy(string.lower)
:value()
-- => "{
@@ -1994,7 +2326,7 @@ local stats = _.chain(lyrics)
-- => }"
````
-For convenience, you can also use `_(value)` to start chaining methods, instead of `_.chain(value)`.
+For convenience, you can also use `_(value)` to start chaining methods, instead of `M.chain(value)`.
Note that one can use `:value()` to unwrap a chained object.
@@ -2011,7 +2343,7 @@ All library functions can be imported in a context using `import` into a specifi
```lua
local context = {}
-_.import(context)
+M.import(context)
context.each({1,2,3},print)
@@ -2020,10 +2352,10 @@ context.each({1,2,3},print)
-- => 3 3
````
-When no `context` was provided, it defaults to the global environment `_G`.
+When no `context` was provided, it defaults to the current environment, `_ENV` or `_G`.
```lua
-_.import()
+M.import()
each({1,2,3},print)
@@ -2036,7 +2368,7 @@ Passing `noConflict` argument leaves untouched conflicting keys while importing
```lua
local context = {each = 1}
-_.import(context, true)
+M.import(context, true)
print(context.each) -- => 1
context.eachi({1,2,3},print)
diff --git a/moses.lua b/moses.lua
index 1e4b1b3..2bb0609 100644
--- a/moses.lua
+++ b/moses.lua
@@ -1,11 +1,12 @@
--- Utility-belt library for functional programming in Lua ([source](http://github.com/Yonaba/Moses))
-- @author [Roland Yonaba](http://github.com/Yonaba)
--- @copyright 2012-2017
+-- @copyright 2012-2018
-- @license [MIT](http://www.opensource.org/licenses/mit-license.php)
--- @release 1.6.1
+-- @release 2.0.0
-- @module moses
+-- @set sort=true
-local _MODULEVERSION = '1.6.1'
+local _MODULEVERSION = '2.0.0'
-- Internalisation
local next, type, select, pcall = next, type, select, pcall
@@ -13,21 +14,21 @@ local setmetatable, getmetatable = setmetatable, getmetatable
local t_insert, t_sort = table.insert, table.sort
local t_remove,t_concat = table.remove, table.concat
local randomseed, random, huge = math.randomseed, math.random, math.huge
-local floor, max, min = math.floor, math.max, math.min
+local floor, max, min, ceil = math.floor, math.max, math.min, math.ceil
+local wrap = coroutine.wrap
+local yield = coroutine.yield
local rawget = rawget
local unpack = table.unpack or unpack
local pairs,ipairs = pairs,ipairs
+local error = error
local clock = os.clock
-local _ = {}
+local M = {}
-- ======== Private helpers
local function f_max(a,b) return a>b end
local function f_min(a,b) return a<b end
-local function clamp(var,a,b) return (var<a) and a or (var>b and b or var) end
-local function isTrue(_,value) return value and true end
-local function iNot(value) return not value end
local function count(t) -- raw count of items in an map-table
local i = 0
@@ -36,13 +37,13 @@ local function count(t) -- raw count of items in an map-table
end
local function extract(list,comp,transform,...) -- extracts value from a list
- local _ans
- local transform = transform or _.identity
- for index,value in pairs(list) do
- if not _ans then _ans = transform(value,...)
+ transform = transform or M.identity
+ local _ans
+ for k,v in pairs(list) do
+ if not _ans then _ans = transform(v,...)
else
- local value = transform(value,...)
- _ans = comp(_ans,value) and _ans or value
+ local val = transform(v,...)
+ _ans = comp(_ans,val) and _ans or val
end
end
return _ans
@@ -50,7 +51,7 @@ end
local function partgen(t, n, f, pad) -- generates array partitions
for i = 0, #t, n do
- local s = _.slice(t, i+1, i+n)
+ local s = M.slice(t, i+1, i+n)
if #s>0 then
while (#s < n and pad) do s[#s+1] = pad end
f(s)
@@ -58,9 +59,9 @@ local function partgen(t, n, f, pad) -- generates array partitions
end
end
-local function partgen2(t, n, f, pad) -- generates sliding array partitions
+local function partgen2(t, n, f, pad) -- generates overlapping array partitions
for i = 0, #t, n-1 do
- local s = _.slice(t, i+1, i+n)
+ local s = M.slice(t, i+1, i+n)
if #s>0 and i+1<#t then
while (#s < n and pad) do s[#s+1] = pad end
f(s)
@@ -68,6 +69,16 @@ local function partgen2(t, n, f, pad) -- generates sliding array partitions
end
end
+local function partgen3(t, n, f, pad) -- generates sliding array partitions
+ for i = 0, #t, 1 do
+ local s = M.slice(t, i+1, i+n)
+ if #s>0 and i+n<=#t then
+ while (#s < n and pad) do s[#s+1] = pad end
+ f(s)
+ end
+ end
+end
+
local function permgen(t, n, f) -- taken from PiL: http://www.lua.org/pil/9.3.html
if n == 0 then f(t) end
for i = 1,n do
@@ -77,9 +88,158 @@ local function permgen(t, n, f) -- taken from PiL: http://www.lua.org/pil/9.3.ht
end
end
+local function signum(a) return a>=0 and 1 or -1 end
+
-- Internal counter for unique ids generation
local unique_id_counter = -1
+--- Operator functions
+-- @section Operator functions
+
+M.operator = {}
+--- Returns a + b. <em>Aliased as `op.add`</em>.
+-- @name operator.add
+-- @param a a value
+-- @param b a value
+-- @return a + b
+M.operator.add = function(a,b) return a + b end
+
+--- Returns a - b. <em>Aliased as `op.sub`</em>.
+-- @name operator.sub
+-- @param a a value
+-- @param b a value
+-- @return a - b
+M.operator.sub = function(a,b) return a - b end
+
+--- Returns a * b. <em>Aliased as `op.mul`</em>.
+-- @name operator.mul
+-- @param a a value
+-- @param b a value
+-- @return a * b
+M.operator.mul = function(a,b) return a * b end
+
+--- Returns a / b. <em>Aliased as `op.div`</em>.
+-- @name operator.div
+-- @param a a value
+-- @param b a value
+-- @return a / b
+M.operator.div = function(a,b) return a / b end
+
+--- Returns a % b. <em>Aliased as `op.mod`</em>.
+-- @name operator.mod
+-- @param a a value
+-- @param b a value
+-- @return a % b
+M.operator.mod = function(a,b) return a % b end
+
+--- Returns a ^ b. <em>Aliased as `op.exp`, `op.pow`</em>.
+-- @name operator.exp
+-- @param a a value
+-- @param b a value
+-- @return a ^ b
+M.operator.exp = function(a,b) return a ^ b end
+M.operator.pow = M.operator.exp
+
+--- Returns -a. <em>Aliased as `op.unm`, `op.neg`</em>.
+-- @name operator.unm
+-- @param a a value
+-- @return -a
+M.operator.unm = function(a) return -a end
+M.operator.neg = M.operator.unm
+
+--- Performs floor division (//) between `a` and `b`. It rounds the quotient towards minus infinity.
+-- <em>Aliased as `op.floordiv`</em>.
+-- @name operator.floordiv
+-- @param a a value
+-- @param b a value
+-- @return a // b
+M.operator.floordiv = function(a, b) return floor(a/b) end
+
+--- Performs integer division between `a` and `b`. <em>Aliased as `op.intdiv`</em>.
+-- @name operator.intdiv
+-- @param a a value
+-- @param b a value
+-- @return a / b
+M.operator.intdiv = function(a,b)
+ return a>=0 and floor(a/b) or ceil(a/b)
+end
+
+--- Checks if a equals b. <em>Aliased as `op.eq`</em>.
+-- @name operator.eq
+-- @param a a value
+-- @param b a value
+-- @return a == b
+M.operator.eq = function(a,b) return a == b end
+
+--- Checks if a not equals b. <em>Aliased as `op.neq`</em>.
+-- @name operator.neq
+-- @param a a value
+-- @param b a value
+-- @return a ~= b
+M.operator.neq = function(a,b) return a ~= b end
+
+--- Checks if a is strictly less than b. <em>Aliased as `op.lt`</em>.
+-- @name operator.lt
+-- @param a a value
+-- @param b a value
+-- @return a < b
+M.operator.lt = function(a,b) return a < b end
+
+--- Checks if a is strictly greater than b. <em>Aliased as `op.gt`</em>.
+-- @name operator.gt
+-- @param a a value
+-- @param b a value
+-- @return a > b
+M.operator.gt = function(a,b) return a > b end
+
+--- Checks if a is less or equal to b. <em>Aliased as `op.le`</em>.
+-- @name operator.le
+-- @param a a value
+-- @param b a value
+-- @return a <= b
+M.operator.le = function(a,b) return a <= b end
+
+--- Checks if a is greater or equal to b. <em>Aliased as `op.ge`</em>.
+-- @name operator.ge
+-- @param a a value
+-- @param b a value
+-- @return a >= b
+M.operator.ge = function(a,b) return a >= b end
+
+--- Returns logical a and b. <em>Aliased as `op.land`</em>.
+-- @name operator.ge
+-- @param a a value
+-- @param b a value
+-- @return a and b
+M.operator.land = function(a,b) return a and b end
+
+--- Returns logical a or b. <em>Aliased as `op.lor`</em>.
+-- @name operator.lor
+-- @param a a value
+-- @param b a value
+-- @return a or b
+M.operator.lor = function(a,b) return a or b end
+
+--- Returns logical not a. <em>Aliased as `op.lnot`</em>.
+-- @name operator.lnot
+-- @param a a value
+-- @return not a
+M.operator.lnot = function(a) return not a end
+
+--- Returns concatenation of a and b. <em>Aliased as `op.concat`</em>.
+-- @name operator.concat
+-- @param a a value
+-- @param b a value
+-- @return a .. b
+M.operator.concat = function(a,b) return a..b end
+
+--- Returns the length of a. <em>Aliased as `op.len`</em>.
+-- @name operator.length
+-- @param a a value
+-- @return #a
+M.operator.length = function(a) return #a end
+M.operator.len = M.operator.length
+
--- Table functions
-- @section Table functions
@@ -87,39 +247,39 @@ local unique_id_counter = -1
-- @name clear
-- @param t a table
-- @return the given table, cleared.
-function _.clear(t)
+function M.clear(t)
for k in pairs(t) do t[k] = nil end
return t
end
---- Iterates on key-value pairs, calling `f (k, v)` at every step.
+
+
+--- Iterates on key-value pairs, calling `f (v, k)` at every step.
-- <br/><em>Aliased as `forEach`</em>.
-- @name each
-- @param t a table
--- @param f a function, prototyped as `f (k, v, ...)`
+-- @param f a function, prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @see eachi
-function _.each(t, f, ...)
+function M.each(t, f, ...)
for index,value in pairs(t) do
- f(index,value,...)
+ f(value, index, ...)
end
end
---- Iterates on integer key-value pairs, calling `f(k, v)` every step.
+--- Iterates on integer key-value pairs, calling `f(v, k)` every step.
-- Only applies to values located at integer keys. The table can be a sparse array.
-- Iteration will start from the lowest integer key found to the highest one.
-- <br/><em>Aliased as `forEachi`</em>.
-- @name eachi
-- @param t a table
--- @param f a function, prototyped as `f (k, v, ...)`
+-- @param f a function, prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @see each
-function _.eachi(t, f, ...)
- local lkeys = _.sort(_.select(_.keys(t), function(k,v)
- return _.isInteger(v)
- end))
+function M.eachi(t, f, ...)
+ local lkeys = M.sort(M.select(M.keys(t), M.isInteger))
for k, key in ipairs(lkeys) do
- f(key, t[key],...)
+ f(t[key], key, ...)
end
end
@@ -128,41 +288,57 @@ end
-- @param t a table
-- @param ... A variable number of keys to collect values
-- @return an array-list of values
-function _.at(t, ...)
+function M.at(t, ...)
local values = {}
- for i, key in ipairs({...}) do
- if _.has(t, key) then values[#values+1] = t[key] end
- end
+ for i, key in ipairs({...}) do values[#values+1] = t[key] end
return values
end
+--- Adjusts the value at a given key using a function or a value. In case `f` is a function,
+-- it should be prototyped `f(v, ...)`. It does not mutate the given table, but rather
+-- returns a new array. In case the given `key` does not exist in `t`, it throws an error.
+-- @param t a table
+-- @param key a key
+-- @param f a function, prototyped as `f(v, ...)` or a value
+-- @param[opt] ... Optional args to be passed to `f`
+function M.adjust(t, key, f, ...)
+ if (t[key] == nil) then error("key not existing in table") end
+ local _t = M.clone(t)
+ _t[key] = type(f) == 'function' and f(_t[key], ...) or f
+ return _t
+end
+
--- Counts occurrences of a given value in a table. Uses @{isEqual} to compare values.
-- @name count
-- @param t a table
--- @param[opt] value a value to be searched in the table. If not given, the @{size} of the table will be returned
+-- @param[opt] val a value to be searched in the table. If not given, the @{size} of the table will be returned
-- @return the count of occurrences of the given value
-- @see countf
-- @see size
-function _.count(t, value)
- if _.isNil(value) then return _.size(t) end
+function M.count(t, val)
+ if val == nil then return M.size(t) end
local count = 0
- _.each(t, function(k,v)
- if _.isEqual(v, value) then count = count + 1 end
- end)
+ for k, v in pairs(t) do
+ if M.isEqual(v, val) then count = count + 1 end
+ end
return count
end
---- Counts occurrences validating a predicate. Same as @{count}, but uses an iterator.
--- Returns the count for values passing the test `f (k, v, ...)`
+--- Counts the number of values passing a predicate test. Same as @{count}, but uses an iterator.
+-- Returns the count for values passing the test `f (v, k, ...)`
-- @name countf
-- @param t a table
--- @param f an iterator function, prototyped as `f (k, v, ...)`
+-- @param f an iterator function, prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return the count of values validating the predicate
-- @see count
-- @see size
-function _.countf(t, f, ...)
- return _.count(_.map(t, f, ...), true)
+function M.countf(t, f, ...)
+ local count = 0
+ for k, v in pairs(t) do
+ if f(v, k, ...) then count = count + 1 end
+ end
+ return count
end
--- Loops `n` times through a table. In case `n` is omitted, it will loop forever.
@@ -170,11 +346,11 @@ end
-- <br/><em>Aliased as `loop`</em>.
-- @name cycle
-- @param t a table
--- @param n the number of loops
--- @return an iterator function yielding key-value pairs from the passed-in table.
-function _.cycle(t, n)
+-- @param[opt] n the number of loops
+-- @return an iterator function yielding value-key pairs from the passed-in table.
+function M.cycle(t, n)
n = n or 1
- if n<=0 then return _.noop end
+ if n<=0 then return M.noop end
local k, fk
local i = 0
while true do
@@ -187,22 +363,22 @@ function _.cycle(t, n)
return
end
end
- return k, t[k]
+ return t[k], k
end
end
end
---- Maps `f (k, v)` on key-value pairs, collects and returns the results.
+--- Maps `f (v, k)` on value-key pairs, collects and returns the results.
-- <br/><em>Aliased as `collect`</em>.
-- @name map
-- @param t a table
--- @param f an iterator function, prototyped as `f (k, v, ...)`
+-- @param f an iterator function, prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return a table of results
-function _.map(t, f, ...)
+function M.map(t, f, ...)
local _t = {}
for index,value in pairs(t) do
- local k, kv, v = index, f(index,value,...)
+ local k, kv, v = index, f(value, index, ...)
_t[v and kv or k] = v or kv
end
return _t
@@ -219,8 +395,8 @@ end
-- @return the final state of reduction
-- @see reduceRight
-- @see reduceby
-function _.reduce(t, f, state)
- for __,value in pairs(t) do
+function M.reduce(t, f, state)
+ for k,value in pairs(t) do
if state == nil then state = value
else state = f(state,value)
end
@@ -233,13 +409,13 @@ end
-- @name reduceby
-- @param t a table
-- @param f an iterator function, prototyped as `f (state, value)`
--- @param state an initial state of reduction.
--- @param pred a predicate function `pred (k, v, ...)` to select values to be considered for reduction
--- @param[opt] ... optional args to be passed to `pred`
+-- @param pred a predicate function `pred (v, k, ...)` to select values to be considered for reduction
+-- @param[opt] state an initial state of reduction. Defaults to the first value in the table of selected values.
+-- @param[optchain] ... optional args to be passed to `pred`
-- @return the final state of reduction
-- @see reduce
-function _.reduceby(t, f, state, pred, ...)
- return _.reduce(_.select(t, pred, ...), f, state)
+function M.reduceby(t, f, pred, state, ...)
+ return M.reduce(M.select(t, pred, ...), f, state)
end
--- Reduces a table, right-to-left. Folds the table from the last element to the first element
@@ -252,8 +428,8 @@ end
-- @param[opt] state an initial state of reduction. Defaults to the last value in the table.
-- @return the final state of reduction
-- @see reduce
-function _.reduceRight(t, f, state)
- return _.reduce(_.reverse(t),f,state)
+function M.reduceRight(t, f, state)
+ return M.reduce(M.reverse(t),f,state)
end
--- Reduces a table while saving intermediate states. Folds the table left-to-right
@@ -266,7 +442,7 @@ end
-- @param[opt] state an initial state of reduction. Defaults to the first value in the table.
-- @return an array of states
-- @see mapReduceRight
-function _.mapReduce(t, f, state)
+function M.mapReduce(t, f, state)
local _t = {}
for i,value in pairs(t) do
_t[i] = not state and value or f(state,value)
@@ -285,8 +461,8 @@ end
-- @param[opt] state an initial state of reduction. Defaults to the last value in the table.
-- @return an array of states
-- @see mapReduce
-function _.mapReduceRight(t, f, state)
- return _.mapReduce(_.reverse(t),f,state)
+function M.mapReduceRight(t, f, state)
+ return M.mapReduce(M.reverse(t),f,state)
end
--- Performs a linear search for a value in a table. It does not work for nested tables.
@@ -298,9 +474,9 @@ end
-- @param value a value to search for
-- @return a boolean : `true` when found, `false` otherwise
-- @see detect
-function _.include(t, value)
- local _iter = _.isFunction(value) and value or _.isEqual
- for __,v in pairs(t) do
+function M.include(t, value)
+ local _iter = (type(value) == 'function') and value or M.isEqual
+ for k,v in pairs(t) do
if _iter(v,value) then return true end
end
return false
@@ -308,14 +484,16 @@ end
--- Performs a linear search for a value in a table. Returns the key of the value if found.
-- The given value can be a function prototyped as `f (v, value)` which should return true when
--- any v in the table equals the value being searched.
+-- any v in the table equals the value being searched. This function is similar to @{find},
+-- which is mostly meant to work with array.
-- @name detect
-- @param t a table
-- @param value a value to search for
-- @return the key of the value when found or __nil__
-- @see include
-function _.detect(t, value)
- local _iter = _.isFunction(value) and value or _.isEqual
+-- @see find
+function M.detect(t, value)
+ local _iter = (type(value) == 'function') and value or M.isEqual
for key,arg in pairs(t) do
if _iter(arg,value) then return key end
end
@@ -327,8 +505,8 @@ end
-- @param props a set of keys
-- @return an array of values from the passed-in table
-- @see findWhere
-function _.where(t, props)
- local r = _.select(t, function(__,v)
+function M.where(t, props)
+ local r = M.select(t, function(v)
for key in pairs(props) do
if v[key] ~= props[key] then return false end
end
@@ -343,8 +521,8 @@ end
-- @param props a set of keys
-- @return a value from the passed-in table
-- @see where
-function _.findWhere(t, props)
- local index = _.detect(t, function(v)
+function M.findWhere(t, props)
+ local index = M.detect(t, function(v)
for key in pairs(props) do
if props[key] ~= v[key] then return false end
end
@@ -357,14 +535,14 @@ end
-- <br/><em>Aliased as `filter`</em>.
-- @name select
-- @param t a table
--- @param f an iterator function, prototyped as `f (k, v, ...)`
+-- @param f an iterator function, prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return the selected values
-- @see reject
-function _.select(t, f, ...)
+function M.select(t, f, ...)
local _t = {}
for index,value in pairs(t) do
- if f(index, value,...) then _t[#_t+1] = value end
+ if f(value,index,...) then _t[#_t+1] = value end
end
return _t
end
@@ -373,15 +551,14 @@ end
-- <br/><em>Aliased as `discard`</em>
-- @name reject
-- @param t a table
--- @param f an iterator function, prototyped as `f (k, v, ...)`
+-- @param f an iterator function, prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return the remaining values
-- @see select
-function _.reject(t, f, ...)
- local _mapped = _.map(t,f,...)
+function M.reject(t, f, ...)
local _t = {}
- for index,value in pairs (_mapped) do
- if not value then _t[#_t+1] = t[index] end
+ for index,value in pairs (t) do
+ if not f(value,index,...) then _t[#_t+1] = value end
end
return _t
end
@@ -390,11 +567,14 @@ end
-- <br/><em>Aliased as `every`</em>
-- @name all
-- @param t a table
--- @param f an iterator function, prototyped as `f (k, v, ...)`
+-- @param f an iterator function, prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return `true` if all values passes the predicate, `false` otherwise
-function _.all(t, f, ...)
- return ((#_.select(_.map(t,f,...), isTrue)) == count(t))
+function M.all(t, f, ...)
+ for index,value in pairs(t) do
+ if not f(value,index,...) then return false end
+ end
+ return true
end
--- Invokes a method on each value in a table.
@@ -404,22 +584,22 @@ end
-- @param[opt] ... Optional args to be passed to `method`
-- @return the result of the call `f (v, ...)`
-- @see pluck
-function _.invoke(t, method, ...)
+function M.invoke(t, method, ...)
local args = {...}
- return _.map(t, function(__,v)
- if _.isTable(v) then
- if _.has(v,method) then
- if _.isCallable(v[method]) then
+ return M.map(t, function(v)
+ if (type(v) == 'table') then
+ if v[method] then
+ if M.isCallable(v[method]) then
return v[method](v,unpack(args))
else
return v[method]
end
else
- if _.isCallable(method) then
+ if M.isCallable(method) then
return method(v,unpack(args))
end
end
- elseif _.isCallable(method) then
+ elseif M.isCallable(method) then
return method(v,unpack(args))
end
end)
@@ -430,13 +610,15 @@ end
-- @param t a table
-- @param key a key, will be used to index in each value: `value[key]`
-- @return an array of values having the given key
-function _.pluck(t, key)
- return _.reject(_.map(t,function(__,value)
- return value[key]
- end), iNot)
+function M.pluck(t, key)
+ local _t = {}
+ for k, v in pairs(t) do
+ if v[key] then _t[#_t+1] = v[key] end
+ end
+ return _t
end
---- Returns the max value in a collection. If an transformation function is passed, it will
+--- Returns the max value in a collection. If a `transform` function is passed, it will
-- be used to evaluate values by which all objects will be sorted.
-- @name max
-- @param t a table
@@ -444,11 +626,11 @@ end
-- @param[optchain] ... Optional args to be passed to `transform`
-- @return the max value found
-- @see min
-function _.max(t, transform, ...)
+function M.max(t, transform, ...)
return extract(t, f_max, transform, ...)
end
---- Returns the min value in a collection. If an transformation function is passed, it will
+--- Returns the min value in a collection. If a `transform` function is passed, it will
-- be used to evaluate values by which all objects will be sorted.
-- @name min
-- @param t a table
@@ -456,45 +638,28 @@ end
-- @param[optchain] ... Optional args to be passed to `transform`
-- @return the min value found
-- @see max
-function _.min(t, transform, ...)
+function M.min(t, transform, ...)
return extract(t, f_min, transform, ...)
end
---- Returns a shuffled copy of a given collection. If a seed is provided, it will
--- be used to init the pseudo random number generator (using `math.randomseed`).
--- @name shuffle
--- @param t a table
--- @param[opt] seed a seed
--- @return a shuffled copy of the given table
-function _.shuffle(t, seed)
- if seed then randomseed(seed) end
- local _shuffled = {}
- _.each(t,function(index,value)
- local randPos = floor(random()*index)+1
- _shuffled[index] = _shuffled[randPos]
- _shuffled[randPos] = value
- end)
- return _shuffled
-end
-
--- Checks if two tables are the same. It compares if both tables features the same values,
-- but not necessarily at the same keys.
-- @name same
-- @param a a table
-- @param b another table
-- @return `true` or `false`
-function _.same(a, b)
- return _.all(a, function (i,v) return _.include(b,v) end)
- and _.all(b, function (i,v) return _.include(a,v) end)
+function M.same(a, b)
+ return M.all(a, function(v) return M.include(b,v) end)
+ and M.all(b, function(v) return M.include(a,v) end)
end
--- Sorts a table, in-place. If a comparison function is given, it will be used to sort values.
-- @name sort
-- @param t a table
-- @param[opt] comp a comparison function prototyped as `comp (a, b)`, defaults to <tt><</tt> operator.
--- @return the initial table, sorted.
+-- @return the given table, sorted.
-- @see sortBy
-function _.sort(t, comp)
+function M.sort(t, comp)
t_sort(t, comp)
return t
end
@@ -508,51 +673,46 @@ end
-- @param[optchain] comp a comparison function, defaults to the `<` operator
-- @return a new array of sorted values
-- @see sort
-function _.sortBy(t, transform, comp)
- local f = transform or _.identity
- if _.isString(transform) then
+function M.sortBy(t, transform, comp)
+ local f = transform or M.identity
+ if (type(transform) == 'string') then
f = function(t) return t[transform] end
end
comp = comp or f_min
- local _t = {}
- _.each(t, function(__,v)
- _t[#_t+1] = {value = v, transform = f(v)}
- end)
- t_sort(_t, function(a,b) return comp(a.transform, b.transform) end)
- return _.pluck(_t, 'value')
+ t_sort(t, function(a,b) return comp(f(a), f(b)) end)
+ return t
end
--- Splits a table into subsets groups.
-- @name groupBy
-- @param t a table
--- @param iter an iterator function, prototyped as `iter (k, v, ...)`
+-- @param iter an iterator function, prototyped as `iter (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `iter`
-- @return a table of subsets groups
-function _.groupBy(t, iter, ...)
+function M.groupBy(t, iter, ...)
local vararg = {...}
local _t = {}
- _.each(t, function(i,v)
- local _key = iter(i,v, unpack(vararg))
- if _t[_key] then _t[_key][#_t[_key]+1] = v
- else _t[_key] = {v}
- end
- end)
+ for k,v in pairs(t) do
+ local _key = iter(v,k, unpack(vararg))
+ if _t[_key] then _t[_key][#_t[_key]+1] = v
+ else _t[_key] = {v}
+ end
+ end
return _t
end
--- Groups values in a collection and counts them.
-- @name countBy
-- @param t a table
--- @param iter an iterator function, prototyped as `iter (k, v, ...)`
+-- @param iter an iterator function, prototyped as `iter (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `iter`
-- @return a table of subsets groups names paired with their count
-function _.countBy(t, iter, ...)
- local vararg = {...}
+function M.countBy(t, iter, ...)
local stats = {}
- _.each(t,function(i,v)
- local key = iter(i,v,unpack(vararg))
- stats[key] = (stats[key] or 0) +1
- end)
+ for i,v in pairs(t) do
+ local key = iter(v,i,...)
+ stats[key] = (stats[key] or 0) +1
+ end
return stats
end
@@ -563,14 +723,10 @@ end
-- @return a count
-- @see count
-- @see countf
-function _.size(...)
+function M.size(...)
local args = {...}
local arg1 = args[1]
- if _.isTable(arg1) then
- return count(args[1])
- else
- return count(args)
- end
+ return (type(arg1) == 'table') and count(args[1]) or count(args)
end
--- Checks if all the keys of `other` table exists in table `t`. It does not
@@ -581,7 +737,7 @@ end
-- @param other another table
-- @return `true` or `false`
-- @see sameKeys
-function _.containsKeys(t, other)
+function M.containsKeys(t, other)
for key in pairs(other) do
if not t[key] then return false end
end
@@ -594,7 +750,7 @@ end
-- @param tB another table
-- @return `true` or `false`
-- @see containsKeys
-function _.sameKeys(tA, tB)
+function M.sameKeys(tA, tB)
for key in pairs(tA) do
if not tB[key] then return false end
end
@@ -614,16 +770,16 @@ end
-- @param array an array
-- @param[opt] n a number of elements to be sampled. Defaults to 1.
-- @param[optchain] seed an optional seed for shuffling
--- @return an array of selected values or a single value when `n` == 1
+-- @return an array of selected values
-- @see sampleProb
-function _.sample(array, n, seed)
- n = n or 1
- if n < 1 then return end
+function M.sample(array, n, seed)
+ n = n or 1
+ if n == 0 then return {} end
if n == 1 then
if seed then randomseed(seed) end
- return array[random(1, #array)]
+ return {array[random(1, #array)]}
end
- return _.slice(_.shuffle(array, seed), 1, n)
+ return M.slice(M.shuffle(array, seed), 1, n)
end
--- Return elements from a sequence with a given probability. It considers each value independently.
@@ -635,16 +791,37 @@ end
-- @param[opt] seed an optional seed for deterministic sampling
-- @return an array of selected values
-- @see sample
-function _.sampleProb(array, prob, seed)
+function M.sampleProb(array, prob, seed)
if seed then randomseed(seed) end
- return _.select(array, function(_,v) return random() < prob end)
+ local t = {}
+ for k, v in ipairs(array) do
+ if random() < prob then t[#t+1] = v end
+ end
+ return t
+end
+
+--- Returns a shuffled copy of a given array. If a seed is provided, it will
+-- be used to init the built-in pseudo random number generator (using `math.randomseed`).
+-- @name shuffle
+-- @param array an array
+-- @param[opt] seed a seed
+-- @return a shuffled copy of the given array
+function M.shuffle(array, seed)
+ if seed then randomseed(seed) end
+ local _shuffled = {}
+ for index, value in ipairs(array) do
+ local randPos = floor(random()*index)+1
+ _shuffled[index] = _shuffled[randPos]
+ _shuffled[randPos] = value
+ end
+ return _shuffled
end
--- Converts a list of arguments to an array.
-- @name toArray
-- @param ... a list of arguments
-- @return an array of all passed-in args
-function _.toArray(...) return {...} end
+function M.toArray(...) return {...} end
--- Looks for the first occurrence of a given value in an array. Returns the value index if found.
-- Uses @{isEqual} to compare values.
@@ -653,9 +830,10 @@ function _.toArray(...) return {...} end
-- @param value a value to lookup for
-- @param[opt] from the index from where the search will start. Defaults to 1.
-- @return the index of the value if found in the array, `nil` otherwise.
-function _.find(array, value, from)
+-- @see detect
+function M.find(array, value, from)
for i = from or 1, #array do
- if _.isEqual(array[i], value) then return i end
+ if M.isEqual(array[i], value) then return i end
end
end
@@ -663,7 +841,7 @@ end
-- @name reverse
-- @param array an array
-- @return a reversed array
-function _.reverse(array)
+function M.reverse(array)
local _array = {}
for i = #array,1,-1 do
_array[#_array+1] = array[i]
@@ -673,32 +851,57 @@ end
--- Replaces elements in a given array with a given value. In case `i` and `j` are given
-- it will only replaces values at indexes between `[i,j]`. In case `j` is greater than the array
--- size, it will append new values, increasing the array.
+-- size, it will append new values, increasing the array size.
-- @name fill
-- @param array an array
-- @param value a value
-- @param[opt] i the index from which to start replacing values. Defaults to 1.
-- @param[optchain] j the index where to stop replacing values. Defaults to the array size.
-- @return the original array with values changed
-function _.fill(array, value, i, j)
- j = j or _.size(array)
+function M.fill(array, value, i, j)
+ j = j or M.size(array)
for i = i or 1, j do array[i] = value end
return array
end
+--- Returns an array of `n` zeros.
+-- @name zeros
+-- @param n a number
+-- @return an array
+-- @see ones
+-- @see vector
+function M.zeros(n) return M.fill({}, 0, 1, n) end
+
+--- Returns an array of `n` 1's.
+-- @name ones
+-- @param n a number
+-- @return an array
+-- @see zeros
+-- @see vector
+function M.ones(n) return M.fill({}, 1, 1, n) end
+
+--- Returns an array of `n` times a given value.
+-- @name vector
+-- @param value a value
+-- @param n a number
+-- @return an array
+-- @see zeros
+-- @see ones
+function M.vector(value, n) return M.fill({}, value, 1, n) end
+
--- Collects values from a given array. The passed-in array should not be sparse.
-- This function collects values as long as they satisfy a given predicate and returns on the first falsy test.
-- <br/><em>Aliased as `takeWhile`</em>
-- @name selectWhile
-- @param array an array
--- @param f an iterator function prototyped as `f (k, v, ...)`
+-- @param f an iterator function prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return a new table containing all values collected
-- @see dropWhile
-function _.selectWhile(array, f, ...)
+function M.selectWhile(array, f, ...)
local t = {}
for i,v in ipairs(array) do
- if f(i,v,...) then t[i] = v else break end
+ if f(v,i,...) then t[i] = v else break end
end
return t
end
@@ -708,20 +911,20 @@ end
-- <br/><em>Aliased as `rejectWhile`</em>
-- @name dropWhile
-- @param array an array
--- @param f an iterator function prototyped as `f (k,v, ...)`
+-- @param f an iterator function prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return a new table containing all values collected
--- @selectWhile
-function _.dropWhile(array, f, ...)
+-- @see selectWhile
+function M.dropWhile(array, f, ...)
local _i
for i,v in ipairs(array) do
- if not f(i,v,...) then
+ if not f(v, i, ...) then
_i = i
break
end
end
- if _.isNil(_i) then return {} end
- return _.rest(array,_i)
+ if (_i == nil) then return {} end
+ return M.rest(array,_i)
end
--- Returns the index at which a value should be inserted. This index is evaluated so
@@ -733,9 +936,9 @@ end
-- @param[opt] comp an comparison function prototyped as `f (a, b)`, defaults to <tt><</tt> operator.
-- @param[optchain] sort whether or not the passed-in array should be sorted
-- @return number the index at which the passed-in value should be inserted
-function _.sortedIndex(array, value, comp, sort)
+function M.sortedIndex(array, value, comp, sort)
local _comp = comp or f_min
- if sort then _.sort(array,_comp) end
+ if (sort == true) then t_sort(array,_comp) end
for i = 1,#array do
if not _comp(array[i],value) then return i end
end
@@ -748,7 +951,7 @@ end
-- @param value the value to search for
-- @return the index of the passed-in value
-- @see lastIndexOf
-function _.indexOf(array, value)
+function M.indexOf(array, value)
for k = 1,#array do
if array[k] == value then return k end
end
@@ -760,21 +963,21 @@ end
-- @param value the value to search for
-- @return the index of the last occurrence of the passed-in value or __nil__
-- @see indexOf
-function _.lastIndexOf(array, value)
- local key = _.indexOf(_.reverse(array),value)
+function M.lastIndexOf(array, value)
+ local key = M.indexOf(M.reverse(array),value)
if key then return #array-key+1 end
end
--- Returns the first index at which a predicate returns true.
-- @name findIndex
-- @param array an array
--- @param predicate a predicate function prototyped as `predicate (k, v, ...)`
+-- @param predicate a predicate function prototyped as `predicate (v, k, ...)`
-- @param[opt] ... optional arguments to `pred`
-- @return the index found or __nil__
-- @see findLastIndex
-function _.findIndex(array, predicate, ...)
+function M.findIndex(array, predicate, ...)
for k = 1, #array do
- if predicate(k,array[k],...) then return k end
+ if predicate(array[k],k,...) then return k end
end
end
@@ -785,8 +988,8 @@ end
-- @param[opt] ... optional arguments to `pred`
-- @return the index found or __nil__
-- @see findIndex
-function _.findLastIndex(array, predicate, ...)
- local key = _.findIndex(_.reverse(array),predicate,...)
+function M.findLastIndex(array, predicate, ...)
+ local key = M.findIndex(M.reverse(array),predicate,...)
if key then return #array-key+1 end
end
@@ -796,31 +999,50 @@ end
-- @param array an array
-- @param ... a variable number of arguments
-- @return the passed-in array with new values added
+-- @see prepend
-- @see push
-function _.addTop(array, ...)
- _.each({...},function(i,v) t_insert(array,1,v) end)
+function M.addTop(array, ...)
+ for k,v in ipairs({...}) do
+ t_insert(array,1,v)
+ end
return array
end
+--- Adds all passed-in values at the top of an array. As opposed to @{addTop}, it preserves the order
+-- of the passed in elements.
+-- @name prepend
+-- @param array an array
+-- @param ... a variable number of arguments
+-- @return the passed-in array with new values added
+-- @see addTop
+-- @see push
+function M.prepend(array, ...)
+ return M.append({...}, array)
+end
+
--- Pushes all passed-in values at the end of an array.
-- @name push
-- @param array an array
-- @param ... a variable number of arguments
-- @return the passed-in array with new added values
-- @see addTop
-function _.push(array, ...)
- _.each({...}, function(i,v) array[#array+1] = v end)
+-- @see prepend
+function M.push(array, ...)
+ local args = {...}
+ for k,v in ipairs({...}) do
+ array[#array+1] = v
+ end
return array
end
--- Removes and returns the values at the top of a given array.
--- <br/><em>Aliased as `shift`</em>
--- @name pop
+-- <br/><em>Aliased as `pop`</em>
+-- @name shift
-- @param array an array
-- @param[opt] n the number of values to be popped. Defaults to 1.
-- @return the popped values
-- @see unshift
-function _.pop(array, n)
+function M.shift(array, n)
n = min(n or 1, #array)
local ret = {}
for i = 1, n do
@@ -836,8 +1058,8 @@ end
-- @param array an array
-- @param[opt] n the number of values to be unshifted. Defaults to 1.
-- @return the values
--- @see pop
-function _.unshift(array, n)
+-- @see shift
+function M.unshift(array, n)
n = min(n or 1, #array)
local ret = {}
for i = 1, n do
@@ -854,10 +1076,10 @@ end
-- @param array an array
-- @param ... a variable number of values to be removed from the array
-- @return the passed-in array with values removed
-function _.pull(array, ...)
- for __, rmValue in ipairs({...}) do
+function M.pull(array, ...)
+ for k, rmValue in ipairs({...}) do
for i = #array, 1, -1 do
- if _.isEqual(array[i], rmValue) then
+ if M.isEqual(array[i], rmValue) then
t_remove(array, i)
end
end
@@ -865,28 +1087,21 @@ function _.pull(array, ...)
return array
end
---- Removes values at index within the range `[start, finish]`.
+--- Removes values at an index within the range `[start, finish]`.
-- <br/><em>Aliased as `rmRange`, `chop`</em>
-- @name removeRange
-- @param array an array
-- @param[opt] start the lower bound index, defaults to the first index in the array.
-- @param[optchain] finish the upper bound index, defaults to the array length.
-- @return the passed-in array with values removed
-function _.removeRange(array, start, finish)
- local array = _.clone(array)
- local i,n = (next(array)),#array
- if n < 1 then return array end
-
- start = clamp(start or i,i,n)
- finish = clamp(finish or n,i,n)
-
- if finish < start then return array end
-
- local count = finish - start + 1
- local i = start
- while count > 0 do
- t_remove(array,i)
- count = count - 1
+function M.removeRange(array, start, finish)
+ start = start or 1
+ finish = finish or #array
+ if start > finish then
+ error("start cannot be greater than finish.")
+ end
+ for i = finish, start, -1 do
+ t_remove(array, i)
end
return array
end
@@ -896,42 +1111,43 @@ end
-- the same value are chunked together. Leaves the first argument untouched if it is not an array.
-- @name chunk
-- @param array an array
--- @param f an iterator function prototyped as `f (k, v, ...)`
+-- @param f an iterator function prototyped as `f (v, k, ...)`
-- @param[opt] ... Optional args to be passed to `f`
-- @return a table of chunks (arrays)
-- @see zip
-function _.chunk(array, f, ...)
- if not _.isArray(array) then return array end
- local ch, ck, prev = {}, 0
- local mask = _.map(array, f,...)
- _.each(mask, function(k,v)
- prev = (prev==nil) and v or prev
- ck = ((v~=prev) and (ck+1) or ck)
+function M.chunk(array, f, ...)
+ local ch, ck, prev, val = {}, 0
+ for k,v in ipairs(array) do
+ val = f(v, k,...)
+ prev = (prev==nil) and val or prev
+ ck = ((val~=prev) and (ck+1) or ck)
if not ch[ck] then
ch[ck] = {array[k]}
else
ch[ck][#ch[ck]+1] = array[k]
end
- prev = v
- end)
+ prev = val
+ end
return ch
end
--- Slices values indexed within `[start, finish]` range.
--- <br/><em>Aliased as `_.sub`</em>
+-- <br/><em>Aliased as `M.sub`</em>
-- @name slice
-- @param array an array
-- @param[opt] start the lower bound index, defaults to the first index in the array.
-- @param[optchain] finish the upper bound index, defaults to the array length.
-- @return a new array of sliced values
-function _.slice(array, start, finish)
- return _.select(array, function(index)
- return (index >= (start or next(array)) and index <= (finish or #array))
- end)
+function M.slice(array, start, finish)
+ local t = {}
+ for k = start or 1, finish or #array do
+ t[#t+1] = array[k]
+ end
+ return t
end
--- Returns the first N values in an array.
--- <br/><em>Aliased as `head`, `take`</em>
+-- <br/><em>Aliased as `head`, `take` </em>
-- @name first
-- @param array an array
-- @param[opt] n the number of values to be collected, defaults to 1.
@@ -939,9 +1155,13 @@ end
-- @see initial
-- @see last
-- @see rest
-function _.first(array, n)
- local n = n or 1
- return _.slice(array,1, min(n,#array))
+function M.first(array, n)
+ n = n or 1
+ local t = {}
+ for k = 1, n do
+ t[k] = array[k]
+ end
+ return t
end
--- Returns all values in an array excluding the last N values.
@@ -952,9 +1172,14 @@ end
-- @see first
-- @see last
-- @see rest
-function _.initial(array, n)
- if n and n < 0 then return end
- return _.slice(array,1, n and #array-(min(n,#array)) or #array-1)
+function M.initial(array, n)
+ local l = #array
+ n = n and l-(min(n,l)) or l-1
+ local t = {}
+ for k = 1, n do
+ t[k] = array[k]
+ end
+ return t
end
--- Returns the last N values in an array.
@@ -965,12 +1190,17 @@ end
-- @see first
-- @see initial
-- @see rest
-function _.last(array, n)
- if n and n <= 0 then return end
- return _.slice(array,n and #array-min(n-1,#array-1) or 2,#array)
+function M.last(array, n)
+ local l = #array
+ n = n and l-min(n-1,l-1) or 2
+ local t = {}
+ for k = n, l do
+ t[#t+1] = array[k]
+ end
+ return t
end
---- Removes all values before index.
+--- Returns all values after index.
-- <br/><em>Aliased as `tail`</em>
-- @name rest
-- @param array an array
@@ -979,9 +1209,12 @@ end
-- @see first
-- @see initial
-- @see last
-function _.rest(array,index)
- if index and index > #array then return {} end
- return _.slice(array,index and max(1,min(index,#array)) or 1,#array)
+function M.rest(array, index)
+ local t = {}
+ for k = index or 1, #array do
+ t[#t+1] = array[k]
+ end
+ return t
end
--- Returns the value at a given index.
@@ -989,33 +1222,35 @@ end
-- @param array an array
-- @param index an index
-- @return the value at the given index
-function _.nth(array, index)
+function M.nth(array, index)
return array[index]
end
---- Removes all falsy (false and nil) values.
+--- Returns all truthy values (removes `falses` and `nils`).
-- @name compact
-- @param array an array
-- @return a new array
-function _.compact(array)
- return _.reject(array, function (_,value)
- return not value
- end)
+function M.compact(array)
+ local t = {}
+ for k,v in pairs(array) do
+ if v then t[#t+1] = v end
+ end
+ return t
end
--- Flattens a nested array. Passing `shallow` will only flatten at the first level.
-- @name flatten
-- @param array an array
--- @param[opt] shallow specifies the flattening depth
--- @return a new array, flattened
-function _.flatten(array, shallow)
- local shallow = shallow or false
+-- @param[opt] shallow specifies the flattening depth. Defaults to `false`.`
+-- @return a flattened array
+function M.flatten(array, shallow)
+ shallow = shallow or false
local new_flattened
local _flat = {}
- for key,value in pairs(array) do
- if _.isTable(value) then
- new_flattened = shallow and value or _.flatten (value)
- _.each(new_flattened, function(_,item) _flat[#_flat+1] = item end)
+ for key,value in ipairs(array) do
+ if type(value) == 'table' then
+ new_flattened = shallow and value or M.flatten (value)
+ for k,item in ipairs(new_flattened) do _flat[#_flat+1] = item end
else _flat[#_flat+1] = value
end
end
@@ -1031,11 +1266,11 @@ end
-- @see union
-- @see intersection
-- @see symmetricDifference
-function _.difference(array, array2)
- if not array2 then return _.clone(array) end
- return _.select(array,function(i,value)
- return not _.include(array2,value)
- end)
+function M.difference(array, array2)
+ if not array2 then return M.clone(array) end
+ return M.select(array,function(value)
+ return not M.include(array2,value)
+ end)
end
--- Returns the duplicate-free union of all passed in arrays.
@@ -1045,8 +1280,8 @@ end
-- @see difference
-- @see intersection
-- @see symmetricDifference
-function _.union(...)
- return _.uniq(_.flatten({...}))
+function M.union(...)
+ return M.unique(M.flatten({...}))
end
--- Returns the intersection of all passed-in arrays.
@@ -1058,14 +1293,12 @@ end
-- @see difference
-- @see union
-- @see symmetricDifference
-function _.intersection(array, ...)
+function M.intersection(array, ...)
local arg = {...}
local _intersect = {}
for i,value in ipairs(array) do
- if _.all(arg,function(i,v)
- return _.include(v,value)
- end) then
- t_insert(_intersect,value)
+ if M.all(arg,function(v) return M.include(v,value) end) then
+ _intersect[#_intersect+1] = value
end
end
return _intersect
@@ -1081,10 +1314,10 @@ end
-- @see difference
-- @see union
-- @see intersection
-function _.symmetricDifference(array, array2)
- return _.difference(
- _.union(array, array2),
- _.intersection(array,array2)
+function M.symmetricDifference(array, array2)
+ return M.difference(
+ M.union(array, array2),
+ M.intersection(array,array2)
)
end
@@ -1094,10 +1327,10 @@ end
-- @param array an array
-- @return a new array, duplicate-free
-- @see isunique
-function _.unique(array)
+function M.unique(array)
local ret = {}
for i = 1, #array do
- if not _.find(ret, array[i]) then
+ if not M.find(ret, array[i]) then
ret[#ret+1] = array[i]
end
end
@@ -1111,8 +1344,8 @@ end
-- @param array an array
-- @return `true` if the given array is unique, `false` otherwise.
-- @see unique
-function _.isunique(array)
- return _.isEqual(array, _.unique(array))
+function M.isunique(array)
+ return #array == #(M.unique(array))
end
--- Merges values of each of the passed-in arrays in subsets.
@@ -1121,24 +1354,45 @@ end
-- @name zip
-- @param ... a variable number of array arguments
-- @return a new array
-function _.zip(...)
- local arg = {...}
- local _len = _.max(_.map(arg,function(i,v)
- return #v
- end))
+-- @see zipWith
+function M.zip(...)
+ local args = {...}
+ local n = M.max(args, function(array) return #array end)
local _ans = {}
- for i = 1,_len do
- _ans[i] = _.pluck(arg,i)
+ for i = 1,n do
+ if not _ans[i] then _ans[i] = {} end
+ for k, array in ipairs(args) do
+ if array[i] then _ans[i][#_ans[i]+1] = array[i] end
+ end
end
return _ans
end
---- Clones `array` and appends `other` values.
+--- Merges values using a given function.
+-- Only values indexed with the same key in the given arrays are merged in the same subset.
+-- Function `f` is used to combine values.
+-- <br/><em>Aliased as `transposeWith`</em>
+-- @name zipWith
+-- @param f a function
+-- @param ... a variable number of array arguments
+-- @return a flat array of results
+-- @see zip
+function M.zipWith(f, ...)
+ local args = {...}
+ local n = M.max(args, function(array) return #array end)
+ local _ans = {}
+ for i = 1,n do
+ _ans[i] = f(unpack(M.pluck(args,i)))
+ end
+ return _ans
+end
+
+--- Clones array and appends values from another array.
-- @name append
-- @param array an array
-- @param other an array
-- @return a new array
-function _.append(array, other)
+function M.append(array, other)
local t = {}
for i,v in ipairs(array) do t[i] = v end
for i,v in ipairs(other) do t[#t+1] = v end
@@ -1151,39 +1405,51 @@ end
-- @param ... a variable list of arrays
-- @return a new array
-- @see interpose
-function _.interleave(...) return _.flatten(_.zip(...)) end
+function M.interleave(...)
+ local args = {...}
+ local n = M.max(args, M.size)
+ local t = {}
+ for i = 1, n do
+ for k, array in ipairs(args) do
+ if array[i] then t[#t+1] = array[i] end
+ end
+ end
+ return t
+end
---- Interposes value in-between consecutive pair of values in `array`.
+--- Interposes value in-between consecutive pair of values in array.
+-- <br/><em>Aliased as `intersperse`</em>
-- @name interpose
--- @param value a value
-- @param array an array
+-- @param value a value
-- @return a new array
-- @see interleave
-function _.interpose(value, array)
- return _.flatten(_.zip(array, _.rep(value, #array-1)))
+function M.interpose(array, value)
+ for k = #array, 2,-1 do
+ t_insert(array, k, value)
+ end
+ return array
end
---- Produces a flexible list of numbers. If one positive value is passed, will count from 0 to that value,
--- with a default step of 1. If two values are passed, will count from the first one to the second one, with the
--- same default step of 1. A third value passed will be considered a step value.
+--- Produces a flexible list of numbers. If one value is passed, will count from 1 to that value,
+-- with a default step of 1 (or -1). If two values are passed, will count from the first one to the second one,
+-- using a default step of 1 (or -1). A third value passed will be considered a step value.
-- @name range
-- @param[opt] from the initial value of the range
-- @param[optchain] to the final value of the range
--- @param[optchain] step the step of count
+-- @param[optchain] step the step of count. Defaults to 1 or -1.
-- @return a new array of numbers
-function _.range(...)
- local arg = {...}
- local _start,_stop,_step
- if #arg==0 then return {}
- elseif #arg==1 then _stop,_start,_step = arg[1],0,1
- elseif #arg==2 then _start,_stop,_step = arg[1],arg[2],1
- elseif #arg == 3 then _start,_stop,_step = arg[1],arg[2],arg[3]
- end
- if (_step and _step==0) then return {} end
- local _ranged = {}
- local _steps = max(floor((_stop-_start)/_step),0)
- for i=1,_steps do _ranged[#_ranged+1] = _start+_step*i end
- if #_ranged>0 then t_insert(_ranged,1,_start) end
+function M.range(from, to, step)
+ if (from == nil) and (to == nil) and (step ==nil) then
+ return {}
+ elseif (from ~= nil) and (to == nil) and (step == nil) then
+ from, to, step = signum(from), from, signum(from)
+ elseif (from ~= nil) and (to ~= nil) and (step == nil) then
+ step = signum(to - from)
+ end
+ local _ranged = {from}
+ local steps = max(floor((to-from)/step),0)
+ for i=1,steps do _ranged[#_ranged+1] = from+step*i end
return _ranged
end
@@ -1192,50 +1458,94 @@ end
-- @param value a value to be repeated
-- @param n the number of repetitions of value.
-- @return a new array of `n` values
-function _.rep(value, n)
+function M.rep(value, n)
local ret = {}
- for i = 1, n do ret[#ret+1] = value end
+ for i = 1, n do ret[i] = value end
return ret
end
+--- Returns the powerset of array values. For instance, when given the set {1,2,3},
+-- returns `{{1},{2},{3},{1,2},{2,3},{1,2,3}}`.
+-- @name powerset
+-- @param array an array
+-- @return an array
+function M.powerset(array)
+ local n = #array
+ if n == 0 then return {{}} end
+ local t = {}
+ for l = 1, n do
+ for s = 1, n-l+1 do
+ t[#t+1] = M.slice(array,s,s+l-1)
+ end
+ end
+ return t
+end
+
--- Iterator returning partitions of an array. It returns arrays of length `n`
-- made of values from the given array. If the last partition has lower elements than `n` and
-- `pad` is supplied, it will be adjusted to `n` of elements with `pad` value.
-- @name partition
-- @param array an array
--- @param[opt] n the size of partitions. Should be greater than 0. Defaults to 1.
--- @param[optchain] pad a value to adjust the last subsequence to the `n` elements
+-- @param[opt] n the size of partitions. Defaults to 1.
+-- @param[optchain] pads a value to adjust the last subsequence to the `n` elements
-- @return an iterator function
-function _.partition(array, n, pad)
+-- @see overlapping
+-- @see aperture
+function M.partition(array, n, pad)
if n<=0 then return end
- return coroutine.wrap(function()
- partgen(array, n or 1, coroutine.yield, pad)
+ return wrap(function()
+ partgen(array, n or 1, yield, pad)
end)
end
---- Iterator returning sliding partitions of an array. It returns overlapping subsequences
--- of length `n`. If the last subsequence has lower elements than `n` and `pad` is
+--- Iterator returning overlapping partitions of an array.
+-- If the last subsequence has lower elements than `n` and `pad` is
-- supplied, it will be adjusted to `n` elements with `pad` value.
--- @name sliding.
+-- @name overlapping
+-- @param array an array
+-- @param[opt] n the size of partitions. Defaults to 2.
+-- @param[optchain] pads a value to adjust the last subsequence to the `n` elements
+-- @return an iterator function
+-- @see partition
+-- @see aperture
+function M.overlapping(array, n, pad)
+ if n<=1 then return end
+ return wrap(function()
+ partgen2(array, n or 2, yield, pad)
+ end)
+end
+
+--- Iterator returning sliding partitions of an array.
+-- <br/><em>Aliased as `sliding`</em>
+-- @name aperture
-- @param array an array
--- @param[opt] n the size of partitions. Should be greater than 1. Defaults to 2.
--- @param[optchain] pad a value to adjust the last subsequence to the `n` elements
+-- @param[opt] n the size of partitions. Defaults to 2 (and then behaves like @{pairwise})
-- @return an iterator function
-function _.sliding(array, n, pad)
+-- @see partition
+-- @see overlapping
+-- @see pairwise
+function M.aperture(array, n)
if n<=1 then return end
- return coroutine.wrap(function()
- partgen2(array, n or 2, coroutine.yield, pad)
+ return wrap(function()
+ partgen3(array, n or 2, yield)
end)
end
+--- Iterator returning sliding pairs of an array.
+-- @name pairwise
+-- @param array an array
+-- @return an iterator function
+-- @see overlapping
+function M.pairwise(array) return M.aperture(array, 2) end
+
--- Iterator returning the permutations of an array. It returns arrays made of all values
-- from the passed-in array, with values permuted.
-- @name permutation
-- @param array an array
-- @return an iterator function
-function _.permutation(array)
- return coroutine.wrap(function()
- permgen(array, #array, coroutine.yield)
+function M.permutation(array)
+ return wrap(function()
+ permgen(array, #array, yield)
end)
end
@@ -1245,9 +1555,11 @@ end
-- @name invert
-- @param array a given array
-- @return a new array
-function _.invert(array)
+function M.invert(array)
local _ret = {}
- _.each(array,function(i,v) _ret[v] = i end)
+ for k, v in ipairs(array) do
+ _ret[v] = k
+ end
return _ret
end
@@ -1261,34 +1573,113 @@ end
-- @param[optchain] i the starting index, defaults to 1.
-- @param[optchain] j the final index, defaults to the array length.
-- @return a string
-function _.concat(array, sep, i, j)
- local _array = _.map(array,function(i,v)
- return tostring(v)
- end)
- return t_concat(_array,sep,i or 1,j or #array)
+function M.concat(array, sep, i, j)
+ return t_concat(M.map(array,tostring),sep,i,j)
+end
+
+--- Returns all possible pairs built from given arrays.
+-- @name xprod
+-- @param array a first array
+-- @param array2 a second array
+-- @return an array list of all pairs
+function M.xprod(array, array2)
+ local p = {}
+ for i, v1 in ipairs(array) do
+ for j, v2 in ipairs(array2) do
+ p[#p+1] = {v1, v2}
+ end
+ end
+ return p
+end
+
+--- Returns the sum of array values.
+-- @name sum
+-- @param array a given array
+-- @return the sum of array values
+function M.sum(array)
+ local s = 0
+ for k, v in ipairs(array) do s = s + v end
+ return s
+end
+--- Returns the product of array values.
+-- @name product
+-- @param array a given array
+-- @return the product of array values
+function M.product(array)
+ local p = 1
+ for k, v in ipairs(array) do p = p * v end
+ return p
+end
+
+--- Returns the mean of an array of numbers.
+-- <br/><em>Aliased as `average`</em>
+-- @name mean
+-- @param array an array of numbers
+-- @return a number
+-- @see sum
+-- @see product
+-- @see median
+function M.mean(array)
+ return M.sum(array)/(#array)
+end
+
+--- Returns the median of an array of numbers.
+-- @name median
+-- @param array an array of numbers
+-- @return a number
+-- @see sum
+-- @see product
+-- @see mean
+function M.median(array)
+ local t = M.sort(M.clone(array))
+ local n = #t
+ if n == 0 then
+ return
+ elseif n==1 then
+ return t[1]
+ end
+ local mid = ceil(n/2)
+ return n%2==0 and (t[mid] + t[mid+1])/2 or t[mid]
end
--- Utility functions
-- @section Utility functions
---- The no-operation function.
+--- The no operation function.
-- @name noop
-- @return nothing
-function _.noop() return end
+function M.noop() return end
--- Returns the passed-in value. This function is used internally
-- as a default iterator.
-- @name identity
-- @param value a value
-- @return the passed-in value
-function _.identity(value) return value end
+function M.identity(value) return value end
--- Creates a constant function which returns the same output on every call.
+-- <br/><em>Aliased as `always`</em>
-- @name constant
-- @param value a constant value
-- @return a constant function
-function _.constant(value) return function() return value end end
+function M.constant(value)
+ return function() return value end
+end
+
+--- Returns a function which applies `specs` on args. This function produces an object having
+-- the same structure than `specs` by mapping each property to the result of calling its
+-- associated function with the supplied arguments
+-- @name applySpec
+-- @param specs a table
+-- @return a function
+function M.applySpec(specs)
+ return function (...)
+ local spec = {}
+ for i, f in pairs(specs) do spec[i] = f(...) end
+ return spec
+ end
+end
--- Memoizes a given function by caching the computed result.
-- Useful for speeding-up slow-running functions. If a `hash` function is passed,
@@ -1298,9 +1689,9 @@ function _.constant(value) return function() return value end end
-- @param f a function
-- @param[opt] hash a hash function, defaults to @{identity}
-- @return a new function
-function _.memoize(f, hash)
+function M.memoize(f, hash)
local _cache = setmetatable({},{__mode = 'kv'})
- local _hasher = hash or _.identity
+ local _hasher = hash or M.identity
return function (...)
local _hashKey = _hasher(...)
local _result = _cache[_hashKey]
@@ -1309,6 +1700,24 @@ function _.memoize(f, hash)
end
end
+--- Builds a list from a seed value. Accepts an iterator function, which
+-- returns either nil to stop iteration or two values : the value to add to the list
+-- of results and the seed to be used in the next call to the iterator function.
+-- @name unfold
+-- @param f an iterator function
+-- @param seed a seed value
+-- @return an array of values
+function M.unfold(f, seed)
+ local t, result = {}
+ while true do
+ result, seed = f(seed)
+ if result ~= nil then t[#t+1] = result
+ else break
+ end
+ end
+ return t
+end
+
--- Returns a version of `f` that runs only once. Successive calls to `f`
-- will keep yielding the same output, no matter what the passed-in arguments are.
-- It can be used to initialize variables.
@@ -1317,7 +1726,7 @@ end
-- @return a new function
-- @see before
-- @see after
-function _.once(f)
+function M.once(f)
local _internal = 0
local _args = {}
return function(...)
@@ -1327,7 +1736,7 @@ function _.once(f)
end
end
---- Returns a version of `f` that will run no more than `count` times. Next calls will
+--- Returns a version of `f` that will run no more than <em>count</em> times. Next calls will
-- keep yielding the results of the count-th call.
-- @name before
-- @param f a function
@@ -1335,7 +1744,7 @@ end
-- @return a new function
-- @see once
-- @see after
-function _.before(f, count)
+function M.before(f, count)
local _internal = 0
local _args = {}
return function(...)
@@ -1353,7 +1762,7 @@ end
-- @return a new function
-- @see once
-- @see before
-function _.after(f, count)
+function M.after(f, count)
local _limit,_internal = count, 0
return function(...)
_internal = _internal+1
@@ -1367,9 +1776,9 @@ end
-- @param ... a variable number of functions
-- @return a new function
-- @see pipe
-function _.compose(...)
+function M.compose(...)
-- See: https://github.com/Yonaba/Moses/pull/15#issuecomment-139038895
- local f = _.reverse {...}
+ local f = M.reverse {...}
return function (...)
local first, _temp = true
for i, func in ipairs(f) do
@@ -1391,8 +1800,8 @@ end
-- @param ... a variable number of functions
-- @return the result of the composition of function calls.
-- @see compose
-function _.pipe(value, ...)
- return _.compose(...)(value)
+function M.pipe(value, ...)
+ return M.compose(...)(value)
end
--- Returns the logical complement of a given function. For a given input, the returned
@@ -1401,7 +1810,7 @@ end
-- @name complement
-- @param f a function
-- @return the logical complement of the given function `f`.
-function _.complement(f)
+function M.complement(f)
return function(...) return not f(...) end
end
@@ -1412,9 +1821,11 @@ end
-- @param value a value
-- @param ... a variable number of functions
-- @return a list of results
-function _.juxtapose(value, ...)
+function M.juxtapose(value, ...)
local res = {}
- _.each({...}, function(_,f) res[#res+1] = f(value) end)
+ for i, func in ipairs({...}) do
+ res[i] = func(value)
+ end
return unpack(res)
end
@@ -1425,19 +1836,19 @@ end
-- @param f a function to be wrapped, prototyped as `f (...)`
-- @param wrapper a wrapper function, prototyped as `wrapper (f, ...)`
-- @return the results
-function _.wrap(f, wrapper)
+function M.wrap(f, wrapper)
return function (...) return wrapper(f,...) end
end
--- Runs `iter` function `n` times. Collects the results of each run and returns them in an array.
-- @name times
--- @param n the number of times `iter` should be called
-- @param iter an iterator function, prototyped as `iter (i, ...)`
--- @param ... args to be passed to `iter` function
+-- @param[opt] n the number of times `iter` should be called. Defaults to 1.
+-- @param[optchain] ... args to be passed to `iter` function
-- @return table an array of results
-function _.times(n, iter, ...)
+function M.times(iter, n, ...)
local results = {}
- for i = 1,n do
+ for i = 1, (n or 1) do
results[i] = iter(i,...)
end
return results
@@ -1450,11 +1861,11 @@ end
-- @return a function
-- @see bind2
-- @see bindn
--- @see bindAll
-function _.bind(f, v)
+-- @see bindall
+function M.bind(f, v)
return function (...)
- return f(v,...)
- end
+ return f(v,...)
+ end
end
--- Binds `v` to be the second argument to `f`. Calling `f (a, ...)` will result to `f (a, v, ...)`.
@@ -1464,8 +1875,8 @@ end
-- @return a function
-- @see bind
-- @see bindn
--- @see bindAll
-function _.bind2(f, v)
+-- @see bindall
+function M.bind2(f, v)
return function (t, ...)
return f(t, v, ...)
end
@@ -1479,32 +1890,48 @@ end
-- @return a function
-- @see bind
-- @see bind2
--- @see bindAll
-function _.bindn(f, ...)
- local iArg = {...}
+-- @see bindall
+function M.bindn(f, ...)
+ local args = {...}
return function (...)
- return f(unpack(_.append(iArg,{...})))
+ return f(unpack(M.append(args,{...})))
end
end
--- Binds methods to object. As such, whenever any of these methods is invoked, it
-- always receives the object as its first argument.
--- @name bindAll
+-- @name bindall
-- @param obj an abject
-- @param ... a variable number of method names
-- @return the passed-in object with all methods bound to the object itself.
-- @see bind
-- @see bind2
-- @see bindn
-function _.bindAll(obj, ...)
+function M.bindall(obj, ...)
local methodNames = {...}
- for __, methodName in ipairs(methodNames) do
+ for i, methodName in ipairs(methodNames) do
local method = obj[methodName]
- if method then obj[methodName] = _.bind(method, obj) end
+ if method then obj[methodName] = M.bind(method, obj) end
end
return obj
end
+--- Returns a function which iterate over a set of conditions. It invokes each predicate,
+-- passing it given values. It returns the value of the corresponding function of the first
+-- predicate to return a non-nil value.
+-- @name cond
+-- @param conds an array list of predicate-function pairs
+-- @return the result of invoking `f(...)` of the first predicate to return a non-nil value
+function M.cond(conds)
+ return function(...)
+ for k, condset in ipairs(conds) do
+ if condset[1](...) then
+ return condset[2](...)
+ end
+ end
+ end
+end
+
--- Generates an unique ID for the current session. If given a string `template`, it
-- will use this template for output formatting. Otherwise, if `template` is a function, it
-- will evaluate `template (id, ...)`.
@@ -1513,12 +1940,12 @@ end
-- @param[opt] template either a string or a function template to format the ID
-- @param[optchain] ... a variable number of arguments to be passed to `template`, in case it is a function.
-- @return value an ID
-function _.uniqueId(template, ...)
+function M.uniqueId(template, ...)
unique_id_counter = unique_id_counter + 1
if template then
- if _.isString(template) then
+ if type(template) == 'string' then
return template:format(unique_id_counter)
- elseif _.isFunction(template) then
+ elseif type(template) == 'function' then
return template(unique_id_counter,...)
end
end
@@ -1526,39 +1953,108 @@ function _.uniqueId(template, ...)
end
--- Produces an iterator which repeatedly apply a function `f` onto an input.
--- Yields x, then f(x), then f(f(x)), continuously.
+-- Yields `value`, then `f(value)`, then `f(f(value))`, continuously.
+-- <br/><em>Aliased as `iter`</em>.
-- @name iterator
-- @param f a function
--- @param x an initial input to `f`
+-- @param value an initial input to `f`
+-- @param[opt] n the number of times the iterator should run
-- @return an iterator function
--- <br/><em>Aliased as `iter`</em>.
-function _.iterator(f, x)
+function M.iterator(f, value, n)
+ local count = 0
return function()
- x = f(x)
- return x
+ count = count + 1
+ if n and count > n then return end
+ value = f(value)
+ return value
end
end
---- Iterates an iterator and returns its values in an array.
+--- Iterates over an iterator and returns its values in an array.
+-- <br/><em>Aliased as `tabulate`</em>.
-- @name array
--- @param ... an iterator (a function, a table and a value)
+-- @param ... an iterator function (returning a generator, a state and a value)
-- @return an array of results
-function _.array(...)
+function M.array(...)
local r = {}
for v in ... do r[#r+1] = v end
return r
end
+--- Casts vaue as an array if it is not one.
+-- @name castArray
+-- @param value a value
+-- @return an array containing the given value
+function M.castArray(value)
+ return (type(value)~='table') and {value} or value
+end
+
--- Creates a function of `f` with arguments flipped in reverse order.
-- @name flip
-- @param f a function
-- @return a function
-function _.flip(f)
+function M.flip(f)
return function(...)
- return f(unpack(_.reverse({...})))
+ return f(unpack(M.reverse({...})))
end
end
+--- Returns a function that gets the nth argument.
+-- If n is negative, the nth argument from the end is returned.
+-- @name nthArg
+-- @param n a number
+-- @return a function
+function M.nthArg(n)
+ return function (...)
+ local args = {...}
+ return args[(n < 0) and (#args + n + 1) or n]
+ end
+end
+
+--- Returns a function which accepts up to one arg. It ignores any additional arguments.
+-- @name unary
+-- @param f a function
+-- @return a function
+-- @see ary
+function M.unary(f)
+ return function (...)
+ local args = {...}
+ return f(args[1])
+ end
+end
+
+--- Returns a function which accepts up to `n` args. It ignores any additional arguments.
+-- <br/><em>Aliased as `nAry`</em>.
+-- @name ary
+-- @param f a function
+-- @param[opt] n a number. Defaults to 1.
+-- @return a function
+-- @see unary
+function M.ary(f, n)
+ n = n or 1
+ return function (...)
+ local args = {...}
+ local fargs = {}
+ for i = 1, n do fargs[i] = args[i] end
+ return f(unpack(fargs))
+ end
+end
+
+--- Returns a function which runs with arguments rearranged. Arguments are passed to the
+-- returned function in the order of supplied `indexes` at call-time.
+-- @name rearg
+-- @param f a function
+-- @param indexes an array list of indexes
+-- @return a function
+function M.rearg(f, indexes)
+ return function(...)
+ local args = {...}
+ local reargs = {}
+ for i, arg in ipairs(indexes) do reargs[i] = args[arg] end
+ return f(unpack(reargs))
+ end
+end
+
--- Creates a function that runs transforms on all arguments it receives.
-- @name over
-- @param ... a set of functions which will receive all arguments to the returned function
@@ -1566,11 +2062,11 @@ end
-- @see overEvery
-- @see overSome
-- @see overArgs
-function _.over(...)
+function M.over(...)
local transforms = {...}
return function(...)
local r = {}
- for __,transform in ipairs(transforms) do
+ for i,transform in ipairs(transforms) do
r[#r+1] = transform(...)
end
return r
@@ -1585,10 +2081,10 @@ end
-- @see over
-- @see overSome
-- @see overArgs
-function _.overEvery(...)
- local f = _.over(...)
+function M.overEvery(...)
+ local f = M.over(...)
return function(...)
- return _.reduce(f(...),function(state,v) return state and v end)
+ return M.reduce(f(...),function(state,v) return state and v end)
end
end
@@ -1600,10 +2096,10 @@ end
-- @see over
-- @see overEvery
-- @see overArgs
-function _.overSome(...)
- local f = _.over(...)
+function M.overSome(...)
+ local f = M.over(...)
return function(...)
- return _.reduce(f(...),function(state,v) return state or v end)
+ return M.reduce(f(...),function(state,v) return state or v end)
end
end
@@ -1616,7 +2112,7 @@ end
-- @see over
-- @see overEvery
-- @see overSome
-function _.overArgs(f,...)
+function M.overArgs(f,...)
local _argf = {...}
return function(...)
local _args = {...}
@@ -1628,8 +2124,16 @@ function _.overArgs(f,...)
end
end
+--- Converges two functions into one.
+-- @name converge
+-- @param f a function
+-- @param g a function
+-- @param h a function
+-- @return a new version of function f
+function M.converge(f, g, h) return function(...) return f(g(...),h(...)) end end
+
--- Partially apply a function by filling in any number of its arguments.
--- One may pass a string `'_'` as a placeholder in the list of arguments to specify an argument
+-- One may pass a string `'M'` as a placeholder in the list of arguments to specify an argument
-- that should not be pre-filled, but left open to be supplied at call-time.
-- @name partial
-- @param f a function
@@ -1637,15 +2141,15 @@ end
-- @return a new version of function f having some of it original arguments filled
-- @see partialRight
-- @see curry
-function _.partial(f,...)
+function M.partial(f,...)
local partial_args = {...}
return function (...)
local n_args = {...}
local f_args = {}
for k,v in ipairs(partial_args) do
- f_args[k] = (v == '_') and _.pop(n_args) or v
+ f_args[k] = (v == '_') and M.shift(n_args) or v
end
- return f(unpack(_.append(f_args,n_args)))
+ return f(unpack(M.append(f_args,n_args)))
end
end
@@ -1656,15 +2160,15 @@ end
-- @return a new version of function f having some of it original arguments filled
-- @see partialRight
-- @see curry
-function _.partialRight(f,...)
+function M.partialRight(f,...)
local partial_args = {...}
return function (...)
local n_args = {...}
local f_args = {}
for k = 1,#partial_args do
- f_args[k] = (partial_args[k] == '_') and _.pop(n_args) or partial_args[k]
+ f_args[k] = (partial_args[k] == '_') and M.shift(n_args) or partial_args[k]
end
- return f(unpack(_.append(n_args, f_args)))
+ return f(unpack(M.append(n_args, f_args)))
end
end
@@ -1677,7 +2181,7 @@ end
-- @return a curried version of `f`
-- @see partial
-- @see partialRight
-function _.curry(f, n_args)
+function M.curry(f, n_args)
n_args = n_args or 2
local _args = {}
local function scurry(v)
@@ -1699,7 +2203,7 @@ end
-- @param f a function
-- @param[opt] ... optional args to `f`
-- @return the execution time and the results of `f (...)`
-function _.time(f, ...)
+function M.time(f, ...)
local stime = clock()
local r = {f(...)}
return clock() - stime, unpack(r)
@@ -1712,43 +2216,58 @@ end
-- @name keys
-- @param obj an object
-- @return an array
-function _.keys(obj)
- local _oKeys = {}
- _.each(obj,function(key) _oKeys[#_oKeys+1]=key end)
- return _oKeys
+function M.keys(obj)
+ local keys = {}
+ for key in pairs(obj) do keys[#keys+1] = key end
+ return keys
end
--- Returns the values of the object properties.
-- @name values
-- @param obj an object
--- @return an array
-function _.values(obj)
- local _oValues = {}
- _.each(obj,function(_,value) _oValues[#_oValues+1]=value end)
- return _oValues
+-- @return an array of values
+function M.values(obj)
+ local values = {}
+ for key, value in pairs(obj) do values[#values+1] = value end
+ return values
+end
+
+--- Returns the value at a given path in an object.
+-- Path is given as a vararg list of keys.
+-- @name path
+-- @param obj an object
+-- @param ... a vararg list of keys
+-- @return a value or nil
+function M.path(obj, ...)
+ local value, path = obj, {...}
+ for i, p in ipairs(path) do
+ if (value[p] == nil) then return end
+ value = value[p]
+ end
+ return value
end
---- Converts keys and values a an array-list of [k, v].
+--- Converts key-value pairs to an array-list of `[k, v]` pairs.
-- @name kvpairs
-- @param obj an object
--- @return an array list of key-values pairs
+-- @return an array list of key-value pairs
-- @see toObj
-function _.kvpairs(obj)
+function M.kvpairs(obj)
local t = {}
- _.each(obj, function(k,v) t[#t+1] = {k,v} end)
+ for k,v in pairs(obj) do t[#t+1] = {k,v} end
return t
end
---- Converts an array list of `kvpairs` to an object. Keys are taken
--- from the 1rst column in the `kvpairs` sequence, associated with values in the 2nd
--- column
+--- Converts an array list of `[k,v]` pairs to an object. Keys are taken
+-- from the 1rst column in the `[k,v]` pairs sequence, associated with values in the 2nd
+-- column.
-- @name toObj
--- @param kvpairs an array-list of `kvpairs`
+-- @param kvpairs an array-list of `[k,v]` pairs
-- @return an object
-- @see kvpairs
-function _.toObj(kvpairs)
+function M.toObj(kvpairs)
local obj = {}
- for __, v in ipairs(kvpairs) do
+ for k, v in ipairs(kvpairs) do
obj[v[1]] = v[2]
end
return obj
@@ -1759,7 +2278,7 @@ end
-- @param key a key property name
-- @return a function which should accept an object as argument
-- @see propertyOf
-function _.property(key)
+function M.property(key)
return function(obj) return obj[key] end
end
@@ -1768,7 +2287,7 @@ end
-- @param obj an object
-- @return a function which should accept a key property argument
-- @see property
-function _.propertyOf(obj)
+function M.propertyOf(obj)
return function(key) return obj[key] end
end
@@ -1776,7 +2295,7 @@ end
-- @name toBoolean
-- @param value a value. Can be of any type
-- @return `true` if value is true, `false` otherwise (false or nil).
-function _.toBoolean(value)
+function M.toBoolean(value)
return not not value
end
@@ -1787,15 +2306,13 @@ end
-- @param destObj a destination object
-- @param ... a list of objects
-- @return the destination object extended
-function _.extend(destObj, ...)
+function M.extend(destObj, ...)
local sources = {...}
- _.each(sources,function(__,source)
- if _.isTable(source) then
- _.each(source,function(key,value)
- destObj[key] = value
- end)
+ for k, source in ipairs(sources) do
+ if type(source) == 'table' then
+ for key, value in pairs(source) do destObj[key] = value end
end
- end)
+ end
return destObj
end
@@ -1806,25 +2323,24 @@ end
-- @name functions
-- @param[opt] obj an object. Defaults to Moses library functions.
-- @return an array-list of methods names
-function _.functions(obj, recurseMt)
- obj = obj or _
+function M.functions(obj, recurseMt)
+ obj = obj or M
local _methods = {}
- _.each(obj,function(key,value)
- if _.isFunction(value) then
- _methods[#_methods+1]=key
+ for key, value in pairs(obj) do
+ if type(value) == 'function' then
+ _methods[#_methods+1] = key
end
- end)
- if not recurseMt then
- return _.sort(_methods)
end
- local mt = getmetatable(obj)
- if mt and mt.__index then
- local mt_methods = _.functions(mt.__index)
- _.each(mt_methods, function(k,fn)
- _methods[#_methods+1] = fn
- end)
+ if recurseMt then
+ local mt = getmetatable(obj)
+ if mt and mt.__index then
+ local mt_methods = M.functions(mt.__index, recurseMt)
+ for k, fn in ipairs(mt_methods) do
+ _methods[#_methods+1] = fn
+ end
+ end
end
- return _.sort(_methods)
+ return _methods
end
--- Clones a given object properties. If `shallow` is passed will also clone nested array properties.
@@ -1832,19 +2348,19 @@ end
-- @param obj an object
-- @param[opt] shallow whether or not nested array-properties should be cloned, defaults to false.
-- @return a copy of the passed-in object
-function _.clone(obj, shallow)
- if not _.isTable(obj) then return obj end
+function M.clone(obj, shallow)
+ if type(obj) ~= 'table' then return obj end
local _obj = {}
- _.each(obj,function(i,v)
- if _.isTable(v) then
+ for i,v in pairs(obj) do
+ if type(v) == 'table' then
if not shallow then
- _obj[i] = _.clone(v,shallow)
+ _obj[i] = M.clone(v,shallow)
else _obj[i] = v
end
else
_obj[i] = v
end
- end)
+ end
return _obj
end
@@ -1856,7 +2372,7 @@ end
-- @param f an interceptor function, should be prototyped as `f (obj, ...)`
-- @param[opt] ... args to be passed to `f`
-- @return the passed-in object
-function _.tap(obj, f, ...)
+function M.tap(obj, f, ...)
f(obj,...)
return obj
end
@@ -1866,7 +2382,7 @@ end
-- @param obj an object
-- @param key a key property to be checked
-- @return `true` or `false`
-function _.has(obj, key)
+function M.has(obj, key)
return obj[key]~=nil
end
@@ -1876,14 +2392,14 @@ end
-- @param obj an object
-- @param ... a variable number of string keys
-- @return the filtered object
-function _.pick(obj, ...)
- local whitelist = _.flatten {...}
+function M.pick(obj, ...)
+ local whitelist = M.flatten {...}
local _picked = {}
- _.each(whitelist,function(key,property)
- if not _.isNil(obj[property]) then
- _picked[property] = obj[property]
- end
- end)
+ for key, property in pairs(whitelist) do
+ if (obj[property])~=nil then
+ _picked[property] = obj[property]
+ end
+ end
return _picked
end
@@ -1893,14 +2409,14 @@ end
-- @param obj an object
-- @param ... a variable number of string keys
-- @return the filtered object
-function _.omit(obj, ...)
- local blacklist = _.flatten {...}
+function M.omit(obj, ...)
+ local blacklist = M.flatten {...}
local _picked = {}
- _.each(obj,function(key,value)
- if not _.include(blacklist,key) then
- _picked[key] = value
- end
- end)
+ for key, value in pairs(obj) do
+ if not M.include(blacklist,key) then
+ _picked[key] = value
+ end
+ end
return _picked
end
@@ -1908,12 +2424,13 @@ end
-- <br/><em>Aliased as `defaults`</em>.
-- @name template
-- @param obj an object
--- @param[opt] template a template object. Defaults to an empty table `{}`.
+-- @param[opt] template a template object. If `nil`, leaves `obj` untouched.
-- @return the passed-in object filled
-function _.template(obj, template)
- _.each(template or {},function(i,v)
- if not obj[i] then obj[i] = v end
- end)
+function M.template(obj, template)
+ if not template then return obj end
+ for i, v in pairs(template) do
+ if not obj[i] then obj[i] = v end
+ end
return obj
end
@@ -1921,13 +2438,13 @@ end
-- (by reference), nil, booleans. Compares tables by reference or by values. If `useMt`
-- is passed, the equality operator `==` will be used if one of the given objects has a
-- metatable implementing `__eq`.
--- <br/><em>Aliased as `_.compare`</em>
+-- <br/><em>Aliased as `M.compare`, `M.matches`</em>
-- @name isEqual
-- @param objA an object
-- @param objB another object
-- @param[opt] useMt whether or not `__eq` should be used, defaults to false.
-- @return `true` or `false`
-function _.isEqual(objA, objB, useMt)
+function M.isEqual(objA, objB, useMt)
local typeObjA = type(objA)
local typeObjB = type(objB)
@@ -1943,16 +2460,16 @@ function _.isEqual(objA, objB, useMt)
end
end
- if _.size(objA)~=_.size(objB) then return false end
-
- for i,v1 in pairs(objA) do
- local v2 = objB[i]
- if _.isNil(v2) or not _.isEqual(v1,v2,useMt) then return false end
+ if M.size(objA)~=M.size(objB) then return false end
+
+ local vB
+ for i,vA in pairs(objA) do
+ vB = objB[i]
+ if vB == nil or not M.isEqual(vA, vB, useMt) then return false end
end
- for i,v1 in pairs(objB) do
- local v2 = objA[i]
- if _.isNil(v2) then return false end
+ for i in pairs(objB) do
+ if objA[i] == nil then return false end
end
return true
@@ -1965,14 +2482,14 @@ end
-- @param method a string key to index in object `obj`.
-- @param[opt] ... Optional args to be passed to `method`
-- @return the returned value of `method (obj, ...)` call
-function _.result(obj, method, ...)
+function M.result(obj, method, ...)
if obj[method] then
- if _.isCallable(obj[method]) then
+ if M.isCallable(obj[method]) then
return obj[method](obj,...)
else return obj[method]
end
end
- if _.isCallable(method) then
+ if M.isCallable(method) then
return method(obj,...)
end
end
@@ -1981,7 +2498,7 @@ end
-- @name isTable
-- @param t a value to be tested
-- @return `true` or `false`
-function _.isTable(t)
+function M.isTable(t)
return type(t) == 'table'
end
@@ -1990,10 +2507,11 @@ end
-- @name isCallable
-- @param obj an object
-- @return `true` or `false`
-function _.isCallable(obj)
- return (_.isFunction(obj) or
- (_.isTable(obj) and getmetatable(obj)
- and getmetatable(obj).__call~=nil) or false)
+function M.isCallable(obj)
+ return
+ ((type(obj) == 'function') or
+ ((type(obj) == 'table') and getmetatable(obj) and getmetatable(obj).__call~=nil) or
+ false)
end
--- Checks if the given argument is an array. Assumes `obj` is an array
@@ -2001,14 +2519,14 @@ end
-- @name isArray
-- @param obj an object
-- @return `true` or `false`
-function _.isArray(obj)
- if not _.isTable(obj) then return false end
+function M.isArray(obj)
+ if not (type(obj) == 'table') then return false end
-- Thanks @Wojak and @Enrique García Cota for suggesting this
-- See : http://love2d.org/forums/viewtopic.php?f=3&t=77255&start=40#p163624
local i = 0
- for __ in pairs(obj) do
+ for k in pairs(obj) do
i = i + 1
- if _.isNil(obj[i]) then return false end
+ if obj[i] == nil then return false end
end
return true
end
@@ -2017,8 +2535,8 @@ end
-- @name isIterable
-- @param obj an object
-- @return `true` if the object can be iterated with `pairs` (or `ipairs`), `false` otherwise
-function _.isIterable(obj)
- return _.toBoolean((pcall(pairs, obj)))
+function M.isIterable(obj)
+ return M.toBoolean((pcall(pairs, obj)))
end
--- Checks if the given pbject is empty. If `obj` is a string, will return `true`
@@ -2027,10 +2545,10 @@ end
-- @name isEmpty
-- @param[opt] obj an object
-- @return `true` or `false`
-function _.isEmpty(obj)
- if _.isNil(obj) then return true end
- if _.isString(obj) then return #obj==0 end
- if _.isTable(obj) then return next(obj)==nil end
+function M.isEmpty(obj)
+ if (obj == nil) then return true end
+ if type(obj) == 'string' then return #obj==0 end
+ if type(obj) == 'table' then return next(obj)==nil end
return true
end
@@ -2038,7 +2556,7 @@ end
-- @name isString
-- @param obj an object
-- @return `true` or `false`
-function _.isString(obj)
+function M.isString(obj)
return type(obj) == 'string'
end
@@ -2046,7 +2564,7 @@ end
-- @name isFunction
-- @param obj an object
-- @return `true` or `false`
-function _.isFunction(obj)
+function M.isFunction(obj)
return type(obj) == 'function'
end
@@ -2054,7 +2572,7 @@ end
-- @name isNil
-- @param obj an object
-- @return `true` or `false`
-function _.isNil(obj)
+function M.isNil(obj)
return obj==nil
end
@@ -2063,7 +2581,7 @@ end
-- @param obj an object
-- @return `true` or `false`
-- @see isNaN
-function _.isNumber(obj)
+function M.isNumber(obj)
return type(obj) == 'number'
end
@@ -2072,16 +2590,16 @@ end
-- @param obj an object
-- @return `true` or `false`
-- @see isNumber
-function _.isNaN(obj)
- return _.isNumber(obj) and obj~=obj
+function M.isNaN(obj)
+ return type(obj) == 'number' and obj~=obj
end
--- Checks if the given argument is a finite number.
-- @name isFinite
-- @param obj an object
-- @return `true` or `false`
-function _.isFinite(obj)
- if not _.isNumber(obj) then return false end
+function M.isFinite(obj)
+ if type(obj) ~= 'number' then return false end
return obj > -huge and obj < huge
end
@@ -2089,7 +2607,7 @@ end
-- @name isBoolean
-- @param obj an object
-- @return `true` or `false`
-function _.isBoolean(obj)
+function M.isBoolean(obj)
return type(obj) == 'boolean'
end
@@ -2097,8 +2615,8 @@ end
-- @name isInteger
-- @param obj an object
-- @return `true` or `false`
-function _.isInteger(obj)
- return _.isNumber(obj) and floor(obj)==obj
+function M.isInteger(obj)
+ return type(obj) == 'number' and floor(obj)==obj
end
-- Aliases
@@ -2106,60 +2624,69 @@ end
do
-- Table functions aliases
- _.forEach = _.each
- _.forEachi = _.eachi
- _.loop = _.cycle
- _.collect = _.map
- _.inject = _.reduce
- _.foldl = _.reduce
- _.injectr = _.reduceRight
- _.foldr = _.reduceRight
- _.mapr = _.mapReduce
- _.maprr = _.mapReduceRight
- _.any = _.include
- _.some = _.include
- _.contains = _.include
- _.filter = _.select
- _.discard = _.reject
- _.every = _.all
+ M.forEach = M.each
+ M.forEachi = M.eachi
+ M.update = M.adjust
+ M.loop = M.cycle
+ M.collect = M.map
+ M.inject = M.reduce
+ M.foldl = M.reduce
+ M.injectr = M.reduceRight
+ M.foldr = M.reduceRight
+ M.mapr = M.mapReduce
+ M.maprr = M.mapReduceRight
+ M.any = M.include
+ M.some = M.include
+ M.contains = M.include
+ M.filter = M.select
+ M.discard = M.reject
+ M.every = M.all
-- Array functions aliases
- _.takeWhile = _.selectWhile
- _.rejectWhile = _.dropWhile
- _.shift = _.pop
- _.remove = _.pull
- _.rmRange = _.removeRange
- _.chop = _.removeRange
- _.sub = _.slice
- _.head = _.first
- _.take = _.first
- _.tail = _.rest
- _.skip = _.last
- _.without = _.difference
- _.diff = _.difference
- _.symdiff = _.symmetricDifference
- _.xor = _.symmetricDifference
- _.uniq = _.unique
- _.isuniq = _.isunique
- _.transpose = _.zip
- _.part = _.partition
- _.perm = _.permutation
- _.mirror = _.invert
- _.join = _.concat
+ M.takeWhile = M.selectWhile
+ M.rejectWhile = M.dropWhile
+ M.pop = M.shift
+ M.remove = M.pull
+ M.rmRange = M.removeRange
+ M.chop = M.removeRange
+ M.sub = M.slice
+ M.head = M.first
+ M.take = M.first
+ M.tail = M.rest
+ M.skip = M.last
+ M.without = M.difference
+ M.diff = M.difference
+ M.symdiff = M.symmetricDifference
+ M.xor = M.symmetricDifference
+ M.uniq = M.unique
+ M.isuniq = M.isunique
+ M.transpose = M.zip
+ M.part = M.partition
+ M.perm = M.permutation
+ M.transposeWith = M.zipWith
+ M.intersperse = M.interpose
+ M.sliding = M.aperture
+ M.mirror = M.invert
+ M.join = M.concat
+ M.average = M.mean
-- Utility functions aliases
- _.cache = _.memoize
- _.juxt = _.juxtapose
- _.uid = _.uniqueId
- _.iter = _.iterator
-
- -- Object functions aliases
- _.methods = _.functions
- _.choose = _.pick
- _.drop = _.omit
- _.defaults = _.template
- _.compare = _.isEqual
+ M.always = M.constant
+ M.cache = M.memoize
+ M.juxt = M.juxtapose
+ M.uid = M.uniqueid
+ M.iter = M.iterator
+ M.tabulate = M.array
+ M.nAry = M.ary
+ -- Object functions aliases
+ M.methods = M.functions
+ M.choose = M.pick
+ M.drop = M.omit
+ M.defaults = M.template
+ M.compare = M.isEqual
+ M.matches = M.isEqual
+
end
-- Setting chaining and building interface
@@ -2170,27 +2697,26 @@ do
local f = {}
-- Will be returned upon requiring, indexes into the wrapper
- local __ = {}
- __.__index = f
+ local Moses = {}
+ Moses.__index = f
-- Wraps a value into an instance, and returns the wrapped object
local function new(value)
- local i = {_value = value, _wrapped = true}
- return setmetatable(i, __)
+ return setmetatable({_value = value, _wrapped = true}, Moses)
end
- setmetatable(__,{
+ setmetatable(Moses,{
__call = function(self,v) return new(v) end, -- Calls returns to instantiation
__index = function(t,key,...) return f[key] end -- Redirects to the wrapper
})
--- Returns a wrapped object. Calling library functions as methods on this object
- -- will continue to return wrapped objects until @{obj:value} is used. Can be aliased as `_(value)`.
+ -- will continue to return wrapped objects until @{obj:value} is used. Can be aliased as `M(value)`.
-- @class function
-- @name chain
-- @param value a value to be wrapped
-- @return a wrapped object
- function __.chain(value)
+ function Moses.chain(value)
return new(value)
end
@@ -2198,53 +2724,59 @@ do
-- @class function
-- @name obj:value
-- @return the value previously wrapped
- function __:value()
+ function Moses:value()
return self._value
end
-- Register chaining methods into the wrapper
- f.chain, f.value = __.chain, __.value
+ f.chain, f.value = Moses.chain, Moses.value
-- Register all functions into the wrapper
- for fname,fct in pairs(_) do
- f[fname] = function(v, ...)
- local wrapped = _.isTable(v) and rawget(v,'_wrapped') or false
- if wrapped then
- local _arg = v._value
- local _rslt = fct(_arg,...)
- return new(_rslt)
- else
- return fct(v,...)
+ for fname,fct in pairs(M) do
+ if fname ~= 'operator' then -- Prevents from wrapping op functions
+ f[fname] = function(v, ...)
+ local wrapped = type(v) == 'table' and rawget(v,'_wrapped') or false
+ if wrapped then
+ local _arg = v._value
+ local _rslt = fct(_arg,...)
+ return new(_rslt)
+ else
+ return fct(v,...)
+ end
end
end
end
+
+ -- Exports all op functions
+ f.operator = M.operator
+ f.op = M.operator
--- Imports all library functions into a context.
-- @name import
- -- @param[opt] context a context. Defaults to `_G` (global environment) when not given.
- -- @param[optchain] noConflict if supplied, will not import functions having a key existing in the destination context.
+ -- @param[opt] context a context. Defaults to `_ENV or `_G`` (current environment).
+ -- @param[optchain] noConflict if supplied, will not import conflicting functions in the destination context.
-- @return the passed-in context
f.import = function(context, noConflict)
context = context or _ENV or _G
- local funcs = _.functions()
- _.each(funcs, function(k, fname)
- if rawget(context, fname) then
+ local funcs = M.functions()
+ for k, fname in ipairs(funcs) do
+ if rawget(context, fname)~= nil then
if not noConflict then
- context[fname] = _[fname]
+ rawset(context, fname, M[fname])
end
else
- context[fname] = _[fname]
+ rawset(context, fname, M[fname])
end
- end)
+ end
return context
end
-- Descriptive tags
- __._VERSION = 'Moses v'.._MODULEVERSION
- __._URL = 'http://github.com/Yonaba/Moses'
- __._LICENSE = 'MIT <http://raw.githubusercontent.com/Yonaba/Moses/master/LICENSE>'
- __._DESCRIPTION = 'utility-belt library for functional programming in Lua'
+ Moses._VERSION = 'Moses v'.._MODULEVERSION
+ Moses._URL = 'http://github.com/Yonaba/Moses'
+ Moses._LICENSE = 'MIT <http://raw.githubusercontent.com/Yonaba/Moses/master/LICENSE>'
+ Moses._DESCRIPTION = 'utility-belt library for functional programming in Lua'
- return __
+ return Moses
end
diff --git a/moses_min.lua b/moses_min.lua
index 901accd..00f471a 100644
--- a/moses_min.lua
+++ b/moses_min.lua
@@ -1,418 +1,518 @@
-local slo60nGX='1.6.1'local XKD,SWFtRywD,e,v=next,type,select,pcall
-local l6Sm5,oUA=setmetatable,getmetatable;local QFKEzBf,odpE=table.insert,table.sort;local p,lIpFkbLI=table.remove,table.concat
-local JdUtcU,GQLN,toXyq=math.randomseed,math.random,math.huge;local S9TO,pS78Y,BCf7=math.floor,math.max,math.min;local RlMSrmdD=rawget
-local VCD=table.unpack or unpack;local OV7,X83a=pairs,ipairs;local PizLA9mj=os.clock;local hUL={}local function l(VQT,Id)return VQT>Id end;local function kyWtqIf0(Ub,qJExeUn2)return
-Ub<qJExeUn2 end
-local function zupvsz(cmWo_v,RoXZEsn,BKLwtAVx)return
-
-(cmWo_v<RoXZEsn)and RoXZEsn or(cmWo_v>BKLwtAVx and BKLwtAVx or cmWo_v)end;local function Mw(hUL,BMZNmf0)return BMZNmf0 and true end
-local function S1wg_DG(qL9C)return not qL9C end
-local function sf0(Colg)local ex2xo17=0;for I,K66 in OV7(Colg)do ex2xo17=ex2xo17+1 end;return ex2xo17 end
-local function qxZa6ozV(Tq,jmB,bjO,...)local QoYPziln;local bjO=bjO or hUL.identity
-for Hj,KBlIVi in OV7(Tq)do if not QoYPziln then
-QoYPziln=bjO(KBlIVi,...)else local KBlIVi=bjO(KBlIVi,...)
-QoYPziln=jmB(QoYPziln,KBlIVi)and QoYPziln or KBlIVi end end;return QoYPziln end
-local function hgW2H5(OR8it1,GAqAsa,Oc_,Qj)
-for Ybp8=0,#OR8it1,GAqAsa do
-local ZmzyNm=hUL.slice(OR8it1,Ybp8+1,Ybp8+GAqAsa)
-if#ZmzyNm>0 then while(#ZmzyNm<GAqAsa and Qj)do
-ZmzyNm[#ZmzyNm+1]=Qj end;Oc_(ZmzyNm)end end end
-local function z5i2i(akG0mUnS,iy,gc7SaW,FnbJWd2)
-for cpdLk=0,#akG0mUnS,iy-1 do
-local FbQX=hUL.slice(akG0mUnS,cpdLk+1,cpdLk+iy)if#FbQX>0 and cpdLk+1 <#akG0mUnS then while
-(#FbQX<iy and FnbJWd2)do FbQX[#FbQX+1]=FnbJWd2 end
-gc7SaW(FbQX)end end end
-local function MGSnnzOI(ejMVLYZd,eS0X,XDQS4ASf)if eS0X==0 then XDQS4ASf(ejMVLYZd)end
-for IiNU=1,eS0X do
-ejMVLYZd[eS0X],ejMVLYZd[IiNU]=ejMVLYZd[IiNU],ejMVLYZd[eS0X]MGSnnzOI(ejMVLYZd,eS0X-1,XDQS4ASf)
-ejMVLYZd[eS0X],ejMVLYZd[IiNU]=ejMVLYZd[IiNU],ejMVLYZd[eS0X]end end;local B0o5xpg7=-1;function hUL.clear(gUfudNUg)for d3 in OV7(gUfudNUg)do gUfudNUg[d3]=nil end;return
-gUfudNUg end
-function hUL.each(gTOcAHv,vY_4HT1n,...)for DzPbzg,UMD in OV7(gTOcAHv)do
-vY_4HT1n(DzPbzg,UMD,...)end end
-function hUL.eachi(K3ZE7Ou,fBI,...)
-local wMSY=hUL.sort(hUL.select(hUL.keys(K3ZE7Ou),function(_nD2rl,aVh8xSly)return hUL.isInteger(aVh8xSly)end))
-for i,P_NNVDyt in X83a(wMSY)do fBI(P_NNVDyt,K3ZE7Ou[P_NNVDyt],...)end end
-function hUL.at(cVEyN,...)local uj2AiF={}
-for W,lbHN2 in X83a({...})do if hUL.has(cVEyN,lbHN2)then
-uj2AiF[#uj2AiF+1]=cVEyN[lbHN2]end end;return uj2AiF end
-function hUL.count(PwgW3lfq,z)if hUL.isNil(z)then return hUL.size(PwgW3lfq)end
-local sf0=0
-hUL.each(PwgW3lfq,function(K,xx)if hUL.isEqual(xx,z)then sf0=sf0+1 end end)return sf0 end
-function hUL.countf(aYb,JM2,...)return hUL.count(hUL.map(aYb,JM2,...),true)end
-function hUL.cycle(bmAjLT,eExYnwnh)eExYnwnh=eExYnwnh or 1;if eExYnwnh<=0 then return hUL.noop end
-local XMBmJyiP,nowqEU6m;local iKD8V=0
+local e='2.0.0'local v,l6Sm5,oUA,QFKEzBf=next,type,select,pcall
+local odpE,p=setmetatable,getmetatable;local lIpFkbLI,JdUtcU=table.insert,table.sort
+local GQLN,toXyq=table.remove,table.concat;local S9TO,pS78Y,BCf7=math.randomseed,math.random,math.huge
+local RlMSrmdD,VCD,OV7,X83a=math.floor,math.max,math.min,math.ceil;local PizLA9mj=coroutine.wrap;local hUL=coroutine.yield;local l=rawget
+local kyWtqIf0=table.unpack or unpack;local zupvsz,Mw=pairs,ipairs;local S1wg_DG=error;local sf0=os.clock;local qxZa6ozV={}local function hgW2H5(BKLwtAVx,BMZNmf0)
+return BKLwtAVx>BMZNmf0 end
+local function z5i2i(qL9C,Colg)return qL9C<Colg end
+local function MGSnnzOI(ex2xo17)local I=0;for K66,Tq in zupvsz(ex2xo17)do I=I+1 end;return I end
+local function B0o5xpg7(jmB,bjO,QoYPziln,...)QoYPziln=QoYPziln or qxZa6ozV.identity;local Hj
+for KBlIVi,OR8it1 in zupvsz(jmB)do if not Hj then
+Hj=QoYPziln(OR8it1,...)else local GAqAsa=QoYPziln(OR8it1,...)
+Hj=bjO(Hj,GAqAsa)and Hj or GAqAsa end end;return Hj end
+local function VQT(Oc_,Qj,Ybp8,ZmzyNm)
+for akG0mUnS=0,#Oc_,Qj do
+local iy=qxZa6ozV.slice(Oc_,akG0mUnS+1,akG0mUnS+Qj)if#iy>0 then
+while(#iy<Qj and ZmzyNm)do iy[#iy+1]=ZmzyNm end;Ybp8(iy)end end end
+local function Id(gc7SaW,FnbJWd2,cpdLk,FbQX)
+for ejMVLYZd=0,#gc7SaW,FnbJWd2-1 do
+local eS0X=qxZa6ozV.slice(gc7SaW,ejMVLYZd+1,ejMVLYZd+FnbJWd2)
+if#eS0X>0 and ejMVLYZd+1 <#gc7SaW then while
+(#eS0X<FnbJWd2 and FbQX)do eS0X[#eS0X+1]=FbQX end;cpdLk(eS0X)end end end
+local function Ub(XDQS4ASf,IiNU,gUfudNUg,d3)
+for gTOcAHv=0,#XDQS4ASf,1 do
+local vY_4HT1n=qxZa6ozV.slice(XDQS4ASf,gTOcAHv+1,gTOcAHv+IiNU)
+if#vY_4HT1n>0 and gTOcAHv+IiNU<=#XDQS4ASf then
+while(#vY_4HT1n<
+IiNU and d3)do vY_4HT1n[#vY_4HT1n+1]=d3 end;gUfudNUg(vY_4HT1n)end end end
+local function qJExeUn2(DzPbzg,UMD,K3ZE7Ou)if UMD==0 then K3ZE7Ou(DzPbzg)end;for fBI=1,UMD do
+DzPbzg[UMD],DzPbzg[fBI]=DzPbzg[fBI],DzPbzg[UMD]qJExeUn2(DzPbzg,UMD-1,K3ZE7Ou)
+DzPbzg[UMD],DzPbzg[fBI]=DzPbzg[fBI],DzPbzg[UMD]end end;local function cmWo_v(wMSY)return wMSY>=0 and 1 or-1 end;local RoXZEsn=-1
+qxZa6ozV.operator={}
+qxZa6ozV.operator.add=function(_nD2rl,aVh8xSly)return _nD2rl+aVh8xSly end
+qxZa6ozV.operator.sub=function(i,P_NNVDyt)return i-P_NNVDyt end
+qxZa6ozV.operator.mul=function(cVEyN,uj2AiF)return cVEyN*uj2AiF end
+qxZa6ozV.operator.div=function(W,lbHN2)return W/lbHN2 end
+qxZa6ozV.operator.mod=function(PwgW3lfq,z)return PwgW3lfq%z end;qxZa6ozV.operator.exp=function(K,xx)return K^xx end
+qxZa6ozV.operator.pow=qxZa6ozV.operator.exp;qxZa6ozV.operator.unm=function(aYb)return-aYb end
+qxZa6ozV.operator.neg=qxZa6ozV.operator.unm
+qxZa6ozV.operator.floordiv=function(JM2,bmAjLT)return RlMSrmdD(JM2/bmAjLT)end
+qxZa6ozV.operator.intdiv=function(eExYnwnh,XMBmJyiP)
+return
+eExYnwnh>=0 and RlMSrmdD(eExYnwnh/XMBmJyiP)or X83a(eExYnwnh/XMBmJyiP)end
+qxZa6ozV.operator.eq=function(nowqEU6m,iKD8V)return nowqEU6m==iKD8V end
+qxZa6ozV.operator.neq=function(YtRS,A)return YtRS~=A end
+qxZa6ozV.operator.lt=function(mHJ,Q57BJ)return mHJ<Q57BJ end
+qxZa6ozV.operator.gt=function(vM,JeGCDX)return vM>JeGCDX end
+qxZa6ozV.operator.le=function(A,UFZlp)return A<=UFZlp end
+qxZa6ozV.operator.ge=function(VsrKM,uhIq)return VsrKM>=uhIq end
+qxZa6ozV.operator.land=function(EEOUzhy,hbrt)return EEOUzhy and hbrt end;qxZa6ozV.operator.lor=function(D,Q)return D or Q end;qxZa6ozV.operator.lnot=function(mRqle)return
+not mRqle end
+qxZa6ozV.operator.concat=function(sBEZ8,WhHB0ygh)return
+sBEZ8 ..WhHB0ygh end
+qxZa6ozV.operator.length=function(rYSD0)return#rYSD0 end;qxZa6ozV.operator.len=qxZa6ozV.operator.length
+function qxZa6ozV.clear(BIL5)for GQLlkH in
+zupvsz(BIL5)do BIL5[GQLlkH]=nil end;return BIL5 end;function qxZa6ozV.each(aN4J2zRQ,eWca,...)
+for AGUR2QK,FK in zupvsz(aN4J2zRQ)do eWca(FK,AGUR2QK,...)end end
+function qxZa6ozV.eachi(_,YQZ729qQ,...)
+local rZh2wG=qxZa6ozV.sort(qxZa6ozV.select(qxZa6ozV.keys(_),qxZa6ozV.isInteger))for sef4eW6Q,Z in Mw(rZh2wG)do YQZ729qQ(_[Z],Z,...)end end
+function qxZa6ozV.at(UacO6D,...)local FdnzjW={}for o,lMAL in Mw({...})do
+FdnzjW[#FdnzjW+1]=UacO6D[lMAL]end;return FdnzjW end
+function qxZa6ozV.adjust(CpQ,L,HnQS_Z,...)if(CpQ[L]==nil)then
+S1wg_DG("key not existing in table")end;local rib=qxZa6ozV.clone(CpQ)
+rib[L]=
+l6Sm5(HnQS_Z)=='function'and HnQS_Z(rib[L],...)or HnQS_Z;return rib end
+function qxZa6ozV.count(w,YT6wZ)if YT6wZ==nil then return qxZa6ozV.size(w)end
+local MGSnnzOI=0;for VYv,gU in zupvsz(w)do
+if qxZa6ozV.isEqual(gU,YT6wZ)then MGSnnzOI=MGSnnzOI+1 end end;return MGSnnzOI end
+function qxZa6ozV.countf(JzG8W4Ya,dZ54oc,...)local MGSnnzOI=0;for v_LoR,gRY in zupvsz(JzG8W4Ya)do if dZ54oc(gRY,v_LoR,...)then
+MGSnnzOI=MGSnnzOI+1 end end;return
+MGSnnzOI end
+function qxZa6ozV.cycle(z,ad)ad=ad or 1;if ad<=0 then return qxZa6ozV.noop end;local Ui0Qa,g
+local Itx=0
while true do
return
-function()
-XMBmJyiP=XMBmJyiP and XKD(bmAjLT,XMBmJyiP)or XKD(bmAjLT)
-nowqEU6m=not nowqEU6m and XMBmJyiP or nowqEU6m
-if eExYnwnh then
-iKD8V=(XMBmJyiP==nowqEU6m)and iKD8V+1 or iKD8V;if iKD8V>eExYnwnh then return end end;return XMBmJyiP,bmAjLT[XMBmJyiP]end end end
-function hUL.map(YtRS,A,...)local mHJ={}
-for Q57BJ,vM in OV7(YtRS)do local JeGCDX,AUFZlp,VsrKM=Q57BJ,A(Q57BJ,vM,...)mHJ[VsrKM and AUFZlp or
-JeGCDX]=VsrKM or AUFZlp end;return mHJ end
-function hUL.reduce(uhIq,EEOUzhy,hbrt)for D,Q in OV7(uhIq)do
-if hbrt==nil then hbrt=Q else hbrt=EEOUzhy(hbrt,Q)end end;return hbrt end;function hUL.reduceby(mRqle,sBEZ8,WhHB0ygh,rYSD0,...)
-return hUL.reduce(hUL.select(mRqle,rYSD0,...),sBEZ8,WhHB0ygh)end
-function hUL.reduceRight(BIL5,GQLlkH,aN4J2zRQ)return
-hUL.reduce(hUL.reverse(BIL5),GQLlkH,aN4J2zRQ)end
-function hUL.mapReduce(eWca,AGUR2QK,FK)local _={}for YQZ729qQ,rZh2wG in OV7(eWca)do
-_[YQZ729qQ]=not FK and rZh2wG or AGUR2QK(FK,rZh2wG)FK=_[YQZ729qQ]end;return _ end;function hUL.mapReduceRight(sef4eW6Q,Z,UacO6D)
-return hUL.mapReduce(hUL.reverse(sef4eW6Q),Z,UacO6D)end
-function hUL.include(FdnzjW,o)local lMAL=
-hUL.isFunction(o)and o or hUL.isEqual;for CpQ,L in OV7(FdnzjW)do if
-lMAL(L,o)then return true end end;return false end
-function hUL.detect(HnQS_Z,rib)
-local w=hUL.isFunction(rib)and rib or hUL.isEqual
-for YT6wZ,VYv in OV7(HnQS_Z)do if w(VYv,rib)then return YT6wZ end end end
-function hUL.where(gU,JzG8W4Ya)
-local dZ54oc=hUL.select(gU,function(v_LoR,gRY)for z in OV7(JzG8W4Ya)do
-if gRY[z]~=JzG8W4Ya[z]then return false end end;return true end)return#dZ54oc>0 and dZ54oc or nil end
-function hUL.findWhere(ad,Ui0Qa)
-local g=hUL.detect(ad,function(Itx)for JpoaGH in OV7(Ui0Qa)do
-if Ui0Qa[JpoaGH]~=Itx[JpoaGH]then return false end end;return true end)return g and ad[g]end
-function hUL.select(cyAcCT,RCA,...)local L46S={}
-for GKTYT,hXSTz8FJ in OV7(cyAcCT)do if RCA(GKTYT,hXSTz8FJ,...)then
-L46S[#L46S+1]=hXSTz8FJ end end;return L46S end
-function hUL.reject(C24r7o4G,b_4Q38cU,...)local N=hUL.map(C24r7o4G,b_4Q38cU,...)local JbPw={}
-for j,S in OV7(N)do if not S then JbPw[
-#JbPw+1]=C24r7o4G[j]end end;return JbPw end
-function hUL.all(cg4FV7bl,flf9sWX,...)return
-(
-(#hUL.select(hUL.map(cg4FV7bl,flf9sWX,...),Mw))==sf0(cg4FV7bl))end
-function hUL.invoke(uNoS,ZWoH9V08,...)local RWo={...}
+function()Ui0Qa=Ui0Qa and v(z,Ui0Qa)or v(z)
+g=not g and Ui0Qa or g;if ad then Itx=(Ui0Qa==g)and Itx+1 or Itx
+if Itx>ad then return end end;return z[Ui0Qa],Ui0Qa end end end
+function qxZa6ozV.map(JpoaGH,cyAcCT,...)local RCA={}
+for L46S,GKTYT in zupvsz(JpoaGH)do
+local hXSTz8FJ,C24r7o4G,b_4Q38cU=L46S,cyAcCT(GKTYT,L46S,...)
+RCA[b_4Q38cU and C24r7o4G or hXSTz8FJ]=b_4Q38cU or C24r7o4G end;return RCA end
+function qxZa6ozV.reduce(N,JbPw,j)for S,cg4FV7bl in zupvsz(N)do
+if j==nil then j=cg4FV7bl else j=JbPw(j,cg4FV7bl)end end;return j end
+function qxZa6ozV.reduceby(flf9sWX,uNoS,ZWoH9V08,RWo,...)return
+qxZa6ozV.reduce(qxZa6ozV.select(flf9sWX,ZWoH9V08,...),uNoS,RWo)end
+function qxZa6ozV.reduceRight(GWBQL,PCldTUn9,sO_)return
+qxZa6ozV.reduce(qxZa6ozV.reverse(GWBQL),PCldTUn9,sO_)end
+function qxZa6ozV.mapReduce(ALbdmINL,b,DUgF0E)local vGxJ6f={}
+for a4ga2I,syGyB_ in zupvsz(ALbdmINL)do vGxJ6f[a4ga2I]=not DUgF0E and syGyB_ or
+b(DUgF0E,syGyB_)DUgF0E=vGxJ6f[a4ga2I]end;return vGxJ6f end
+function qxZa6ozV.mapReduceRight(VO,J1r,iBcU3_7D)return
+qxZa6ozV.mapReduce(qxZa6ozV.reverse(VO),J1r,iBcU3_7D)end
+function qxZa6ozV.include(N,M4V)local _feve=(l6Sm5(M4V)=='function')and M4V or
+qxZa6ozV.isEqual;for OPz_7bk,H64aD in zupvsz(N)do if
+_feve(H64aD,M4V)then return true end end;return false end
+function qxZa6ozV.detect(ny7,QDj6GAX)
+local k6pXzd=
+(l6Sm5(QDj6GAX)=='function')and QDj6GAX or qxZa6ozV.isEqual
+for hsLwu,R in zupvsz(ny7)do if k6pXzd(R,QDj6GAX)then return hsLwu end end end
+function qxZa6ozV.where(JKZ,yHbsh)
+local d4z=qxZa6ozV.select(JKZ,function(i)
+for HyEk4lbh in zupvsz(yHbsh)do if i[HyEk4lbh]~=yHbsh[HyEk4lbh]then return
+false end end;return true end)return#d4z>0 and d4z or nil end
+function qxZa6ozV.findWhere(PhU,rWwbNge)
+local SKxD=qxZa6ozV.detect(PhU,function(o3uQKvJ)
+for vAZm in zupvsz(rWwbNge)do if
+rWwbNge[vAZm]~=o3uQKvJ[vAZm]then return false end end;return true end)return SKxD and PhU[SKxD]end
+function qxZa6ozV.select(q,fFuE,...)local KypMW={}for JJT4nKO,TFLF in zupvsz(q)do if fFuE(TFLF,JJT4nKO,...)then
+KypMW[#KypMW+1]=TFLF end end
+return KypMW end
+function qxZa6ozV.reject(hEoAa,PGN,...)local K2_kF5={}
+for YpimJ,Gg7Ttui in zupvsz(hEoAa)do if not PGN(Gg7Ttui,YpimJ,...)then
+K2_kF5[#K2_kF5+1]=Gg7Ttui end end;return K2_kF5 end
+function qxZa6ozV.all(_,EGeAf,...)for ymP,z5pHKyoa in zupvsz(_)do
+if not EGeAf(z5pHKyoa,ymP,...)then return false end end;return true end
+function qxZa6ozV.invoke(h,xwT,...)local y33ux={...}
return
-hUL.map(uNoS,function(GWBQL,PCldTUn9)
-if hUL.isTable(PCldTUn9)then
-if hUL.has(PCldTUn9,ZWoH9V08)then if
-hUL.isCallable(PCldTUn9[ZWoH9V08])then return PCldTUn9[ZWoH9V08](PCldTUn9,VCD(RWo))else return
-PCldTUn9[ZWoH9V08]end else
+qxZa6ozV.map(h,function(Ut)
+if(l6Sm5(Ut)=='table')then
+if Ut[xwT]then
if
-hUL.isCallable(ZWoH9V08)then return ZWoH9V08(PCldTUn9,VCD(RWo))end end elseif hUL.isCallable(ZWoH9V08)then return ZWoH9V08(PCldTUn9,VCD(RWo))end end)end
-function hUL.pluck(sO_,ALbdmINL)return
-hUL.reject(hUL.map(sO_,function(b,DUgF0E)return DUgF0E[ALbdmINL]end),S1wg_DG)end
-function hUL.max(vGxJ6f,a4ga2I,...)return qxZa6ozV(vGxJ6f,l,a4ga2I,...)end
-function hUL.min(syGyB_,VO,...)return qxZa6ozV(syGyB_,kyWtqIf0,VO,...)end
-function hUL.shuffle(J1r,iBcU3_7D)if iBcU3_7D then JdUtcU(iBcU3_7D)end;local N={}
-hUL.each(J1r,function(M4V,_feve)local OPz_7bk=
-S9TO(GQLN()*M4V)+1;N[M4V]=N[OPz_7bk]N[OPz_7bk]=_feve end)return N end
-function hUL.same(H64aD,ny7)
-return
-hUL.all(H64aD,function(QDj6GAX,k6pXzd)return hUL.include(ny7,k6pXzd)end)and
-hUL.all(ny7,function(hsLwu,R)return hUL.include(H64aD,R)end)end;function hUL.sort(JKZ,yHbsh)odpE(JKZ,yHbsh)return JKZ end
-function hUL.sortBy(d4z,i,HyEk4lbh)local PhU=i or
-hUL.identity;if hUL.isString(i)then
-PhU=function(d4z)return d4z[i]end end;HyEk4lbh=HyEk4lbh or kyWtqIf0
-local rWwbNge={}
-hUL.each(d4z,function(SKxD,o3uQKvJ)
-rWwbNge[#rWwbNge+1]={value=o3uQKvJ,transform=PhU(o3uQKvJ)}end)
-odpE(rWwbNge,function(vAZm,q)return HyEk4lbh(vAZm.transform,q.transform)end)return hUL.pluck(rWwbNge,'value')end
-function hUL.groupBy(fFuE,KypMW,...)local JJT4nKO={...}local TFLF={}
-hUL.each(fFuE,function(hEoAa,PGN)
-local K2_kF5=KypMW(hEoAa,PGN,VCD(JJT4nKO))if TFLF[K2_kF5]then
-TFLF[K2_kF5][#TFLF[K2_kF5]+1]=PGN else TFLF[K2_kF5]={PGN}end end)return TFLF end
-function hUL.countBy(YpimJ,Gg7Ttui,...)local _={...}local EGeAf={}
-hUL.each(YpimJ,function(ymP,z5pHKyoa)
-local h=Gg7Ttui(ymP,z5pHKyoa,VCD(_))EGeAf[h]=(EGeAf[h]or 0)+1 end)return EGeAf end
-function hUL.size(...)local xwT={...}local y33ux=xwT[1]if hUL.isTable(y33ux)then return sf0(xwT[1])else return
-sf0(xwT)end end;function hUL.containsKeys(Ut,GOijBp)
-for oUi in OV7(GOijBp)do if not Ut[oUi]then return false end end;return true end
-function hUL.sameKeys(b2a3,xer)
-for SQHAAR in
-OV7(b2a3)do if not xer[SQHAAR]then return false end end
-for qybRcP1 in OV7(xer)do if not b2a3[qybRcP1]then return false end end;return true end
-function hUL.sample(z,N0NaR,FBfW)N0NaR=N0NaR or 1;if N0NaR<1 then return end;if N0NaR==1 then
-if FBfW then JdUtcU(FBfW)end;return z[GQLN(1,#z)]end;return
-hUL.slice(hUL.shuffle(z,FBfW),1,N0NaR)end
-function hUL.sampleProb(lnM4,_oDmX_,t)if t then JdUtcU(t)end;return
-hUL.select(lnM4,function(hUL,K)return GQLN()<_oDmX_ end)end;function hUL.toArray(...)return{...}end
-function hUL.find(ppm021I,ASUXhD,KCm)for u=KCm or 1,#ppm021I do if
-hUL.isEqual(ppm021I[u],ASUXhD)then return u end end end;function hUL.reverse(fDk)local gxYY={}
-for sVMxk=#fDk,1,-1 do gxYY[#gxYY+1]=fDk[sVMxk]end;return gxYY end
-function hUL.fill(SyD,v4,j7siW,Hl)Hl=Hl or
-hUL.size(SyD)for j7siW=j7siW or 1,Hl do SyD[j7siW]=v4 end;return SyD end
-function hUL.selectWhile(AP060rq,DIEKD10,...)local lLJ={}for EicsS,JubU in X83a(AP060rq)do
-if DIEKD10(EicsS,JubU,...)then lLJ[EicsS]=JubU else break end end;return lLJ end
-function hUL.dropWhile(L,JKci,...)local SsBe;for o,ZOmcmO in X83a(L)do
-if not JKci(o,ZOmcmO,...)then SsBe=o;break end end
-if hUL.isNil(SsBe)then return{}end;return hUL.rest(L,SsBe)end
-function hUL.sortedIndex(_G19JrRB,m0r3_J,MLrs,hP5)local oqjhEZb0=MLrs or kyWtqIf0;if hP5 then
-hUL.sort(_G19JrRB,oqjhEZb0)end
-for Pha=1,#_G19JrRB do if
-not oqjhEZb0(_G19JrRB[Pha],m0r3_J)then return Pha end end;return#_G19JrRB+1 end;function hUL.indexOf(G,MOrzq4)
-for bEMp=1,#G do if G[bEMp]==MOrzq4 then return bEMp end end end
-function hUL.lastIndexOf(dd,MOQN)
-local O=hUL.indexOf(hUL.reverse(dd),MOQN)if O then return#dd-O+1 end end;function hUL.findIndex(FEpet,P,...)
-for G=1,#FEpet do if P(G,FEpet[G],...)then return G end end end
-function hUL.findLastIndex(EcLLM,wo,...)
-local ur=hUL.findIndex(hUL.reverse(EcLLM),wo,...)if ur then return#EcLLM-ur+1 end end;function hUL.addTop(XTX,...)
-hUL.each({...},function(wc8hjKp1,f)QFKEzBf(XTX,1,f)end)return XTX end;function hUL.push(Hjag,...)
-hUL.each({...},function(Yg,uc)Hjag[
-#Hjag+1]=uc end)return Hjag end
-function hUL.pop(bw,ad)
-ad=BCf7(ad or 1,#bw)local EG344W={}
-for MVlUhPEM=1,ad do local LT=bw[1]EG344W[#EG344W+1]=LT;p(bw,1)end;return VCD(EG344W)end
-function hUL.unshift(pfiWYrg,smnX9H6)smnX9H6=BCf7(smnX9H6 or 1,#pfiWYrg)local FzRhHR={}for mMBxOoQa=1,smnX9H6 do local xYSLIT=pfiWYrg[
-#pfiWYrg]FzRhHR[#FzRhHR+1]=xYSLIT
-p(pfiWYrg)end;return VCD(FzRhHR)end
-function hUL.pull(Eae7ILmk,...)for Jy23ZRAA,V8IWw in X83a({...})do
-for uyYdf=#Eae7ILmk,1,-1 do if hUL.isEqual(Eae7ILmk[uyYdf],V8IWw)then
-p(Eae7ILmk,uyYdf)end end end
-return Eae7ILmk end
-function hUL.removeRange(K,ZX,tbdC)local K=hUL.clone(K)local VaY3,HK7Mbgze=(XKD(K)),#K
-if HK7Mbgze<1 then return K end;ZX=zupvsz(ZX or VaY3,VaY3,HK7Mbgze)
-tbdC=zupvsz(tbdC or HK7Mbgze,VaY3,HK7Mbgze)if tbdC<ZX then return K end;local sf0=tbdC-ZX+1;local VaY3=ZX;while sf0 >0 do p(K,VaY3)
-sf0=sf0-1 end;return K end
-function hUL.chunk(VXPfx,j3Qk,...)if not hUL.isArray(VXPfx)then return VXPfx end
-local X1,GpruB,r={},0;local V7YqV=hUL.map(VXPfx,j3Qk,...)
-hUL.each(V7YqV,function(JbvH7,Cqk9Luq)
-r=(r==nil)and Cqk9Luq or r
-GpruB=((Cqk9Luq~=r)and(GpruB+1)or GpruB)if not X1[GpruB]then X1[GpruB]={VXPfx[JbvH7]}else
-X1[GpruB][#X1[GpruB]+1]=VXPfx[JbvH7]end;r=Cqk9Luq end)return X1 end
-function hUL.slice(PeAP9X,vN5AF9,j)return
-hUL.select(PeAP9X,function(EOgmP)return
-(EOgmP>= (vN5AF9 or XKD(PeAP9X))and EOgmP<= (j or
-#PeAP9X))end)end
-function hUL.first(j,mJof)local mJof=mJof or 1;return hUL.slice(j,1,BCf7(mJof,#j))end
-function hUL.initial(yz1Kuwby,KVE6TG)if KVE6TG and KVE6TG<0 then return end;return
-hUL.slice(yz1Kuwby,1,KVE6TG and#yz1Kuwby- (BCf7(KVE6TG,
-#yz1Kuwby))or#
-yz1Kuwby-1)end;function hUL.last(YY,r9)if r9 and r9 <=0 then return end
-return hUL.slice(YY,r9 and
-#YY-BCf7(r9-1,#YY-1)or 2,#YY)end;function hUL.rest(mtUG,PFRuf)if PFRuf and
-PFRuf>#mtUG then return{}end
-return hUL.slice(mtUG,PFRuf and
-pS78Y(1,BCf7(PFRuf,#mtUG))or 1,#mtUG)end;function hUL.nth(KhK1gRj9,Xgj)return
-KhK1gRj9[Xgj]end;function hUL.compact(Ko)return
-hUL.reject(Ko,function(hUL,A)return not A end)end
-function hUL.flatten(IU6Om,sKIIqz)local sKIIqz=
-sKIIqz or false;local wmhARqEa;local _RT3={}
-for V,BTA in OV7(IU6Om)do
-if hUL.isTable(BTA)then wmhARqEa=
-sKIIqz and BTA or hUL.flatten(BTA)
-hUL.each(wmhARqEa,function(hUL,QVEYENaX)
-_RT3[#_RT3+1]=QVEYENaX end)else _RT3[#_RT3+1]=BTA end end;return _RT3 end
-function hUL.difference(gxqa,q4)if not q4 then return hUL.clone(gxqa)end;return
-hUL.select(gxqa,function(QyKi,_o3FE)return not
-hUL.include(q4,_o3FE)end)end
-function hUL.union(...)return hUL.uniq(hUL.flatten({...}))end
-function hUL.intersection(n,...)local WM={...}local zb8b={}
-for YBqeh,WRkIg in X83a(n)do if hUL.all(WM,function(YBqeh,RH_vLUg)
-return hUL.include(RH_vLUg,WRkIg)end)then
-QFKEzBf(zb8b,WRkIg)end end;return zb8b end
-function hUL.symmetricDifference(aEH,g20N7)return
-hUL.difference(hUL.union(aEH,g20N7),hUL.intersection(aEH,g20N7))end
-function hUL.unique(puZN)local _Dy={}for MC=1,#puZN do if not hUL.find(_Dy,puZN[MC])then
-_Dy[#_Dy+1]=puZN[MC]end end;return _Dy end;function hUL.isunique(WOBSVeqF)
-return hUL.isEqual(WOBSVeqF,hUL.unique(WOBSVeqF))end
-function hUL.zip(...)local A={...}
-local vqW6=hUL.max(hUL.map(A,function(rBRXA,qfFSJN)
-return#qfFSJN end))local R4oRlgh={}
-for Va8fT08T=1,vqW6 do R4oRlgh[Va8fT08T]=hUL.pluck(A,Va8fT08T)end;return R4oRlgh end
-function hUL.append(d778,aZT)local ni9je9bJ={}
-for uwwNE,X40cF in X83a(d778)do ni9je9bJ[uwwNE]=X40cF end
-for EW,asgq in X83a(aZT)do ni9je9bJ[#ni9je9bJ+1]=asgq end;return ni9je9bJ end
-function hUL.interleave(...)return hUL.flatten(hUL.zip(...))end
-function hUL.interpose(IQybL1,hYKT45)return
-hUL.flatten(hUL.zip(hYKT45,hUL.rep(IQybL1,#hYKT45-1)))end
-function hUL.range(...)local Rq7={...}local LQ_EIcl,uaL,gujcrFp
-if#Rq7 ==0 then return{}elseif#Rq7 ==1 then
-uaL,LQ_EIcl,gujcrFp=Rq7[1],0,1 elseif#Rq7 ==2 then LQ_EIcl,uaL,gujcrFp=Rq7[1],Rq7[2],1 elseif#Rq7 ==3 then
-LQ_EIcl,uaL,gujcrFp=Rq7[1],Rq7[2],Rq7[3]end;if(gujcrFp and gujcrFp==0)then return{}end;local ph06vXj={}
-local nH0LB4c=pS78Y(S9TO((
-uaL-LQ_EIcl)/gujcrFp),0)for ALwJ9=1,nH0LB4c do
-ph06vXj[#ph06vXj+1]=LQ_EIcl+gujcrFp*ALwJ9 end;if#ph06vXj>0 then
-QFKEzBf(ph06vXj,1,LQ_EIcl)end;return ph06vXj end
-function hUL.rep(_X,ruXMob)local E={}for jcgjAE=1,ruXMob do E[#E+1]=_X end;return E end
-function hUL.partition(BZmaGN,HSav,sDjMr)if HSav<=0 then return end
-return coroutine.wrap(function()
-hgW2H5(BZmaGN,HSav or 1,coroutine.yield,sDjMr)end)end
-function hUL.sliding(biQX3Ut,BLEXN_,Ljc)if BLEXN_<=1 then return end
-return coroutine.wrap(function()
-z5i2i(biQX3Ut,BLEXN_ or 2,coroutine.yield,Ljc)end)end;function hUL.permutation(fpN7T)
-return coroutine.wrap(function()
-MGSnnzOI(fpN7T,#fpN7T,coroutine.yield)end)end;function hUL.invert(FNSk_)local LmE={}hUL.each(FNSk_,function(pZTFVP,XL)
-LmE[XL]=pZTFVP end)
-return LmE end
-function hUL.concat(L5vC0Jx,vpONJ,A,LN)
-local dA14qP=hUL.map(L5vC0Jx,function(A,JcQc)return
-tostring(JcQc)end)return lIpFkbLI(dA14qP,vpONJ,A or 1,LN or#L5vC0Jx)end;function hUL.noop()return end;function hUL.identity(hDih6_D)return hDih6_D end
-function hUL.constant(QKbZ464i)return function()return
-QKbZ464i end end
-function hUL.memoize(F1TsZ,uF2)local T=l6Sm5({},{__mode='kv'})
-local pC_=uF2 or hUL.identity
-return function(...)local ju=pC_(...)local deu1=T[ju]if not deu1 then T[ju]=F1TsZ(...)end;return
-T[ju]end end
-function hUL.once(IgZ6)local kVRiv3F=0;local kWMf={}
-return function(...)kVRiv3F=kVRiv3F+1
-if kVRiv3F<=1 then kWMf={...}end;return IgZ6(VCD(kWMf))end end
-function hUL.before(DawC,sf0)local cP=0;local w={}return function(...)cP=cP+1;if cP<=sf0 then w={...}end
-return DawC(VCD(w))end end
-function hUL.after(UZ,sf0)local tdH,ymt=sf0,0;return
-function(...)ymt=ymt+1;if ymt>=tdH then return UZ(...)end end end
-function hUL.compose(...)local WxGA=hUL.reverse{...}
+qxZa6ozV.isCallable(Ut[xwT])then return Ut[xwT](Ut,kyWtqIf0(y33ux))else return Ut[xwT]end else
+if qxZa6ozV.isCallable(xwT)then return xwT(Ut,kyWtqIf0(y33ux))end end elseif qxZa6ozV.isCallable(xwT)then return xwT(Ut,kyWtqIf0(y33ux))end end)end
+function qxZa6ozV.pluck(GOijBp,oUi)local b2a3={}for xer,SQHAAR in zupvsz(GOijBp)do if SQHAAR[oUi]then
+b2a3[#b2a3+1]=SQHAAR[oUi]end end;return b2a3 end
+function qxZa6ozV.max(qybRcP1,z,...)return B0o5xpg7(qybRcP1,hgW2H5,z,...)end
+function qxZa6ozV.min(N0NaR,FBfW,...)return B0o5xpg7(N0NaR,z5i2i,FBfW,...)end
+function qxZa6ozV.same(lnM4,_oDmX_)
return
-function(...)local jBuHkH,E3=true
-for CZi_zK,_6KCMph in X83a(WxGA)do if jBuHkH then jBuHkH=false
-E3=_6KCMph(...)else E3=_6KCMph(E3)end end;return E3 end end
-function hUL.pipe(PY3VqYZ8,...)return hUL.compose(...)(PY3VqYZ8)end
-function hUL.complement(V)return function(...)return not V(...)end end;function hUL.juxtapose(y,...)local QF={}
-hUL.each({...},function(hUL,hN)QF[#QF+1]=hN(y)end)return VCD(QF)end
-function hUL.wrap(hVflx4kh,GP)return function(...)return
-GP(hVflx4kh,...)end end;function hUL.times(oCZYv2dT,RLaqM3,...)local PoH={}
-for xM709D=1,oCZYv2dT do PoH[xM709D]=RLaqM3(xM709D,...)end;return PoH end
-function hUL.bind(z50,sAPD)return function(...)return
-z50(sAPD,...)end end;function hUL.bind2(AVFi,GGKI)
-return function(gWaGu,...)return AVFi(gWaGu,GGKI,...)end end;function hUL.bindn(SFKM,...)local j6jQmlbr={...}
+qxZa6ozV.all(lnM4,function(t)return qxZa6ozV.include(_oDmX_,t)end)and
+qxZa6ozV.all(_oDmX_,function(K)return qxZa6ozV.include(lnM4,K)end)end
+function qxZa6ozV.sort(ppm021I,ASUXhD)JdUtcU(ppm021I,ASUXhD)return ppm021I end
+function qxZa6ozV.sortBy(KCm,u,fDk)local gxYY=u or qxZa6ozV.identity
+if
+(l6Sm5(u)=='string')then gxYY=function(KCm)return KCm[u]end end;fDk=fDk or z5i2i
+JdUtcU(KCm,function(sVMxk,SyD)return fDk(gxYY(sVMxk),gxYY(SyD))end)return KCm end
+function qxZa6ozV.groupBy(v4,j7siW,...)local Hl={...}local AP060rq={}
+for DIEKD10,lLJ in zupvsz(v4)do
+local EicsS=j7siW(lLJ,DIEKD10,kyWtqIf0(Hl))if AP060rq[EicsS]then
+AP060rq[EicsS][#AP060rq[EicsS]+1]=lLJ else AP060rq[EicsS]={lLJ}end end;return AP060rq end
+function qxZa6ozV.countBy(JubU,L,...)local JKci={}
+for SsBe,o in zupvsz(JubU)do local ZOmcmO=L(o,SsBe,...)JKci[ZOmcmO]=(
+JKci[ZOmcmO]or 0)+1 end;return JKci end
+function qxZa6ozV.size(...)local _G19JrRB={...}local m0r3_J=_G19JrRB[1]return
+
+(l6Sm5(m0r3_J)=='table')and MGSnnzOI(_G19JrRB[1])or MGSnnzOI(_G19JrRB)end
+function qxZa6ozV.containsKeys(MLrs,hP5)for oqjhEZb0 in zupvsz(hP5)do
+if not MLrs[oqjhEZb0]then return false end end;return true end
+function qxZa6ozV.sameKeys(Pha,G)
+for MOrzq4 in zupvsz(Pha)do if not G[MOrzq4]then return false end end
+for bEMp in zupvsz(G)do if not Pha[bEMp]then return false end end;return true end
+function qxZa6ozV.sample(dd,MOQN,O)MOQN=MOQN or 1;if MOQN==0 then return{}end;if MOQN==1 then
+if O then S9TO(O)end;return{dd[pS78Y(1,#dd)]}end;return
+qxZa6ozV.slice(qxZa6ozV.shuffle(dd,O),1,MOQN)end
+function qxZa6ozV.sampleProb(FEpet,P,G)if G then S9TO(G)end;local EcLLM={}for wo,ur in Mw(FEpet)do if pS78Y()<P then
+EcLLM[#EcLLM+1]=ur end end;return EcLLM end
+function qxZa6ozV.shuffle(XTX,wc8hjKp1)if wc8hjKp1 then S9TO(wc8hjKp1)end;local f={}
+for Hjag,Yg in Mw(XTX)do local uc=RlMSrmdD(pS78Y()*
+Hjag)+1;f[Hjag]=f[uc]f[uc]=Yg end;return f end;function qxZa6ozV.toArray(...)return{...}end;function qxZa6ozV.find(bw,ad,EG344W)
+for MVlUhPEM=EG344W or 1,#bw do if
+qxZa6ozV.isEqual(bw[MVlUhPEM],ad)then return MVlUhPEM end end end;function qxZa6ozV.reverse(LT)
+local pfiWYrg={}
+for smnX9H6=#LT,1,-1 do pfiWYrg[#pfiWYrg+1]=LT[smnX9H6]end;return pfiWYrg end
+function qxZa6ozV.fill(FzRhHR,mMBxOoQa,xYSLIT,Eae7ILmk)Eae7ILmk=
+Eae7ILmk or qxZa6ozV.size(FzRhHR)for xYSLIT=xYSLIT or 1,Eae7ILmk
+do FzRhHR[xYSLIT]=mMBxOoQa end;return FzRhHR end
+function qxZa6ozV.zeros(Jy23ZRAA)return qxZa6ozV.fill({},0,1,Jy23ZRAA)end
+function qxZa6ozV.ones(V8IWw)return qxZa6ozV.fill({},1,1,V8IWw)end
+function qxZa6ozV.vector(uyYdf,K)return qxZa6ozV.fill({},uyYdf,1,K)end
+function qxZa6ozV.selectWhile(ZX,tbdC,...)local VaY3={}
+for HK7Mbgze,VXPfx in Mw(ZX)do if tbdC(VXPfx,HK7Mbgze,...)then VaY3[HK7Mbgze]=VXPfx else
+break end end;return VaY3 end
+function qxZa6ozV.dropWhile(j3Qk,X1,...)local GpruB;for r,V7YqV in Mw(j3Qk)do
+if not X1(V7YqV,r,...)then GpruB=r;break end end;if(GpruB==nil)then return{}end;return
+qxZa6ozV.rest(j3Qk,GpruB)end
+function qxZa6ozV.sortedIndex(JbvH7,Cqk9Luq,PeAP9X,vN5AF9)local j=PeAP9X or z5i2i;if(vN5AF9 ==true)then
+JdUtcU(JbvH7,j)end;for EOgmP=1,#JbvH7 do
+if not j(JbvH7[EOgmP],Cqk9Luq)then return EOgmP end end;return#JbvH7+1 end;function qxZa6ozV.indexOf(j,mJof)
+for yz1Kuwby=1,#j do if j[yz1Kuwby]==mJof then return yz1Kuwby end end end
+function qxZa6ozV.lastIndexOf(KVE6TG,YY)
+local r9=qxZa6ozV.indexOf(qxZa6ozV.reverse(KVE6TG),YY)if r9 then return#KVE6TG-r9+1 end end
+function qxZa6ozV.findIndex(mtUG,PFRuf,...)for KhK1gRj9=1,#mtUG do
+if PFRuf(mtUG[KhK1gRj9],KhK1gRj9,...)then return KhK1gRj9 end end end
+function qxZa6ozV.findLastIndex(Xgj,Ko,...)
+local A=qxZa6ozV.findIndex(qxZa6ozV.reverse(Xgj),Ko,...)if A then return#Xgj-A+1 end end;function qxZa6ozV.addTop(IU6Om,...)
+for sKIIqz,wmhARqEa in Mw({...})do lIpFkbLI(IU6Om,1,wmhARqEa)end;return IU6Om end;function qxZa6ozV.prepend(_RT3,...)return
+qxZa6ozV.append({...},_RT3)end
+function qxZa6ozV.push(V,...)local BTA={...}for QVEYENaX,gxqa in
+Mw({...})do V[#V+1]=gxqa end;return V end
+function qxZa6ozV.shift(q4,QyKi)QyKi=OV7(QyKi or 1,#q4)local _o3FE={}for n=1,QyKi do local WM=q4[1]
+_o3FE[#_o3FE+1]=WM;GQLN(q4,1)end;return kyWtqIf0(_o3FE)end
+function qxZa6ozV.unshift(zb8b,YBqeh)YBqeh=OV7(YBqeh or 1,#zb8b)local WRkIg={}
+for RH_vLUg=1,YBqeh do
+local aEH=zb8b[#zb8b]WRkIg[#WRkIg+1]=aEH;GQLN(zb8b)end;return kyWtqIf0(WRkIg)end
+function qxZa6ozV.pull(g20N7,...)
+for puZN,_Dy in Mw({...})do for MC=#g20N7,1,-1 do if qxZa6ozV.isEqual(g20N7[MC],_Dy)then
+GQLN(g20N7,MC)end end end;return g20N7 end
+function qxZa6ozV.removeRange(WOBSVeqF,A,vqW6)A=A or 1;vqW6=vqW6 or#WOBSVeqF;if A>vqW6 then
+S1wg_DG("start cannot be greater than finish.")end
+for R4oRlgh=vqW6,A,-1 do GQLN(WOBSVeqF,R4oRlgh)end;return WOBSVeqF end
+function qxZa6ozV.chunk(rBRXA,qfFSJN,...)local Va8fT08T,d778,aZT,ni9je9bJ={},0
+for uwwNE,X40cF in Mw(rBRXA)do
+ni9je9bJ=qfFSJN(X40cF,uwwNE,...)aZT=(aZT==nil)and ni9je9bJ or aZT
+d778=(
+(ni9je9bJ~=aZT)and(d778+1)or d778)if not Va8fT08T[d778]then Va8fT08T[d778]={rBRXA[uwwNE]}else
+Va8fT08T[d778][
+#Va8fT08T[d778]+1]=rBRXA[uwwNE]end;aZT=ni9je9bJ end;return Va8fT08T end
+function qxZa6ozV.slice(EW,asgq,IQybL1)local hYKT45={}for Rq7=asgq or 1,IQybL1 or#EW do
+hYKT45[#hYKT45+1]=EW[Rq7]end;return hYKT45 end
+function qxZa6ozV.first(LQ_EIcl,uaL)uaL=uaL or 1;local gujcrFp={}for ph06vXj=1,uaL do
+gujcrFp[ph06vXj]=LQ_EIcl[ph06vXj]end;return gujcrFp end
+function qxZa6ozV.initial(nH0LB4c,ALwJ9)local _X=#nH0LB4c;ALwJ9=
+ALwJ9 and _X- (OV7(ALwJ9,_X))or _X-1;local ruXMob={}for E=1,ALwJ9 do
+ruXMob[E]=nH0LB4c[E]end;return ruXMob end
+function qxZa6ozV.last(jcgjAE,BZmaGN)local HSav=#jcgjAE;BZmaGN=
+BZmaGN and HSav-OV7(BZmaGN-1,HSav-1)or 2;local sDjMr={}for biQX3Ut=BZmaGN,HSav do
+sDjMr[#sDjMr+1]=jcgjAE[biQX3Ut]end;return sDjMr end
+function qxZa6ozV.rest(BLEXN_,Ljc)local fpN7T={}for FNSk_=Ljc or 1,#BLEXN_ do
+fpN7T[#fpN7T+1]=BLEXN_[FNSk_]end;return fpN7T end;function qxZa6ozV.nth(LmE,pZTFVP)return LmE[pZTFVP]end
+function qxZa6ozV.compact(XL)
+local L5vC0Jx={}
+for vpONJ,A in zupvsz(XL)do if A then L5vC0Jx[#L5vC0Jx+1]=A end end;return L5vC0Jx end
+function qxZa6ozV.flatten(LN,dA14qP)dA14qP=dA14qP or false;local JcQc;local hDih6_D={}
+for QKbZ464i,F1TsZ in Mw(LN)do
+if
+l6Sm5(F1TsZ)=='table'then
+JcQc=dA14qP and F1TsZ or qxZa6ozV.flatten(F1TsZ)for uF2,T in Mw(JcQc)do hDih6_D[#hDih6_D+1]=T end else hDih6_D[#
+hDih6_D+1]=F1TsZ end end;return hDih6_D end
+function qxZa6ozV.difference(pC_,ju)if not ju then return qxZa6ozV.clone(pC_)end;return
+qxZa6ozV.select(pC_,function(deu1)return
+not qxZa6ozV.include(ju,deu1)end)end;function qxZa6ozV.union(...)
+return qxZa6ozV.unique(qxZa6ozV.flatten({...}))end
+function qxZa6ozV.intersection(IgZ6,...)local kVRiv3F={...}local kWMf={}
+for DawC,cP in
+Mw(IgZ6)do if
+qxZa6ozV.all(kVRiv3F,function(w)return qxZa6ozV.include(w,cP)end)then kWMf[#kWMf+1]=cP end end;return kWMf end
+function qxZa6ozV.symmetricDifference(UZ,tdH)return
+qxZa6ozV.difference(qxZa6ozV.union(UZ,tdH),qxZa6ozV.intersection(UZ,tdH))end
+function qxZa6ozV.unique(ymt)local WxGA={}
+for jBuHkH=1,#ymt do if
+not qxZa6ozV.find(WxGA,ymt[jBuHkH])then WxGA[#WxGA+1]=ymt[jBuHkH]end end;return WxGA end;function qxZa6ozV.isunique(E3)
+return#E3 ==# (qxZa6ozV.unique(E3))end
+function qxZa6ozV.zip(...)local CZi_zK={...}local _6KCMph=qxZa6ozV.max(CZi_zK,function(V)
+return#V end)local PY3VqYZ8={}
+for y=1,_6KCMph
+do if not PY3VqYZ8[y]then PY3VqYZ8[y]={}end;for QF,hN in Mw(CZi_zK)do
+if hN[y]then PY3VqYZ8[y][
+#PY3VqYZ8[y]+1]=hN[y]end end end;return PY3VqYZ8 end
+function qxZa6ozV.zipWith(hVflx4kh,...)local GP={...}
+local oCZYv2dT=qxZa6ozV.max(GP,function(PoH)return#PoH end)local RLaqM3={}for xM709D=1,oCZYv2dT do
+RLaqM3[xM709D]=hVflx4kh(kyWtqIf0(qxZa6ozV.pluck(GP,xM709D)))end;return RLaqM3 end
+function qxZa6ozV.append(z50,sAPD)local AVFi={}for GGKI,gWaGu in Mw(z50)do AVFi[GGKI]=gWaGu end;for SFKM,j6jQmlbr in
+Mw(sAPD)do AVFi[#AVFi+1]=j6jQmlbr end;return AVFi end
+function qxZa6ozV.interleave(...)local m403CY={...}
+local dL=qxZa6ozV.max(m403CY,qxZa6ozV.size)local PrTsHeT={}for eNI3MT7=1,dL do
+for Rfoo,eUJhGD in Mw(m403CY)do if eUJhGD[eNI3MT7]then
+PrTsHeT[#PrTsHeT+1]=eUJhGD[eNI3MT7]end end end;return PrTsHeT end;function qxZa6ozV.interpose(wot8,j9vJ)
+for J6Qr27Mh=#wot8,2,-1 do lIpFkbLI(wot8,J6Qr27Mh,j9vJ)end;return wot8 end
+function qxZa6ozV.range(AwxW8Do,_u,B)
+if(
+AwxW8Do==nil)and(_u==nil)and(B==nil)then return{}elseif(
+AwxW8Do~=nil)and(_u==nil)and(B==nil)then
+AwxW8Do,_u,B=cmWo_v(AwxW8Do),AwxW8Do,cmWo_v(AwxW8Do)elseif(AwxW8Do~=nil)and(_u~=nil)and(B==nil)then B=cmWo_v(_u-
+AwxW8Do)end;local cdxFVpZw={AwxW8Do}
+local Y=VCD(RlMSrmdD((_u-AwxW8Do)/B),0)
+for o9Uh=1,Y do cdxFVpZw[#cdxFVpZw+1]=AwxW8Do+B*o9Uh end;return cdxFVpZw end
+function qxZa6ozV.rep(BuX1r,Wyf83f2)local P0olj={}for z=1,Wyf83f2 do P0olj[z]=BuX1r end;return P0olj end
+function qxZa6ozV.powerset(EHCCkt)local x=#EHCCkt;if x==0 then return{{}}end;local xNWVmS={}
+for kGWnkgDu=1,x do for Pkis6H28=1,x-kGWnkgDu+1
+do
+xNWVmS[#xNWVmS+1]=qxZa6ozV.slice(EHCCkt,Pkis6H28,Pkis6H28+kGWnkgDu-1)end end;return xNWVmS end
+function qxZa6ozV.partition(tSE,abKH,LDp)if abKH<=0 then return end;return PizLA9mj(function()
+VQT(tSE,abKH or 1,hUL,LDp)end)end;function qxZa6ozV.overlapping(GWouUlzZ,MqJhIr,Q9)if MqJhIr<=1 then return end
+return PizLA9mj(function()
+Id(GWouUlzZ,MqJhIr or 2,hUL,Q9)end)end
+function qxZa6ozV.aperture(c,qnZ81I)if
+qnZ81I<=1 then return end;return
+PizLA9mj(function()Ub(c,qnZ81I or 2,hUL)end)end
+function qxZa6ozV.pairwise(N9uN)return qxZa6ozV.aperture(N9uN,2)end;function qxZa6ozV.permutation(QGC)return
+PizLA9mj(function()qJExeUn2(QGC,#QGC,hUL)end)end
+function qxZa6ozV.invert(K8iFU)
+local gbU={}for h,hS7 in Mw(K8iFU)do gbU[hS7]=h end;return gbU end
+function qxZa6ozV.concat(KQjMKhN,R6PYgHHE,ZwCXrLO,lI)return
+toXyq(qxZa6ozV.map(KQjMKhN,tostring),R6PYgHHE,ZwCXrLO,lI)end
+function qxZa6ozV.xprod(iMSMP5Lp,WoARZdZ3)local n={}for Uj,HpN_N in Mw(iMSMP5Lp)do
+for yP3QEJ,pwi in Mw(WoARZdZ3)do n[#n+1]={HpN_N,pwi}end end;return n end
+function qxZa6ozV.sum(QP)local Iy=0;for O9P0mj,eFGwPxi in Mw(QP)do Iy=Iy+eFGwPxi end;return Iy end;function qxZa6ozV.product(m4x8ZsD4)local _witc0Pe=1
+for Y8E,h in Mw(m4x8ZsD4)do _witc0Pe=_witc0Pe*h end;return _witc0Pe end
+function qxZa6ozV.mean(EnMMG)return
+qxZa6ozV.sum(EnMMG)/ (#EnMMG)end
+function qxZa6ozV.median(HzO7UpZ)
+local B=qxZa6ozV.sort(qxZa6ozV.clone(HzO7UpZ))local RNTu=#B;if RNTu==0 then return elseif RNTu==1 then return B[1]end
+local Q_=X83a(RNTu/2)return
+RNTu%2 ==0 and(B[Q_]+B[Q_+1])/2 or B[Q_]end;function qxZa6ozV.noop()return end;function qxZa6ozV.identity(S8GB)return S8GB end;function qxZa6ozV.constant(W7yjGm)return function()return
+W7yjGm end end
+function qxZa6ozV.applySpec(X)return
+function(...)
+local Y={}for qqvEf3,Wriu in zupvsz(X)do Y[qqvEf3]=Wriu(...)end;return Y end end
+function qxZa6ozV.memoize(I0Pxr5F,ukGf_)local uZpt01P=odpE({},{__mode='kv'})
+local hJk0n8bR=ukGf_ or qxZa6ozV.identity;return
+function(...)local o9DTTJig=hJk0n8bR(...)local v4=uZpt01P[o9DTTJig]if not v4 then
+uZpt01P[o9DTTJig]=I0Pxr5F(...)end;return uZpt01P[o9DTTJig]end end
+function qxZa6ozV.unfold(Uaq2_Xzk,S0DM)local GHasi5,QeX_U9tm={}
+while true do QeX_U9tm,S0DM=Uaq2_Xzk(S0DM)if QeX_U9tm~=nil then GHasi5[#
+GHasi5+1]=QeX_U9tm else break end end;return GHasi5 end
+function qxZa6ozV.once(Dp9m)local sJjNM=0;local GnSs={}
+return function(...)sJjNM=sJjNM+1;if sJjNM<=1 then GnSs={...}end;return
+Dp9m(kyWtqIf0(GnSs))end end
+function qxZa6ozV.before(XP,MGSnnzOI)local Sj=0;local yKj1={}
+return function(...)Sj=Sj+1;if Sj<=MGSnnzOI then yKj1={...}end;return
+XP(kyWtqIf0(yKj1))end end
+function qxZa6ozV.after(F9WZ,MGSnnzOI)local A5,nY_O=MGSnnzOI,0;return function(...)nY_O=nY_O+1
+if nY_O>=A5 then return F9WZ(...)end end end
+function qxZa6ozV.compose(...)local QAJAyj5=qxZa6ozV.reverse{...}
+return function(...)local EZ,n=true
+for M,AADiL1 in
+Mw(QAJAyj5)do if EZ then EZ=false;n=AADiL1(...)else n=AADiL1(n)end end;return n end end
+function qxZa6ozV.pipe(Arw,...)return qxZa6ozV.compose(...)(Arw)end
+function qxZa6ozV.complement(b)return function(...)return not b(...)end end
+function qxZa6ozV.juxtapose(_ZM1Yj3,...)local rmSU={}
+for L2RHrI,XW7Y5Rz in Mw({...})do rmSU[L2RHrI]=XW7Y5Rz(_ZM1Yj3)end;return kyWtqIf0(rmSU)end
+function qxZa6ozV.wrap(C,NhwEkTd)return function(...)return NhwEkTd(C,...)end end
+function qxZa6ozV.times(XGz,Tf4P2eIf,...)local TF3Htu={}for K5yUw1t=1,(Tf4P2eIf or 1)do
+TF3Htu[K5yUw1t]=XGz(K5yUw1t,...)end;return TF3Htu end;function qxZa6ozV.bind(Mi,WWyrqnSL)
+return function(...)return Mi(WWyrqnSL,...)end end
+function qxZa6ozV.bind2(gVTyP,Ck)return function(CRG,...)
+return gVTyP(CRG,Ck,...)end end;function qxZa6ozV.bindn(dkz,...)local zrCq={...}
return function(...)return
-SFKM(VCD(hUL.append(j6jQmlbr,{...})))end end
-function hUL.bindAll(m403CY,...)
-local dL={...}
-for PrTsHeT,eNI3MT7 in X83a(dL)do local Rfoo=m403CY[eNI3MT7]if Rfoo then
-m403CY[eNI3MT7]=hUL.bind(Rfoo,m403CY)end end;return m403CY end
-function hUL.uniqueId(eUJhGD,...)B0o5xpg7=B0o5xpg7+1;if eUJhGD then
-if hUL.isString(eUJhGD)then return
-eUJhGD:format(B0o5xpg7)elseif hUL.isFunction(eUJhGD)then return eUJhGD(B0o5xpg7,...)end end
-return B0o5xpg7 end;function hUL.iterator(wot8,j9vJ)
-return function()j9vJ=wot8(j9vJ)return j9vJ end end
-function hUL.array(...)local J6Qr27Mh={}for AwxW8Do in...do
-J6Qr27Mh[#J6Qr27Mh+1]=AwxW8Do end;return J6Qr27Mh end;function hUL.flip(_u)return
-function(...)return _u(VCD(hUL.reverse({...})))end end
-function hUL.over(...)
-local B={...}
-return function(...)local cdxFVpZw={}
-for Y,o9Uh in X83a(B)do cdxFVpZw[#cdxFVpZw+1]=o9Uh(...)end;return cdxFVpZw end end
-function hUL.overEvery(...)local BuX1r=hUL.over(...)
+dkz(kyWtqIf0(qxZa6ozV.append(zrCq,{...})))end end
+function qxZa6ozV.bindall(azXMvVdM,...)
+local CBgxHfbq={...}
+for WO,H in Mw(CBgxHfbq)do local C28NuJ3=azXMvVdM[H]if C28NuJ3 then
+azXMvVdM[H]=qxZa6ozV.bind(C28NuJ3,azXMvVdM)end end;return azXMvVdM end;function qxZa6ozV.cond(sz)
return function(...)
-return hUL.reduce(BuX1r(...),function(Wyf83f2,P0olj)
-return Wyf83f2 and P0olj end)end end;function hUL.overSome(...)local z=hUL.over(...)
+for qH,u in Mw(sz)do if u[1](...)then return u[2](...)end end end end
+function qxZa6ozV.uniqueId(u,...)RoXZEsn=
+RoXZEsn+1;if u then
+if l6Sm5(u)=='string'then return u:format(RoXZEsn)elseif l6Sm5(u)==
+'function'then return u(RoXZEsn,...)end end;return RoXZEsn end
+function qxZa6ozV.iterator(J1Vn4uYP,Z,pJ)local MGSnnzOI=0
+return function()MGSnnzOI=MGSnnzOI+1
+if pJ and MGSnnzOI>pJ then return end;Z=J1Vn4uYP(Z)return Z end end
+function qxZa6ozV.array(...)local NAjg={}for con in...do NAjg[#NAjg+1]=con end;return NAjg end;function qxZa6ozV.castArray(I)
+return(l6Sm5(I)~='table')and{I}or I end;function qxZa6ozV.flip(TxmZR6UE)
return function(...)return
-hUL.reduce(z(...),function(EHCCkt,x)return EHCCkt or x end)end end
-function hUL.overArgs(xNWVmS,...)
-local kGWnkgDu={...}
+TxmZR6UE(kyWtqIf0(qxZa6ozV.reverse({...})))end end;function qxZa6ozV.nthArg(I1b4o)
+return function(...)
+local nAt={...}return
+nAt[(I1b4o<0)and(#nAt+I1b4o+1)or I1b4o]end end
+function qxZa6ozV.unary(pNJ)return function(...)
+local RQ={...}return pNJ(RQ[1])end end
+function qxZa6ozV.ary(wnZcHKf,Lv_8)Lv_8=Lv_8 or 1;return
+function(...)local UQ={...}local FG={}for vLzqjJw=1,Lv_8 do
+FG[vLzqjJw]=UQ[vLzqjJw]end;return wnZcHKf(kyWtqIf0(FG))end end
+function qxZa6ozV.rearg(v2dsC21,O)
+return function(...)local wx={...}local u={}for V_84V,qF in Mw(O)do u[V_84V]=wx[qF]end;return
+v2dsC21(kyWtqIf0(u))end end
+function qxZa6ozV.over(...)local IZbOX7TW={...}return
+function(...)local Dd6ZLpU={}for MP,w4c in Mw(IZbOX7TW)do
+Dd6ZLpU[#Dd6ZLpU+1]=w4c(...)end;return Dd6ZLpU end end
+function qxZa6ozV.overEvery(...)local C58=qxZa6ozV.over(...)
+return function(...)
+return qxZa6ozV.reduce(C58(...),function(Jk6Nh,s1Ws)return
+Jk6Nh and s1Ws end)end end
+function qxZa6ozV.overSome(...)local desLYv=qxZa6ozV.over(...)return
+function(...)return
+qxZa6ozV.reduce(desLYv(...),function(COq2NY9I,aoBEg65S)return COq2NY9I or
+aoBEg65S end)end end
+function qxZa6ozV.overArgs(x6,...)local t3cNa2l={...}
return
-function(...)local Pkis6H28={...}
-for tSE=1,#kGWnkgDu do local xNWVmS=kGWnkgDu[tSE]if Pkis6H28[tSE]then
-Pkis6H28[tSE]=xNWVmS(Pkis6H28[tSE])end end;return xNWVmS(VCD(Pkis6H28))end end
-function hUL.partial(abKH,...)local LDp={...}
+function(...)local Ik={...}
+for SeHOs=1,#t3cNa2l do local x6=t3cNa2l[SeHOs]if
+Ik[SeHOs]then Ik[SeHOs]=x6(Ik[SeHOs])end end;return x6(kyWtqIf0(Ik))end end
+function qxZa6ozV.converge(P2rGsUx,c,v12AhMm)return
+function(...)return P2rGsUx(c(...),v12AhMm(...))end end
+function qxZa6ozV.partial(F2uxGC,...)local Xs0={...}
return
-function(...)local GWouUlzZ={...}local MqJhIr={}
-for Q9,c in X83a(LDp)do MqJhIr[Q9]=(c=='_')and
-hUL.pop(GWouUlzZ)or c end
-return abKH(VCD(hUL.append(MqJhIr,GWouUlzZ)))end end
-function hUL.partialRight(qnZ81I,...)local N9uN={...}
+function(...)local QK8ibF={...}local TEio7k0z={}
+for u,N in Mw(Xs0)do TEio7k0z[u]=(N=='_')and
+qxZa6ozV.shift(QK8ibF)or N end;return
+F2uxGC(kyWtqIf0(qxZa6ozV.append(TEio7k0z,QK8ibF)))end end
+function qxZa6ozV.partialRight(O2YgxDc,...)local VLsC67={...}
return
-function(...)local QGC={...}local K8iFU={}for gbU=1,#N9uN do
-K8iFU[gbU]=
-(N9uN[gbU]=='_')and hUL.pop(QGC)or N9uN[gbU]end;return
-qnZ81I(VCD(hUL.append(QGC,K8iFU)))end end
-function hUL.curry(h,hS7)hS7=hS7 or 2;local KQjMKhN={}
-local function R6PYgHHE(ZwCXrLO)if hS7 ==1 then return h(ZwCXrLO)end;if
-ZwCXrLO~=nil then KQjMKhN[#KQjMKhN+1]=ZwCXrLO end;if
-#KQjMKhN<hS7 then return R6PYgHHE else local lI={h(VCD(KQjMKhN))}KQjMKhN={}return
-VCD(lI)end end;return R6PYgHHE end
-function hUL.time(iMSMP5Lp,...)local WoARZdZ3=PizLA9mj()local n={iMSMP5Lp(...)}return
-PizLA9mj()-WoARZdZ3,VCD(n)end;function hUL.keys(Uj)local HpN_N={}
-hUL.each(Uj,function(yP3QEJ)HpN_N[#HpN_N+1]=yP3QEJ end)return HpN_N end;function hUL.values(pwi)local QP={}
-hUL.each(pwi,function(hUL,Iy)QP[
-#QP+1]=Iy end)return QP end
-function hUL.kvpairs(O9P0mj)local eFGwPxi={}
-hUL.each(O9P0mj,function(m4x8ZsD4,_witc0Pe)eFGwPxi[
-#eFGwPxi+1]={m4x8ZsD4,_witc0Pe}end)return eFGwPxi end;function hUL.toObj(Y8E)local h={}
-for EnMMG,HzO7UpZ in X83a(Y8E)do h[HzO7UpZ[1]]=HzO7UpZ[2]end;return h end;function hUL.property(B)return function(RNTu)
-return RNTu[B]end end
-function hUL.propertyOf(Q_)return function(S8GB)return
-Q_[S8GB]end end;function hUL.toBoolean(W7yjGm)return not not W7yjGm end
-function hUL.extend(X,...)
-local Y={...}
-hUL.each(Y,function(qqvEf3,Wriu)if hUL.isTable(Wriu)then
-hUL.each(Wriu,function(I0Pxr5F,ukGf_)X[I0Pxr5F]=ukGf_ end)end end)return X end
-function hUL.functions(uZpt01P,hJk0n8bR)uZpt01P=uZpt01P or hUL;local o9DTTJig={}
-hUL.each(uZpt01P,function(Uaq2_Xzk,S0DM)
-if hUL.isFunction(S0DM)then o9DTTJig[
-#o9DTTJig+1]=Uaq2_Xzk end end)if not hJk0n8bR then return hUL.sort(o9DTTJig)end
-local v4=oUA(uZpt01P)if v4 and v4.__index then local GHasi5=hUL.functions(v4.__index)
-hUL.each(GHasi5,function(QeX_U9tm,Dp9m)o9DTTJig[#
-o9DTTJig+1]=Dp9m end)end;return
-hUL.sort(o9DTTJig)end
-function hUL.clone(sJjNM,GnSs)if not hUL.isTable(sJjNM)then return sJjNM end;local XP={}
-hUL.each(sJjNM,function(Sj,yKj1)if
-hUL.isTable(yKj1)then
-if not GnSs then XP[Sj]=hUL.clone(yKj1,GnSs)else XP[Sj]=yKj1 end else XP[Sj]=yKj1 end end)return XP end;function hUL.tap(F9WZ,A5,...)A5(F9WZ,...)return F9WZ end;function hUL.has(nY_O,QAJAyj5)return nY_O[QAJAyj5]~=
-nil end
-function hUL.pick(EZ,...)
-local n=hUL.flatten{...}local M={}
-hUL.each(n,function(AADiL1,Arw)
-if not hUL.isNil(EZ[Arw])then M[Arw]=EZ[Arw]end end)return M end
-function hUL.omit(b,...)local _ZM1Yj3=hUL.flatten{...}local rmSU={}
-hUL.each(b,function(L2RHrI,XW7Y5Rz)if not
-hUL.include(_ZM1Yj3,L2RHrI)then rmSU[L2RHrI]=XW7Y5Rz end end)return rmSU end;function hUL.template(C,NhwEkTd)
-hUL.each(NhwEkTd or{},function(XGz,Tf4P2eIf)if not C[XGz]then C[XGz]=Tf4P2eIf end end)return C end
-function hUL.isEqual(TF3Htu,K5yUw1t,Mi)
-local WWyrqnSL=SWFtRywD(TF3Htu)local gVTyP=SWFtRywD(K5yUw1t)if WWyrqnSL~=gVTyP then return false end;if
-WWyrqnSL~='table'then return(TF3Htu==K5yUw1t)end
-local Ck=oUA(TF3Htu)local CRG=oUA(K5yUw1t)
-if Mi then if
-(Ck or CRG)and(Ck.__eq or CRG.__eq)then
-return Ck.__eq(TF3Htu,K5yUw1t)or CRG.__eq(K5yUw1t,TF3Htu)or(TF3Htu==
-K5yUw1t)end end
-if hUL.size(TF3Htu)~=hUL.size(K5yUw1t)then return false end;for dkz,zrCq in OV7(TF3Htu)do local azXMvVdM=K5yUw1t[dkz]
-if hUL.isNil(azXMvVdM)or not
-hUL.isEqual(zrCq,azXMvVdM,Mi)then return false end end
-for CBgxHfbq,WO in
-OV7(K5yUw1t)do local H=TF3Htu[CBgxHfbq]if hUL.isNil(H)then return false end end;return true end
-function hUL.result(C28NuJ3,sz,...)if C28NuJ3[sz]then
-if hUL.isCallable(C28NuJ3[sz])then return
-C28NuJ3[sz](C28NuJ3,...)else return C28NuJ3[sz]end end;if
-hUL.isCallable(sz)then return sz(C28NuJ3,...)end end;function hUL.isTable(qH)return SWFtRywD(qH)=='table'end
-function hUL.isCallable(u)return
+function(...)local OHw4={...}local FKZ={}for Fl=1,#VLsC67 do
+FKZ[Fl]=
+(VLsC67[Fl]=='_')and qxZa6ozV.shift(OHw4)or VLsC67[Fl]end;return
+O2YgxDc(kyWtqIf0(qxZa6ozV.append(OHw4,FKZ)))end end
+function qxZa6ozV.curry(QhS8FvKI,FaZIJL)FaZIJL=FaZIJL or 2;local sOT2O5={}
+local function x(Wswd_OC)if FaZIJL==1 then
+return QhS8FvKI(Wswd_OC)end
+if Wswd_OC~=nil then sOT2O5[#sOT2O5+1]=Wswd_OC end
+if#sOT2O5 <FaZIJL then return x else
+local E={QhS8FvKI(kyWtqIf0(sOT2O5))}sOT2O5={}return kyWtqIf0(E)end end;return x end;function qxZa6ozV.time(A0Un,...)local nRHrI=sf0()local k={A0Un(...)}
+return sf0()-nRHrI,kyWtqIf0(k)end
+function qxZa6ozV.keys(Zp)local A={}for _L_ in
+zupvsz(Zp)do A[#A+1]=_L_ end;return A end;function qxZa6ozV.values(WHpm)local g={}
+for HiR3yiw,KeKbiDqN in zupvsz(WHpm)do g[#g+1]=KeKbiDqN end;return g end
+function qxZa6ozV.path(WfrZqHH8,...)
+local YX9s9O,y64dF=WfrZqHH8,{...}
+for sNSsH,K in Mw(y64dF)do if(YX9s9O[K]==nil)then return end;YX9s9O=YX9s9O[K]end;return YX9s9O end;function qxZa6ozV.kvpairs(o8T)local xeP={}
+for Tv_3VlmX,BT in zupvsz(o8T)do xeP[#xeP+1]={Tv_3VlmX,BT}end;return xeP end;function qxZa6ozV.toObj(_y3z)
+local rdl={}for NAP_5jYs,BZnlpW in Mw(_y3z)do rdl[BZnlpW[1]]=BZnlpW[2]end;return
+rdl end
+function qxZa6ozV.property(isN)return function(yRADzw1v)return
+yRADzw1v[isN]end end;function qxZa6ozV.propertyOf(Jafp)
+return function(XWh8Ee)return Jafp[XWh8Ee]end end;function qxZa6ozV.toBoolean(kpezL1e)
+return not not kpezL1e end
+function qxZa6ozV.extend(h,...)local R7yfz_l9={...}for D35PFLu,wK in Mw(R7yfz_l9)do
+if
+l6Sm5(wK)=='table'then for qeEwE,cbtvFnSa in zupvsz(wK)do h[qeEwE]=cbtvFnSa end end end;return h end
+function qxZa6ozV.functions(fYKH_,W)fYKH_=fYKH_ or qxZa6ozV;local o={}
+for Mm99M,l6YH in zupvsz(fYKH_)do if
+l6Sm5(l6YH)=='function'then o[#o+1]=Mm99M end end
+if W then local gf2=p(fYKH_)
+if gf2 and gf2.__index then
+local F744Ew=qxZa6ozV.functions(gf2.__index,W)for zgxKF4,UlvVvSBR in Mw(F744Ew)do o[#o+1]=UlvVvSBR end end end;return o end
+function qxZa6ozV.clone(i2i,uRGAL)if l6Sm5(i2i)~='table'then return i2i end;local UUlqXyb6={}
+for fOR92g8,jU26 in
+zupvsz(i2i)do
+if l6Sm5(jU26)=='table'then
+if not uRGAL then
+UUlqXyb6[fOR92g8]=qxZa6ozV.clone(jU26,uRGAL)else UUlqXyb6[fOR92g8]=jU26 end else UUlqXyb6[fOR92g8]=jU26 end end;return UUlqXyb6 end
+function qxZa6ozV.tap(WIPTsAPz,DgUx8,...)DgUx8(WIPTsAPz,...)return WIPTsAPz end;function qxZa6ozV.has(imac,xX)return imac[xX]~=nil end
+function qxZa6ozV.pick(Mfb6Kb,...)
+local RRjV=qxZa6ozV.flatten{...}local TDOaFo={}for tLo4,m72l in zupvsz(RRjV)do if(Mfb6Kb[m72l])~=nil then
+TDOaFo[m72l]=Mfb6Kb[m72l]end end;return
+TDOaFo end
+function qxZa6ozV.omit(npM3DSU,...)local HGp4e1=qxZa6ozV.flatten{...}local uzJt7E={}
+for sRe5S32N,Bp in
+zupvsz(npM3DSU)do if not qxZa6ozV.include(HGp4e1,sRe5S32N)then
+uzJt7E[sRe5S32N]=Bp end end;return uzJt7E end
+function qxZa6ozV.template(rg,S)if not S then return rg end;for Fem,cHmVGY in zupvsz(S)do
+if not rg[Fem]then rg[Fem]=cHmVGY end end;return rg end
+function qxZa6ozV.isEqual(g29sXR,Vat,sfnkWAy8)local hbJSGe9=l6Sm5(g29sXR)local pI=l6Sm5(Vat)
+if hbJSGe9 ~=pI then return false end;if hbJSGe9 ~='table'then return(g29sXR==Vat)end
+local B7jhm=p(g29sXR)local hj3=p(Vat)if sfnkWAy8 then
+if
+(B7jhm or hj3)and(B7jhm.__eq or hj3.__eq)then return B7jhm.__eq(g29sXR,Vat)or hj3.__eq(Vat,g29sXR)or
+(g29sXR==Vat)end end
+if
+qxZa6ozV.size(g29sXR)~=qxZa6ozV.size(Vat)then return false end;local FKxU4;for UW,tReY in zupvsz(g29sXR)do FKxU4=Vat[UW]
+if FKxU4 ==nil or not
+qxZa6ozV.isEqual(tReY,FKxU4,sfnkWAy8)then return false end end;for lex in zupvsz(Vat)do if
+g29sXR[lex]==nil then return false end end;return
+true end
+function qxZa6ozV.result(h79Pm,vksQpy4,...)if h79Pm[vksQpy4]then
+if qxZa6ozV.isCallable(h79Pm[vksQpy4])then return
+h79Pm[vksQpy4](h79Pm,...)else return h79Pm[vksQpy4]end end;if
+qxZa6ozV.isCallable(vksQpy4)then return vksQpy4(h79Pm,...)end end
+function qxZa6ozV.isTable(gPCIWPt)return l6Sm5(gPCIWPt)=='table'end
+function qxZa6ozV.isCallable(l4Byxa7)return
+((l6Sm5(l4Byxa7)=='function')or
(
-hUL.isFunction(u)or
-(hUL.isTable(u)and oUA(u)and oUA(u).__call~=nil)or false)end
-function hUL.isArray(u)if not hUL.isTable(u)then return false end;local J1Vn4uYP=0
-for Z in OV7(u)do J1Vn4uYP=
-J1Vn4uYP+1;if hUL.isNil(u[J1Vn4uYP])then return false end end;return true end
-function hUL.isIterable(pJ)return hUL.toBoolean((v(OV7,pJ)))end
-function hUL.isEmpty(NAjg)if hUL.isNil(NAjg)then return true end;if hUL.isString(NAjg)then return
-#NAjg==0 end
-if hUL.isTable(NAjg)then return XKD(NAjg)==nil end;return true end
-function hUL.isString(con)return SWFtRywD(con)=='string'end
-function hUL.isFunction(I)return SWFtRywD(I)=='function'end;function hUL.isNil(TxmZR6UE)return TxmZR6UE==nil end;function hUL.isNumber(I1b4o)return
-SWFtRywD(I1b4o)=='number'end;function hUL.isNaN(nAt)return
-hUL.isNumber(nAt)and nAt~=nAt end
-function hUL.isFinite(pNJ)if
-not hUL.isNumber(pNJ)then return false end;return pNJ>-toXyq and pNJ<
-toXyq end
-function hUL.isBoolean(RQ)return SWFtRywD(RQ)=='boolean'end;function hUL.isInteger(wnZcHKf)return
-hUL.isNumber(wnZcHKf)and S9TO(wnZcHKf)==wnZcHKf end
-do
-hUL.forEach=hUL.each;hUL.forEachi=hUL.eachi;hUL.loop=hUL.cycle;hUL.collect=hUL.map
-hUL.inject=hUL.reduce;hUL.foldl=hUL.reduce;hUL.injectr=hUL.reduceRight
-hUL.foldr=hUL.reduceRight;hUL.mapr=hUL.mapReduce;hUL.maprr=hUL.mapReduceRight
-hUL.any=hUL.include;hUL.some=hUL.include;hUL.contains=hUL.include;hUL.filter=hUL.select
-hUL.discard=hUL.reject;hUL.every=hUL.all;hUL.takeWhile=hUL.selectWhile
-hUL.rejectWhile=hUL.dropWhile;hUL.shift=hUL.pop;hUL.remove=hUL.pull;hUL.rmRange=hUL.removeRange
-hUL.chop=hUL.removeRange;hUL.sub=hUL.slice;hUL.head=hUL.first;hUL.take=hUL.first
-hUL.tail=hUL.rest;hUL.skip=hUL.last;hUL.without=hUL.difference;hUL.diff=hUL.difference
-hUL.symdiff=hUL.symmetricDifference;hUL.xor=hUL.symmetricDifference;hUL.uniq=hUL.unique
-hUL.isuniq=hUL.isunique;hUL.transpose=hUL.zip;hUL.part=hUL.partition;hUL.perm=hUL.permutation
-hUL.mirror=hUL.invert;hUL.join=hUL.concat;hUL.cache=hUL.memoize;hUL.juxt=hUL.juxtapose
-hUL.uid=hUL.uniqueId;hUL.iter=hUL.iterator;hUL.methods=hUL.functions;hUL.choose=hUL.pick
-hUL.drop=hUL.omit;hUL.defaults=hUL.template;hUL.compare=hUL.isEqual end
-do local Lv_8={}local UQ={}UQ.__index=Lv_8;local function FG(vLzqjJw)local v2dsC21={_value=vLzqjJw,_wrapped=true}return
-l6Sm5(v2dsC21,UQ)end
-l6Sm5(UQ,{__call=function(O,wx)
-return FG(wx)end,__index=function(u,V_84V,...)return Lv_8[V_84V]end})function UQ.chain(qF)return FG(qF)end
-function UQ:value()return self._value end;Lv_8.chain,Lv_8.value=UQ.chain,UQ.value
-for IZbOX7TW,Dd6ZLpU in OV7(hUL)do
-Lv_8[IZbOX7TW]=function(MP,...)
-local w4c=
-hUL.isTable(MP)and RlMSrmdD(MP,'_wrapped')or false;if w4c then local C58=MP._value;local Jk6Nh=Dd6ZLpU(C58,...)return FG(Jk6Nh)else
-return Dd6ZLpU(MP,...)end end end
-Lv_8.import=function(s1Ws,desLYv)s1Ws=s1Ws or _ENV or _G;local COq2NY9I=hUL.functions()
-hUL.each(COq2NY9I,function(aoBEg65S,x6)
+(l6Sm5(l4Byxa7)=='table')and p(l4Byxa7)and p(l4Byxa7).__call~=nil)or false)end
+function qxZa6ozV.isArray(Fn8OR)
+if not(l6Sm5(Fn8OR)=='table')then return false end;local X1Z0van=0;for C_ACFsd in zupvsz(Fn8OR)do X1Z0van=X1Z0van+1
+if Fn8OR[X1Z0van]==nil then return false end end;return true end;function qxZa6ozV.isIterable(GC)
+return qxZa6ozV.toBoolean((QFKEzBf(zupvsz,GC)))end
+function qxZa6ozV.isEmpty(SC7gSvMB)if(SC7gSvMB==nil)then
+return true end
+if l6Sm5(SC7gSvMB)=='string'then return#SC7gSvMB==0 end
+if l6Sm5(SC7gSvMB)=='table'then return v(SC7gSvMB)==nil end;return true end
+function qxZa6ozV.isString(Ei)return l6Sm5(Ei)=='string'end
+function qxZa6ozV.isFunction(GFuK1ut)return l6Sm5(GFuK1ut)=='function'end;function qxZa6ozV.isNil(SXmRY3i)return SXmRY3i==nil end;function qxZa6ozV.isNumber(b)return
+l6Sm5(b)=='number'end
+function qxZa6ozV.isNaN(KApFr)return
+l6Sm5(KApFr)=='number'and KApFr~=KApFr end
+function qxZa6ozV.isFinite(jE)if l6Sm5(jE)~='number'then return false end;return jE>-BCf7 and jE<
+BCf7 end
+function qxZa6ozV.isBoolean(yVVmXC)return l6Sm5(yVVmXC)=='boolean'end
+function qxZa6ozV.isInteger(MkxwoCeK)return l6Sm5(MkxwoCeK)=='number'and
+RlMSrmdD(MkxwoCeK)==MkxwoCeK end
+do qxZa6ozV.forEach=qxZa6ozV.each
+qxZa6ozV.forEachi=qxZa6ozV.eachi;qxZa6ozV.update=qxZa6ozV.adjust;qxZa6ozV.loop=qxZa6ozV.cycle
+qxZa6ozV.collect=qxZa6ozV.map;qxZa6ozV.inject=qxZa6ozV.reduce
+qxZa6ozV.foldl=qxZa6ozV.reduce;qxZa6ozV.injectr=qxZa6ozV.reduceRight
+qxZa6ozV.foldr=qxZa6ozV.reduceRight;qxZa6ozV.mapr=qxZa6ozV.mapReduce
+qxZa6ozV.maprr=qxZa6ozV.mapReduceRight;qxZa6ozV.any=qxZa6ozV.include;qxZa6ozV.some=qxZa6ozV.include
+qxZa6ozV.contains=qxZa6ozV.include;qxZa6ozV.filter=qxZa6ozV.select
+qxZa6ozV.discard=qxZa6ozV.reject;qxZa6ozV.every=qxZa6ozV.all
+qxZa6ozV.takeWhile=qxZa6ozV.selectWhile;qxZa6ozV.rejectWhile=qxZa6ozV.dropWhile
+qxZa6ozV.pop=qxZa6ozV.shift;qxZa6ozV.remove=qxZa6ozV.pull
+qxZa6ozV.rmRange=qxZa6ozV.removeRange;qxZa6ozV.chop=qxZa6ozV.removeRange
+qxZa6ozV.sub=qxZa6ozV.slice;qxZa6ozV.head=qxZa6ozV.first;qxZa6ozV.take=qxZa6ozV.first
+qxZa6ozV.tail=qxZa6ozV.rest;qxZa6ozV.skip=qxZa6ozV.last
+qxZa6ozV.without=qxZa6ozV.difference;qxZa6ozV.diff=qxZa6ozV.difference
+qxZa6ozV.symdiff=qxZa6ozV.symmetricDifference;qxZa6ozV.xor=qxZa6ozV.symmetricDifference
+qxZa6ozV.uniq=qxZa6ozV.unique;qxZa6ozV.isuniq=qxZa6ozV.isunique
+qxZa6ozV.transpose=qxZa6ozV.zip;qxZa6ozV.part=qxZa6ozV.partition
+qxZa6ozV.perm=qxZa6ozV.permutation;qxZa6ozV.transposeWith=qxZa6ozV.zipWith
+qxZa6ozV.intersperse=qxZa6ozV.interpose;qxZa6ozV.sliding=qxZa6ozV.aperture
+qxZa6ozV.mirror=qxZa6ozV.invert;qxZa6ozV.join=qxZa6ozV.concat;qxZa6ozV.average=qxZa6ozV.mean
+qxZa6ozV.always=qxZa6ozV.constant;qxZa6ozV.cache=qxZa6ozV.memoize
+qxZa6ozV.juxt=qxZa6ozV.juxtapose;qxZa6ozV.uid=qxZa6ozV.uniqueid
+qxZa6ozV.iter=qxZa6ozV.iterator;qxZa6ozV.tabulate=qxZa6ozV.array;qxZa6ozV.nAry=qxZa6ozV.ary
+qxZa6ozV.methods=qxZa6ozV.functions;qxZa6ozV.choose=qxZa6ozV.pick;qxZa6ozV.drop=qxZa6ozV.omit
+qxZa6ozV.defaults=qxZa6ozV.template;qxZa6ozV.compare=qxZa6ozV.isEqual
+qxZa6ozV.matches=qxZa6ozV.isEqual end
+do local AT={}local _8KO={}_8KO.__index=AT;local function NI(PE)
+return odpE({_value=PE,_wrapped=true},_8KO)end
+odpE(_8KO,{__call=function(a,GhVWeuQs)return NI(GhVWeuQs)end,__index=function(kQlY,xIl1shq,...)return
+AT[xIl1shq]end})function _8KO.chain(qv)return NI(qv)end
+function _8KO:value()return self._value end;AT.chain,AT.value=_8KO.chain,_8KO.value
+for pbEt6T,MBdHQ in zupvsz(qxZa6ozV)do
+if
+pbEt6T~='operator'then
+AT[pbEt6T]=function(STXAhhM,...)local assFn=
+l6Sm5(STXAhhM)=='table'and l(STXAhhM,'_wrapped')or false
+if assFn then
+local EXpWzv=STXAhhM._value;local kq=MBdHQ(EXpWzv,...)return NI(kq)else return MBdHQ(STXAhhM,...)end end end end;AT.operator=qxZa6ozV.operator;AT.op=qxZa6ozV.operator
+AT.import=function(up,wlI_l)up=
+up or _ENV or _G;local nK7J=qxZa6ozV.functions()for xv,IWG in Mw(nK7J)do
if
-RlMSrmdD(s1Ws,x6)then if not desLYv then s1Ws[x6]=hUL[x6]end else s1Ws[x6]=hUL[x6]end end)return s1Ws end;UQ._VERSION='Moses v'..slo60nGX
-UQ._URL='http://github.com/Yonaba/Moses'
-UQ._LICENSE='MIT <http://raw.githubusercontent.com/Yonaba/Moses/master/LICENSE>'UQ._DESCRIPTION='utility-belt library for functional programming in Lua'
-return UQ end \ No newline at end of file
+l(up,IWG)~=nil then
+if not wlI_l then rawset(up,IWG,qxZa6ozV[IWG])end else rawset(up,IWG,qxZa6ozV[IWG])end end;return up end;_8KO._VERSION='Moses v'..e
+_8KO._URL='http://github.com/Yonaba/Moses'
+_8KO._LICENSE='MIT <http://raw.githubusercontent.com/Yonaba/Moses/master/LICENSE>'
+_8KO._DESCRIPTION='utility-belt library for functional programming in Lua'return _8KO end \ No newline at end of file
diff --git a/spec/array_spec.lua b/spec/array_spec.lua
index e79a6f7..74c7b13 100644
--- a/spec/array_spec.lua
+++ b/spec/array_spec.lua
@@ -1,48 +1,81 @@
-require 'luacov'
-local _ = require 'moses'
+--require 'luacov'
+local M = require 'moses'
context('Array functions specs', function()
context('sample', function()
test('samples n values from array', function()
- local array = _.range(1,20)
- local sample = _.sample(array, 5)
+ local array = M.range(1,20)
+ local sample = M.sample(array, 5)
assert_equal(#sample, 5)
- _.each(sample, function(__,v)
- assert_true(_.include(array, v))
+ M.each(sample, function(__,v)
+ assert_true(M.include(array, v))
end)
end)
test('when not given, n defaults to 1', function()
- local array = _.range(1,20)
- local sample = _.sample(array)
- assert_true(_.include(array, sample))
+ local array = M.range(1,20)
+ local sample = M.sample(array)
+ assert_equal(#sample, 1)
+ assert_true(M.include(array, sample[1]))
end)
+ test('if n == 0, returns an empty array', function()
+ local array = M.range(1,5)
+ local sample = M.sample(array, 0)
+ assert_true(#sample == 0)
+ end)
+
+ test('if n < 0, throws an error', function()
+ local array = M.range(1,5)
+ assert_error(M.sample(array, -1))
+ end)
+
end)
context('sampleProb', function()
test('returns a sample of an array values', function()
- local array = _.range(1,20)
- local sample = _.sampleProb(array, 0.2)
- _.each(sample, function(__,v)
- assert_true(_.include(array, v))
+ local array = M.range(1,20)
+ local sample = M.sampleProb(array, 0.2)
+ M.each(sample, function(__,v)
+ assert_true(M.include(array, v))
end)
end)
end)
+ context('shuffle', function()
+
+ test('shuffles values and objects in a collection', function()
+ local values = {'a','b','c','d'}
+ assert_true(M.same(M.shuffle (values),values))
+ end)
+
+ test('can accept a seed value to init randomization', function()
+ local values = {'a','b','c','d'}
+ local seed = os.time()
+ assert_true(M.same(M.shuffle(values,seed),values))
+ end)
+
+ test('shuffled table has the same elements in a different order', function()
+ local values = {'a','b','c','d'}
+ assert_true(M.same(M.shuffle(values),values))
+ assert_true(M.same(M.shuffle(values),values))
+ end)
+
+ end)
+
context('toArray', function()
test('converts a vararg list to an array', function()
- assert_true(_.isArray(_.toArray(1,2,3,4)))
- assert_true(_.isEqual(_.toArray(1,2,8,'d','a',0),{1,2,8,'d','a',0}))
+ assert_true(M.isArray(M.toArray(1,2,3,4)))
+ assert_true(M.isEqual(M.toArray(1,2,8,'d','a',0),{1,2,8,'d','a',0}))
end)
test('preserves input order', function()
- local args = _.toArray(1,2,3,4,5)
+ local args = M.toArray(1,2,3,4,5)
for i = 1, 5 do assert_equal(args[i], i) end
end)
@@ -51,19 +84,19 @@ context('Array functions specs', function()
context('find', function()
test('looks for a value in a given array and returns its position', function()
- assert_equal(_.find({4,3,2,1},2), 3)
+ assert_equal(M.find({4,3,2,1},2), 3)
end)
- test('uses _.isEqual to compare values', function()
- assert_equal(_.find({{4},{3},{2},{1}},{3}), 2)
+ test('uses M.isEqual to compare values', function()
+ assert_equal(M.find({{4},{3},{2},{1}},{3}), 2)
end)
test('returns the index of the first occurence', function()
- assert_equal(_.find({4,4,3,3,2,2,1,1},2),5)
+ assert_equal(M.find({4,4,3,3,2,2,1,1},2),5)
end)
test('can start the search at a specific position', function()
- assert_equal(_.find({4,4,3,3,2,1,2,1,1},2,6),7)
+ assert_equal(M.find({4,4,3,3,2,1,2,1,1},2,6),7)
end)
end)
@@ -71,7 +104,7 @@ context('Array functions specs', function()
context('reverse', function()
test('reverse values and objects in a given array', function()
- assert_true(_.isEqual(_.reverse({1,2,3,'d'}),{'d',3,2,1}))
+ assert_true(M.isEqual(M.reverse({1,2,3,'d'}),{'d',3,2,1}))
end)
end)
@@ -79,39 +112,65 @@ context('Array functions specs', function()
context('fill', function()
test('fills an array with a value', function()
- local array = _.range(1,5)
- assert_true(_.isEqual(_.fill(array,0),{0,0,0,0,0}))
+ local array = M.range(1,5)
+ assert_true(M.isEqual(M.fill(array,0),{0,0,0,0,0}))
end)
test('fills an array starting from an index', function()
- local array = _.range(1,5)
- assert_true(_.isEqual(_.fill(array,0,4),{1,2,3,0,0}))
+ local array = M.range(1,5)
+ assert_true(M.isEqual(M.fill(array,0,4),{1,2,3,0,0}))
end)
test('fills an array replacing values inside a range', function()
- local array = _.range(1,5)
- assert_true(_.isEqual(_.fill(array,0,3,4),{1,2,0,0,5}))
+ local array = M.range(1,5)
+ assert_true(M.isEqual(M.fill(array,0,3,4),{1,2,0,0,5}))
end)
test('enlarges the array when the last index is greater than array size', function()
- local array = _.range(1,5)
- assert_true(_.isEqual(_.fill(array,0,3,8),{1,2,0,0,0,0,0,0}))
+ local array = M.range(1,5)
+ assert_true(M.isEqual(M.fill(array,0,3,8),{1,2,0,0,0,0,0,0}))
end)
end)
+ context('zeros', function()
+
+ test('returns an array of n zeros', function()
+ assert_true(M.isEqual(M.zeros(5), {0,0,0,0,0}))
+ assert_true(M.isEqual(M.zeros(2), {0,0}))
+ assert_true(M.isEqual(M.zeros(1), {0}))
+ end)
+
+ end)
+
+ context('ones', function()
+
+ test('returns an array of n zeros', function()
+ assert_true(M.isEqual(M.ones(5), {1,1,1,1,1}))
+ assert_true(M.isEqual(M.ones(3), {1,1,1}))
+ assert_true(M.isEqual(M.ones(1), {1}))
+ end)
+
+ end)
+
+ context('vector', function()
+
+ test('returns an array of n times a given value', function()
+ assert_true(M.isEqual(M.vector(false,4), {false, false, false, false}))
+ local f = function() end
+ assert_true(M.isEqual(M.vector(f,2), {f, f}))
+ end)
+
+ end)
+
context('selectWhile', function()
test('collect values from an array while they pass a thruth test', function()
- assert_true(_.isEqual(_.selectWhile({2,4,6,8}, function(i,v)
- return v%2==0
- end),{2,4,6,8}))
+ assert_true(M.isEqual(M.selectWhile({2,4,6,8}, function(v)return v%2==0 end),{2,4,6,8}))
end)
test('breaks as soon as one value do not pass the test', function()
- assert_true(_.isEqual(_.selectWhile({2,4,6,8,9,10,12}, function(i,v)
- return v%2==0
- end),{2,4,6,8}))
+ assert_true(M.isEqual(M.selectWhile({2,4,6,8,9,10,12}, function(v) return v%2==0 end),{2,4,6,8}))
end)
end)
@@ -119,15 +178,11 @@ context('Array functions specs', function()
context('dropWhile', function()
test('rejects values from an array while they pass a thruth test', function()
- assert_true(_.isEqual(_.dropWhile({2,4,6,8}, function(i,v)
- return v%2==0
- end),{}))
+ assert_true(M.isEqual(M.dropWhile({2,4,6,8}, function(v) return v%2==0 end),{}))
end)
test('breaks as soon as one value do not pass the test', function()
- assert_true(_.isEqual(_.dropWhile({2,4,6,8,9,10,12}, function(i,v)
- return v%2==0
- end),{9,10,12}))
+ assert_true(M.isEqual(M.dropWhile({2,4,6,8,9,10,12}, function(v) return v%2==0 end),{9,10,12}))
end)
end)
@@ -136,16 +191,16 @@ context('Array functions specs', function()
test('returns the index at which a value should be inserted to preserve order', function()
local comp = function(a,b) return a<b end
- assert_equal(_.sortedIndex({1,2,3},4,comp),4)
+ assert_equal(M.sortedIndex({1,2,3},4,comp),4)
end)
test('the given array will be sorted before if boolean arg "sort" is given', function()
local comp = function(a,b) return a<b end
- assert_equal(_.sortedIndex({0,10,3,-5},4,comp,true),4)
+ assert_equal(M.sortedIndex({0,10,3,-5},4,comp,true),4)
end)
test('when no comparison function is given, uses "<" operator', function()
- assert_equal(_.sortedIndex({'a','d','e','z'},'b'),2)
+ assert_equal(M.sortedIndex({'a','d','e','z'},'b'),2)
end)
end)
@@ -153,15 +208,15 @@ context('Array functions specs', function()
context('indexOf', function()
test('returns the index of a value in an array', function()
- assert_equal(_.indexOf({1,2,3},2),2)
+ assert_equal(M.indexOf({1,2,3},2),2)
end)
test('returns nil when value was not found', function()
- assert_nil(_.indexOf({'a','b','c','d'},'e'))
+ assert_nil(M.indexOf({'a','b','c','d'},'e'))
end)
test('will always return the index of the first occurence', function()
- assert_equal(_.indexOf({'a','d','d','z'},'d'),2)
+ assert_equal(M.indexOf({'a','d','d','z'},'d'),2)
end)
end)
@@ -169,12 +224,12 @@ context('Array functions specs', function()
context('lastIndexOf', function()
test('returns the index of the last occurence of a value in an array', function()
- assert_equal(_.lastIndexOf({1,2,3},2),2)
- assert_equal(_.lastIndexOf({'a','d','d','z'},'d'),3)
+ assert_equal(M.lastIndexOf({1,2,3},2),2)
+ assert_equal(M.lastIndexOf({'a','d','d','z'},'d'),3)
end)
test('returns nil when value was not found', function()
- assert_nil(_.lastIndexOf({'a','b','c','d'},'e'))
+ assert_nil(M.lastIndexOf({'a','b','c','d'},'e'))
end)
end)
@@ -182,11 +237,11 @@ context('Array functions specs', function()
context('findIndex', function()
test('returns the first index at which a predicate passes a truth test', function()
- assert_equal(_.findIndex({1,2,3,4,5},function(__,v) return v%2==0 end),2)
+ assert_equal(M.findIndex({1,2,3,4,5},function(__,v) return v%2==0 end),2)
end)
test('returns nil when nothing was found', function()
- assert_nil(_.findIndex({1,2,3,4,5},function(_,v) return v>5 end))
+ assert_nil(M.findIndex({1,2,3,4,5},function(_,v) return v>5 end))
end)
end)
@@ -194,11 +249,11 @@ context('Array functions specs', function()
context('findLastIndex', function()
test('returns the last index at which a predicate passes a truth test', function()
- assert_equal(_.findLastIndex({1,2,3,4,5},function(_,v) return v%2==0 end),4)
+ assert_equal(M.findLastIndex({1,2,3,4,5},function(_,v) return v%2==0 end),4)
end)
test('returns nil when nothing was found', function()
- assert_nil(_.findLastIndex({1,2,3,4,5},function(_,v) return v>5 end))
+ assert_nil(M.findLastIndex({1,2,3,4,5},function(_,v) return v>5 end))
end)
end)
@@ -206,41 +261,55 @@ context('Array functions specs', function()
context('addTop', function()
test('adds values at the top of an array', function()
- assert_true(_.isEqual(_.addTop({},1,2,3),{3,2,1}))
- assert_true(_.isEqual(_.addTop({},'a',true,3),{3,true,'a'}))
+ assert_true(M.isEqual(M.addTop({},1,2,3),{3,2,1}))
+ assert_true(M.isEqual(M.addTop({},'a',true,3),{3,true,'a'}))
end)
test('preserves the existing elements', function()
- assert_true(_.isEqual(_.addTop({1,2},1,2,3),{3,2,1,1,2}))
- assert_true(_.isEqual(_.addTop({'i','j'},'a',true,3),{3,true,'a','i','j'}))
+ assert_true(M.isEqual(M.addTop({1,2},1,2,3),{3,2,1,1,2}))
+ assert_true(M.isEqual(M.addTop({'i','j'},'a',true,3),{3,true,'a','i','j'}))
end)
end)
+ context('prepend', function()
+
+ test('adds values at the top of an array, preserving order', function()
+ assert_true(M.isEqual(M.prepend({},1,2,3),{1,2,3}))
+ assert_true(M.isEqual(M.prepend({},'a',true,3),{'a',true,3}))
+ end)
+
+ test('preserves the existing elements', function()
+ assert_true(M.isEqual(M.prepend({1,2},1,2,3),{1,2,3,1,2}))
+ assert_true(M.isEqual(M.prepend({'i','j'},'a',true,3),{'a',true,3,'i','j'}))
+ end)
+
+ end)
+
context('push', function()
test('appends values at the end of an array', function()
- assert_true(_.isEqual(_.push({},1,2,3),{1,2,3}))
- assert_true(_.isEqual(_.push({},'a',true,3),{'a',true,3}))
+ assert_true(M.isEqual(M.push({},1,2,3),{1,2,3}))
+ assert_true(M.isEqual(M.push({},'a',true,3),{'a',true,3}))
end)
test('preserves the existing elements', function()
- assert_true(_.isEqual(_.push({1,2},1,2,3),{1,2,1,2,3}))
- assert_true(_.isEqual(_.push({'i','j'},'a',true,3),{'i','j','a',true,3}))
+ assert_true(M.isEqual(M.push({1,2},1,2,3),{1,2,1,2,3}))
+ assert_true(M.isEqual(M.push({'i','j'},'a',true,3),{'i','j','a',true,3}))
end)
end)
- context('pop', function()
+ context('shift', function()
test('returns the value at the top of a given array', function()
- assert_equal(_.pop {1,7,9} ,1)
+ assert_equal(M.shift {1,7,9} ,1)
end)
test('also removes this value from the given array', function()
local array = {1,7,9}
- assert_equal(_.pop(array),1)
- assert_true(_.isEqual(array,{7,9}))
+ assert_equal(M.shift(array),1)
+ assert_true(M.isEqual(array,{7,9}))
end)
end)
@@ -248,13 +317,13 @@ context('Array functions specs', function()
context('unshift', function()
test('returns the value at the end of a given array', function()
- assert_equal(_.unshift {1,7,9} ,9)
+ assert_equal(M.unshift {1,7,9} ,9)
end)
test('also removes this value from the given array', function()
local array = {1,7,9}
- assert_equal(_.unshift(array),9)
- assert_true(_.isEqual(array,{1,7}))
+ assert_equal(M.unshift(array),9)
+ assert_true(M.isEqual(array,{1,7}))
end)
end)
@@ -262,8 +331,8 @@ context('Array functions specs', function()
context('pull', function()
test('removes all listed values in a given array', function()
- assert_true(_.same(_.pull({1,4,3,1,2,3},1),{4,3,2,3}))
- assert_true(_.same(_.pull({1,4,3,1,2,3},1,3),{4,2}))
+ assert_true(M.same(M.pull({1,4,3,1,2,3},1),{4,3,2,3}))
+ assert_true(M.same(M.pull({1,4,3,1,2,3},1,3),{4,2}))
end)
end)
@@ -271,23 +340,23 @@ context('Array functions specs', function()
context('removeRange', function()
test('removes all values within "start" and "finish" indexes', function()
- assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},2,4),{1,5,6}))
+ assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6},2,4),{1,5,6}))
end)
test('arg "finish" defaults to the end of the array when not given ', function()
- assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},3),{1,2}))
+ assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6},3),{1,2}))
end)
test('arg "start" defaults to the initial index when not given ', function()
- assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6}),{}))
+ assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6}),{}))
end)
test('args "start" and "finish" are be clamped to the array bound ', function()
- assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},0,100),{}))
+ assert_true(M.isEqual(M.removeRange({1,2,3,4,5,6},0,100),{}))
end)
- test('leaves the array untouched when "finish" < "start"', function()
- assert_true(_.isEqual(_.removeRange({1,2,3,4,5,6},4,2),{1,2,3,4,5,6}))
+ test('throws an error when "finish" < "start"', function()
+ assert_error(function()M.removeRange({1,2,3,4,5,6},4,2) end)
end)
end)
@@ -296,29 +365,12 @@ context('Array functions specs', function()
test('chunks in blocks consecutive values returning the same value from a given function', function()
local t = {1,2,2,3,3,4,4}
- local v = _.chunk(t, function(k,v) return v%2==0 end)
+ local v = M.chunk(t, function(v) return v%2==0 end)
assert_equal(#v, 4)
- _.each(v[1], function(k)
- assert_equal(v[1][k],1)
- end)
- assert_equal(#v[1],1)
- _.each(v[2], function(k)
- assert_equal(v[2][k],2)
- end)
- assert_equal(#v[2],2)
- _.each(v[3], function(k)
- assert_equal(v[3][k],3)
- end)
- assert_equal(#v[3],2)
- _.each(v[4], function(k)
- assert_equal(v[4][k],4)
- end)
- assert_equal(#v[4],2)
- end)
-
- test('Returns the first argument in case it is not an array', function()
- local t = {a = 1, b = 2}
- assert_equal(_.chunk(t, function(k,v) return v%2==0 end), t)
+ assert_true(M.isEqual(v[1], {1}))
+ assert_true(M.isEqual(v[2], {2,2}))
+ assert_true(M.isEqual(v[3], {3,3}))
+ assert_true(M.isEqual(v[4], {4,4}))
end)
end)
@@ -326,15 +378,15 @@ context('Array functions specs', function()
context('slice',function()
test('slices a portion of an array',function()
- assert_true(_.isEqual(_.slice({'a','b','c','d','e'},2,3),{'b','c'}))
+ assert_true(M.isEqual(M.slice({'a','b','c','d','e'},2,3),{'b','c'}))
end)
test('arg "right" bound defaults to the array length when not given',function()
- assert_true(_.isEqual(_.slice({'a','b','c','d','e'},3),{'c','d','e'}))
+ assert_true(M.isEqual(M.slice({'a','b','c','d','e'},3),{'c','d','e'}))
end)
test('arg "left" bound defaults to the initial index when not given',function()
- assert_true(_.isEqual(_.slice({'a','b','c','d','e'}),{'a','b','c','d','e'}))
+ assert_true(M.isEqual(M.slice({'a','b','c','d','e'}),{'a','b','c','d','e'}))
end)
end)
@@ -342,11 +394,11 @@ context('Array functions specs', function()
context('first',function()
test('returns the n-first elements', function()
- assert_true(_.isEqual(_.first({5,8,12,20},2),{5,8}))
+ assert_true(M.isEqual(M.first({5,8,12,20},2),{5,8}))
end)
test('arg "n" defaults 1 when not given', function()
- assert_true(_.isEqual(_.first({5,8,12,20}),{5}))
+ assert_true(M.isEqual(M.first({5,8,12,20}),{5}))
end)
end)
@@ -354,67 +406,58 @@ context('Array functions specs', function()
context('initial',function()
test('exludes the last N elements', function()
- assert_true(_.isEqual(_.initial({5,8,12,20},3),{5}))
- assert_true(_.isEqual(_.initial({5,8,12,20},4),{}))
+ assert_true(M.isEqual(M.initial({5,8,12,20},3),{5}))
+ assert_true(M.isEqual(M.initial({5,8,12,20},4),{}))
end)
test('returns all values but the last one if arg "n" was not given', function()
- assert_true(_.isEqual(_.initial({5,8,12,20}),{5,8,12}))
+ assert_true(M.isEqual(M.initial({5,8,12,20}),{5,8,12}))
end)
test('passing "n" greather than the array size returns an empty', function()
- assert_true(_.isEqual(_.initial({5,8,12,20},5),{}))
+ assert_true(M.isEqual(M.initial({5,8,12,20},5),{}))
end)
test('returns the whole array when "n" equals 0', function()
- assert_true(_.isEqual(_.initial({5,8,12,20},0),{5,8,12,20}))
- end)
-
- test('returns "nil" when arg "n" < 0', function()
- assert_nil(_.initial({5,8,12,20},-1))
- end)
+ assert_true(M.isEqual(M.initial({5,8,12,20},0),{5,8,12,20}))
+ end)
end)
context('last',function()
test('returns the last N elements', function()
- assert_true(_.isEqual(_.last({5,8,12,20},3),{8,12,20}))
- assert_true(_.isEqual(_.last({5,8,12,20},1),{20}))
- assert_true(_.isEqual(_.last({5,8,12,20},2),{12,20}))
- assert_true(_.isEqual(_.last({5,8,12,20},4),{5,8,12,20}))
+ assert_true(M.isEqual(M.last({5,8,12,20},3),{8,12,20}))
+ assert_true(M.isEqual(M.last({5,8,12,20},1),{20}))
+ assert_true(M.isEqual(M.last({5,8,12,20},2),{12,20}))
+ assert_true(M.isEqual(M.last({5,8,12,20},4),{5,8,12,20}))
end)
test('returns all values but the first one if arg "n" was not given', function()
- assert_true(_.isEqual(_.last({5,8,12,20}),{8,12,20}))
+ assert_true(M.isEqual(M.last({5,8,12,20}),{8,12,20}))
end)
test('if arg "n" is lower than the array size, returns all values', function()
- assert_true(_.isEqual(_.last({5,8,12,20},5),{5,8,12,20}))
- end)
-
- test('returns "nil" when arg "n" <= 0', function()
- assert_nil(_.last({5,8,12,20},0))
- assert_nil(_.last({5,8,12,20},-1))
- end)
+ assert_true(M.isEqual(M.last({5,8,12,20},5),{5,8,12,20}))
+ end)
end)
context('rest',function()
test('excludes all values before a given index', function()
- assert_true(_.isEqual(_.rest({5,8,12,20},2),{8,12,20}))
- assert_true(_.isEqual(_.rest({5,8,12,20},1),{5,8,12,20}))
- assert_true(_.isEqual(_.rest({5,8,12,20},4),{20}))
+ assert_true(M.isEqual(M.rest({5,8,12,20},2),{8,12,20}))
+ assert_true(M.isEqual(M.rest({5,8,12,20},1),{5,8,12,20}))
+ assert_true(M.isEqual(M.rest({5,8,12,20},4),{20}))
end)
test('returns an empty array when arg "index" > #array', function()
- assert_true(_.isEqual(_.rest({5,8,12,20},5),{}))
+ assert_true(M.isEqual(M.rest({5,8,12,20},5),{}))
end)
test('returns all values if arg "index" <= 0', function()
- assert_true(_.isEqual(_.rest({5,8,12,20},0),{5,8,12,20}))
- assert_true(_.isEqual(_.rest({5,8,12,20},-1),{5,8,12,20}))
+ assert_true(M.isEqual(M.rest({5,8,12,20},0),{5,8,12,20}))
+ assert_true(M.isEqual(M.rest({5,8,12,20},-1),{5,8,12,20}))
end)
end)
@@ -422,7 +465,7 @@ context('Array functions specs', function()
context('nth', function()
test('returns the value at "index"', function()
- assert_equal(3, _.nth({1,2,3,4,5,6}, 3))
+ assert_equal(3, M.nth({1,2,3,4,5,6}, 3))
end)
end)
@@ -430,7 +473,7 @@ context('Array functions specs', function()
context('compact',function()
test('trims out all falsy values from an array', function()
- assert_true(_.isEqual(_.compact({a,'a',false,'b',true}),{'a','b',true}))
+ assert_true(M.isEqual(M.compact({a,'a',false,'b',true}),{'a','b',true}))
end)
end)
@@ -438,11 +481,11 @@ context('Array functions specs', function()
context('flatten',function()
test('flattens nested arrays', function()
- assert_true(_.isEqual(_.flatten({1,{2,3},{4,5,{6,7}}}),{1,2,3,4,5,6,7}))
+ assert_true(M.isEqual(M.flatten({1,{2,3},{4,5,{6,7}}}),{1,2,3,4,5,6,7}))
end)
test('when given arg "shallow", flatten only first level', function()
- assert_true(_.isEqual(_.flatten({1,{2,3},{4,5,{6,7}}},true),{1,2,3,4,5,{6,7}}))
+ assert_true(M.isEqual(M.flatten({1,{2,3},{4,5,{6,7}}},true),{1,2,3,4,5,{6,7}}))
end)
end)
@@ -451,17 +494,17 @@ context('Array functions specs', function()
test('returns values in the first array not present in the second array', function()
local array = {1,2,'a',4,5}
- assert_true(_.isEqual(_.difference(array,{1,'a'}),{2,4,5}))
- assert_true(_.isEqual(_.difference(array,{5}),{1,2,'a',4}))
+ assert_true(M.isEqual(M.difference(array,{1,'a'}),{2,4,5}))
+ assert_true(M.isEqual(M.difference(array,{5}),{1,2,'a',4}))
end)
test('ignores values in the second array not found in the first array', function()
local array = {1,2,'a',4,5}
- assert_true(_.isEqual(_.difference(array,{1,'a','b','c'}),{2,4,5}))
+ assert_true(M.isEqual(M.difference(array,{1,'a','b','c'}),{2,4,5}))
end)
test('leaves array untouched when given no extra-args', function()
- assert_true(_.isEqual(_.difference({1,2,'a',4,5}),{1,2,'a',4,5}))
+ assert_true(M.isEqual(M.difference({1,2,'a',4,5}),{1,2,'a',4,5}))
end)
end)
@@ -470,12 +513,12 @@ context('Array functions specs', function()
test('returns the duplicate-free union of all passed-in arrays', function()
local a = {"a"}; local b = {1,2,3}; local c = {2,10}
- assert_true(_.isEqual(_.union(a,b,c),{'a',1,2,3,10}))
+ assert_true(M.isEqual(M.union(a,b,c),{'a',1,2,3,10}))
end)
test('accepts nested arrays as well', function()
local a = {"a",{"b","c"}}; local b = {1,{2},3}; local c = {2,10}
- assert_true(_.isEqual(_.union(a,b,c),{'a','b','c',1,2,3,10}))
+ assert_true(M.isEqual(M.union(a,b,c),{'a','b','c',1,2,3,10}))
end)
end)
@@ -484,12 +527,12 @@ context('Array functions specs', function()
test('returns the intersection of all passed-in arrays', function()
local a = {1,3}; local b = {4,2,3}; local c = {2,3,10}
- assert_true(_.isEqual(_.intersection(a,b,c),{3}))
+ assert_true(M.isEqual(M.intersection(a,b,c),{3}))
end)
test('fails with nested arrays', function()
local a = {1,{3}}; local b = {4,2,3}; local c = {2,3,10}
- assert_true(_.isEqual(_.intersection(a,b,c),{}))
+ assert_true(M.isEqual(M.intersection(a,b,c),{}))
end)
end)
@@ -498,9 +541,9 @@ context('Array functions specs', function()
test('returns the symmetric difference from two arrays', function()
local a = {1,3}; local b = {4,2,3}; local c = {2,3,10}
- assert_true(_.same(_.symmetricDifference(a, b), {1,4,2}))
- assert_true(_.same(_.symmetricDifference(a, c), {1,2,10}))
- assert_true(_.same(_.symmetricDifference(b, c), {4,10}))
+ assert_true(M.same(M.symmetricDifference(a, b), {1,4,2}))
+ assert_true(M.same(M.symmetricDifference(a, c), {1,2,10}))
+ assert_true(M.same(M.symmetricDifference(b, c), {4,10}))
end)
end)
@@ -508,7 +551,7 @@ context('Array functions specs', function()
context('unique',function()
test('returns a duplicate-free array',function()
- assert_true(_.isEqual(_.unique({1,1,2,2,3,3,4,4,4,5}),{1,2,3,4,5}))
+ assert_true(M.isEqual(M.unique({1,1,2,2,3,3,4,4,4,5}),{1,2,3,4,5}))
end)
end)
@@ -516,8 +559,8 @@ context('Array functions specs', function()
context('isunique',function()
test('Checks if a given array is duplicate-free',function()
- assert_true(_.isunique({1,2,3,4,5}))
- assert_false(_.isunique({1,2,3,4,4}))
+ assert_true(M.isunique({1,2,3,4,5}))
+ assert_false(M.isunique({1,2,3,4,4}))
end)
end)
@@ -525,14 +568,25 @@ context('Array functions specs', function()
context('zip',function()
test('zips together values from different arrays sharing the same index', function()
local names = {'Bob','Alice','James'}; local ages = {22, 23}
- assert_true(_.isEqual(_.zip(names,ages),{{'Bob',22},{'Alice',23},{'James'}}))
+ assert_true(M.isEqual(M.zip(names,ages),{{'Bob',22},{'Alice',23},{'James'}}))
end)
end)
+ context('zipWith',function()
+ test('zips together values from different arrays sharing the same index using a function', function()
+ local names = {'Bob','Alice','James'}; local ages = {22, 23, 25}
+ local function introduce(name, age) return 'My name is '..name..' and I am '..age..' years old.' end
+ local t = M.zipWith(introduce,names,ages)
+ assert_equal(t[1],'My name is Bob and I am 22 years old.')
+ assert_equal(t[2],'My name is Alice and I am 23 years old.')
+ assert_equal(t[3],'My name is James and I am 25 years old.')
+ end)
+ end)
+
context('append',function()
test('appends two arrays together', function()
- assert_true(_.isEqual(_.append({1,2,3},{'a','b'}),{1,2,3,'a','b'}))
+ assert_true(M.isEqual(M.append({1,2,3},{'a','b'}),{1,2,3,'a','b'}))
end)
end)
@@ -540,8 +594,8 @@ context('Array functions specs', function()
context('interleave',function()
test('interleaves values from passed-in arrays', function()
- assert_true(_.isEqual(_.interleave({1,2,3},{'a','b','c'}),{1,'a',2,'b',3,'c'}))
- assert_true(_.isEqual(_.interleave({1},{'a','b','c'}),{1,'a','b','c'}))
+ assert_true(M.isEqual(M.interleave({1,2,3},{'a','b','c'}),{1,'a',2,'b',3,'c'}))
+ assert_true(M.isEqual(M.interleave({1},{'a','b','c'}),{1,'a','b','c'}))
end)
end)
@@ -549,35 +603,36 @@ context('Array functions specs', function()
context('interpose',function()
test('interposes a value in-between values from a passed-in array', function()
- assert_true(_.isEqual(_.interpose('a',{1,2,3}),{1,'a',2,'a',3}))
- assert_true(_.isEqual(_.interpose(false,{5,5,5,5}),{5,false,5,false,5,false,5}))
- end)
+ assert_true(M.isEqual(M.interpose({1,2,3},'a'),{1,'a',2,'a',3}))
+ assert_true(M.isEqual(M.interpose({5,5,5,5}, false),{5,false,5,false,5,false,5}))
+ end)
+
+ test('leaves the array untouched if containing a single element', function()
+ assert_true(M.isEqual(M.interpose({1},'a'),{1}))
+ end)
end)
context('range',function()
test('generate an arithmetic progression', function()
- assert_true(_.isEqual(_.range(1,5,1),{1,2,3,4,5}))
- assert_true(_.isEqual(_.range(-2,5,1),{-2,-1,0,1,2,3,4,5}))
- assert_true(_.isEqual(_.range(1,5,2),{1,3,5}))
- end)
-
- test('arg "step" default to 1 when no given', function()
- assert_true(_.isEqual(_.range(1,5),{1,2,3,4,5}))
+ assert_true(M.isEqual(M.range(1,5,1),{1,2,3,4,5}))
+ assert_true(M.isEqual(M.range(-2,5,1),{-2,-1,0,1,2,3,4,5}))
+ assert_true(M.isEqual(M.range(1,5,2),{1,3,5}))
end)
- test('when a limit cannot be reached via "step", returns an empty array', function()
- assert_true(_.isEqual(_.range(1,5,0),{}))
- assert_true(_.isEqual(_.range(1,5,-1),{}))
+ test('arg "step" default to 1 or -1 when no given', function()
+ assert_true(M.isEqual(M.range(1,5),{1,2,3,4,5}))
+ assert_true(M.isEqual(M.range(5,1),{5,4,3,2,1}))
end)
test('handles real values as well', function()
- assert_true(_.isEqual(_.range(3.2,5,0.5),{3.2,3.7,4.2,4.7}))
+ assert_true(M.isEqual(M.range(3.2,5,0.5),{3.2,3.7,4.2,4.7}))
end)
- test('when only one arg is passed, counts from 0', function()
- assert_true(_.isEqual(_.range(3),{0,1,2,3}))
+ test('when only one arg is passed, counts from 1', function()
+ assert_true(M.isEqual(M.range(3),{1,2,3}))
+ assert_true(M.isEqual(M.range(-3),{-1,-2,-3}))
end)
end)
@@ -585,8 +640,17 @@ context('Array functions specs', function()
context('rep',function()
test('generates a list of n repetitions of a value', function()
- assert_true(_.isEqual(_.rep('a',4),{'a','a','a','a'}))
- assert_true(_.isEqual(_.rep(false,3),{false, false, false}))
+ assert_true(M.isEqual(M.rep('a',4),{'a','a','a','a'}))
+ assert_true(M.isEqual(M.rep(false,3),{false, false, false}))
+ end)
+
+ end)
+
+ context('powerset',function()
+
+ test('generates the powerset of a given array', function()
+ assert_true(M.isEqual(M.powerset({1,2,3}),{{1},{2},{3},{1,2},{2,3},{1,2,3}}))
+ assert_true(M.isEqual(M.powerset({1,2,3,4}),{{1},{2},{3},{4},{1,2},{2,3},{3,4},{1,2,3},{2,3,4},{1,2,3,4}}))
end)
end)
@@ -594,83 +658,134 @@ context('Array functions specs', function()
context('partition',function()
test('iterates on partitions of a given array', function()
- local array = _.range(1,10)
- local split5 = {_.range(1,5), _.range(6,10)}
- local split3 = {_.range(1,3), _.range(4,6), _.range(7,9), {10}}
+ local array = M.range(1,10)
+ local split5 = {M.range(1,5), M.range(6,10)}
+ local split3 = {M.range(1,3), M.range(4,6), M.range(7,9), {10}}
local i = 0
- for p in _.partition(array,5) do
+ for p in M.partition(array,5) do
i = i + 1
- assert_true(_.isEqual(p, split5[i]))
+ assert_true(M.isEqual(p, split5[i]))
end
i = 0
- for p in _.partition(array,3) do
+ for p in M.partition(array,3) do
i = i + 1
- assert_true(_.isEqual(p, split3[i]))
+ assert_true(M.isEqual(p, split3[i]))
end
end)
test('if a 3rd argument pad is supplied, will adjust the last partition', function()
- local array = _.range(1,10)
+ local array = M.range(1,10)
local split4 = {{1,2,3,4},{5,6,7,8},{9,10,0,0}}
local i = 0
- for p in _.partition(array,4,0) do
+ for p in M.partition(array,4,0) do
i = i + 1
- assert_true(_.isEqual(p, split4[i]))
+ assert_true(M.isEqual(p, split4[i]))
end
end)
end)
- context('sliding',function()
+ context('overlapping',function()
test('returns overlapping subsequences', function()
- local array = _.range(1,10)
+ local array = M.range(1,10)
local sliding2 = {{1,2},{2,3},{3,4},{4,5},{5,6},{6,7},{7,8},{8,9},{9,10}}
local sliding3 = {{1,2,3},{3,4,5},{5,6,7},{7,8,9},{9,10}}
local sliding5 = {{1,2,3,4,5},{5,6,7,8,9},{9,10}}
local i = 0
- for p in _.sliding(array,2) do
+ for p in M.overlapping(array,2) do
i = i + 1
- assert_true(_.isEqual(p, sliding2[i]))
+ assert_true(M.isEqual(p, sliding2[i]))
end
i = 0
- for p in _.sliding(array,3) do
+ for p in M.overlapping(array,3) do
i = i + 1
- assert_true(_.isEqual(p, sliding3[i]))
+ assert_true(M.isEqual(p, sliding3[i]))
end
i = 0
- for p in _.sliding(array,5) do
+ for p in M.overlapping(array,5) do
i = i + 1
- assert_true(_.isEqual(p, sliding5[i]))
+ assert_true(M.isEqual(p, sliding5[i]))
end
end)
test('if a 3rd argument pad is supplied, will adjust the last subsequence', function()
- local array = _.range(1,10)
+ local array = M.range(1,10)
local sliding3 = {{1,2,3},{3,4,5},{5,6,7},{7,8,9},{9,10,0}}
local sliding5 = {{1,2,3,4,5},{5,6,7,8,9},{9,10,0,0,0}}
local i = 0
- for p in _.sliding(array,3,0) do
+ for p in M.overlapping(array,3,0) do
i = i + 1
- assert_true(_.isEqual(p, sliding3[i]))
+ assert_true(M.isEqual(p, sliding3[i]))
end
i = 0
- for p in _.sliding(array,5,0) do
+ for p in M.overlapping(array,5,0) do
i = i + 1
- assert_true(_.isEqual(p, sliding5[i]))
+ assert_true(M.isEqual(p, sliding5[i]))
end
end)
- end)
+ end)
+
+ context('aperture', function()
+
+ test('returns sliding partitions of a given array', function()
+ local array = M.range(1,5)
+ local slides2 = {{1,2},{2,3},{3,4},{4,5}}
+ local slides3 = {{1,2,3},{2,3,4},{3,4,5}}
+ local slides4 = {{1,2,3,4},{2,3,4,5}}
+ local slides5 = {{1,2,3,4,5}}
+
+ local i = 0
+ for p in M.aperture(array, 2) do
+ i = i + 1
+ assert_true(M.isEqual(p, slides2[i]))
+ end
+
+ i = 0
+ for p in M.aperture(array, 3) do
+ i = i + 1
+ assert_true(M.isEqual(p, slides3[i]))
+ end
+
+ i = 0
+ for p in M.aperture(array, 4) do
+ i = i + 1
+ assert_true(M.isEqual(p, slides4[i]))
+ end
+
+ i = 0
+ for p in M.aperture(array, 5) do
+ i = i + 1
+ assert_true(M.isEqual(p, slides5[i]))
+ end
+ end)
+
+ end)
+
+ context('pairwise', function()
+
+ test('returns sliding partitions of a given array', function()
+ local array = M.range(1,5)
+ local pw = {{1,2},{2,3},{3,4},{4,5}}
+
+ local i = 0
+ for p in M.pairwise(array) do
+ i = i + 1
+ assert_true(M.isEqual(p, pw[i]))
+ end
+ end)
+
+ end)
context('permutation',function()
test('iterates on permutations of a given array', function()
local array = {'a','b', 'c'}
local perm = {'abc','acb', 'bac', 'bca', 'cab', 'cba'}
- for p in _.permutation(array) do
- local strp = _.concat(p)
- _.pull(perm, strp)
+ for p in M.permutation(array) do
+ local strp = M.concat(p)
+ M.pull(perm, strp)
end
assert_true(#perm == 0)
end)
@@ -680,8 +795,8 @@ context('Array functions specs', function()
context('invert',function()
test('switches key-values pairs', function()
- assert_true(_.isEqual(_.invert({1,2,3}),{1,2,3}))
- assert_true(_.isEqual(_.invert({'a','b','c'}),{a = 1,b = 2,c = 3}))
+ assert_true(M.isEqual(M.invert({1,2,3}),{1,2,3}))
+ assert_true(M.isEqual(M.invert({'a','b','c'}),{a = 1,b = 2,c = 3}))
end)
end)
@@ -689,25 +804,77 @@ context('Array functions specs', function()
context('concat',function()
test('concatenates an array contents', function()
- assert_equal(_.concat({1,2,3,4}),'1234')
- assert_equal(_.concat({'a',1,0,1,'b'}),'a101b')
+ assert_equal(M.concat({1,2,3,4}),'1234')
+ assert_equal(M.concat({'a',1,0,1,'b'}),'a101b')
end)
test('handles boolean values', function()
- assert_equal(_.concat({1,true,3,false}),'1true3false')
+ assert_equal(M.concat({1,true,3,false}),'1true3false')
end)
test('when arg "sep" is given, uses "sep" as a separator', function()
- assert_equal(_.concat({1,3,false,'A'},' '),'1 3 false A')
- assert_equal(_.concat({1,3,false,'A'},', '),'1, 3, false, A')
+ assert_equal(M.concat({1,3,false,'A'},' '),'1 3 false A')
+ assert_equal(M.concat({1,3,false,'A'},', '),'1, 3, false, A')
end)
test('when args "i" and/or "j" are given, concats values within "i" and "j" indexes', function()
- assert_equal(_.concat({1,3,false,'A'},' ',2,3),'3 false')
- assert_equal(_.concat({1,3,false,'A'},', ',2,3),'3, false')
- assert_equal(_.concat({1,3,false,'A','K'},' ',2),'3 false A K')
+ assert_equal(M.concat({1,3,false,'A'},' ',2,3),'3 false')
+ assert_equal(M.concat({1,3,false,'A'},', ',2,3),'3, false')
+ assert_equal(M.concat({1,3,false,'A','K'},' ',2),'3 false A K')
end)
+ end)
+
+ context('xprod',function()
+
+ test('returns all possible pairs', function()
+ local r = M.xprod({1,2,3},{'a','b'})
+ assert_true(M.isEqual(r[1],{1,'a'}))
+ assert_true(M.isEqual(r[2],{1,'b'}))
+ assert_true(M.isEqual(r[3],{2,'a'}))
+ assert_true(M.isEqual(r[4],{2,'b'}))
+ assert_true(M.isEqual(r[5],{3,'a'}))
+ assert_true(M.isEqual(r[6],{3,'b'}))
+ end)
+
+ end)
+
+ context('sum',function()
+
+ test('returns the sum of array values', function()
+ assert_equal(M.sum {1,2,3,4,5}, 15)
+ assert_equal(M.sum {1,2,3,4}, 10)
+ assert_equal(M.sum {1,2,3}, 6)
+ end)
+
+ end)
+
+ context('product',function()
+
+ test('returns the product of array values', function()
+ assert_equal(M.product {1,2,3,4,5}, 120)
+ assert_equal(M.product {1,2,3,4}, 24)
+ assert_equal(M.product {1,2,3}, 6)
+ end)
+
+ end)
+
+ context('mean',function()
+
+ test('returns the mean of array values', function()
+ assert_equal(M.mean {1,2,3,4,5}, 3)
+ assert_equal(M.mean {1,2,3,4}, 2.5)
+ end)
+
+ end)
+
+ context('meadian',function()
+
+ test('returns the median of array values', function()
+ assert_equal(M.median {1,2,3,4,5}, 3)
+ assert_equal(M.median {1,2,3,4}, 2.5)
+ end)
+
end)
end) \ No newline at end of file
diff --git a/spec/chaining_spec.lua b/spec/chaining_spec.lua
index 065491a..5a24aa6 100644
--- a/spec/chaining_spec.lua
+++ b/spec/chaining_spec.lua
@@ -1,4 +1,4 @@
-require 'luacov'
+--require 'luacov'
local _ = require 'moses'
context('Chaining specs', function()
diff --git a/spec/func_spec.lua b/spec/func_spec.lua
index 2803922..1e588d0 100644
--- a/spec/func_spec.lua
+++ b/spec/func_spec.lua
@@ -1,17 +1,17 @@
-require 'luacov'
-local _ = require 'moses'
+--require 'luacov'
+local M = require 'moses'
context('Utility functions specs', function()
context('noop', function()
test('the no-operation function',function()
- assert_nil(_.noop())
- assert_nil(_.noop(nil))
- assert_nil(_.noop(false))
- assert_nil(_.noop({}))
- assert_nil(_.noop(function() end))
- assert_nil(_.noop(_.noop))
+ assert_nil(M.noop())
+ assert_nil(M.noop(nil))
+ assert_nil(M.noop(false))
+ assert_nil(M.noop({}))
+ assert_nil(M.noop(function() end))
+ assert_nil(M.noop(M.noop))
end)
end)
@@ -19,9 +19,9 @@ context('Utility functions specs', function()
context('identity', function()
test('returns the received value',function()
- assert_equal(_.identity(1),1)
+ assert_equal(M.identity(1),1)
local v = {x = 0}
- assert_equal(_.identity(v),v)
+ assert_equal(M.identity(v),v)
assert_not_equal(v,{x = 0})
end)
@@ -30,7 +30,7 @@ context('Utility functions specs', function()
context('constant', function()
test('creates a constant function',function()
- local gravity = _.constant(9.81)
+ local gravity = M.constant(9.81)
assert_equal(gravity(),9.81)
assert_equal(gravity(10), 9.81)
assert_equal(gravity(nil), 9.81)
@@ -38,69 +38,80 @@ context('Utility functions specs', function()
end)
+ context('applySpec', function()
+
+ test('returns a spec function which produces objects',function()
+ local stats = M.applySpec({
+ min = function(...) return math.min(...) end,
+ max = function(...) return math.max(...) end,
+ })
+
+ for i = 1, 10 do
+ local mn, mx = math.random(1,10), math.random(11,20)
+ local t = M.range(mn, mx)
+ table.sort(t)
+ local r = stats(unpack(t))
+ assert_equal(r.min, t[1])
+ assert_equal(r.max, t[#t])
+ end
+ end)
+
+ end)
+
context('memoize', function()
local fib_time, fib_value, mfib_time, mfib_value
local fib, mfib
- before(function()
- local function fib(n)
- return n < 2 and n or fib(n-1)+fib(n-2)
- end
- local times = 10
- local mfib = _.memoize(fib)
- fib_time = os.clock()
- for i = 1, times do fib_value = (fib_value or 0)+fib(20) end
- fib_time = (os.clock()-fib_time)*1000
-
- mfib_time = os.clock()
- for i = 1, times do mfib_value = (mfib_value or 0)+mfib(20) end
- mfib_time = (os.clock()-mfib_time )*1000
- end)
-
test('memoizes an expensive function by caching its results',function()
- assert_true(mfib_time<=fib_time)
+ local function fib(n) return n < 2 and n or fib(n-1)+fib(n-2) end
+ local mfib = M.memoize(fib)
+ assert_equal(fib(10), mfib(10))
+ assert_equal(fib(15), mfib(15))
+ assert_equal(fib(8), mfib(8))
+ assert_equal(fib(13), mfib(13))
end)
test('can take a hash function to compute an unique output for multiple args',function()
-
local function hash(a,b) return (a^13+b^19) end
local function fact(a) return a <= 1 and 1 or a*fact(a-1) end
local diffFact = function(a,b) return fact(a)-fact(b) end
- local mdiffFact = _.memoize(function(a,b) return fact(a)-fact(b) end,hash)
+ local mdiffFact = M.memoize(function(a,b) return fact(a)-fact(b) end,hash)
local times, rep = 100, 10
- local time = os.clock()
for j = 1,times do
for ai = 1,rep do
- for aj = 1,rep do diffFact(ai,aj) end
+ for aj = 1,rep do
+ assert_equal(diffFact(ai,aj), mdiffFact(ai,aj))
+ end
end
end
- time = (os.clock()-time)*1000
-
- local mtime = os.clock()
- for j = 1,times do
- for ai = 1,rep do
- for aj = 1,rep do mdiffFact(ai,aj) end
- end
- end
- mtime = (os.clock()-mtime)*1000
-
- assert_true(mtime<=time)
-
end)
- end)
+ end)
+
+ context('unfold', function()
+
+ test('builds a list from a seed value using a iterator',function()
+ local function iter(seed)
+ if seed < 100 then return seed, seed * 2 end
+ end
+ assert_true(M.isEqual(M.unfold(iter,1),{1,2,4,8,16,32,64}))
+ assert_true(M.isEqual(M.unfold(iter,5),{5, 10,20,40,80}))
+ assert_true(M.isEqual(M.unfold(iter,10),{10,20,40,80}))
+ end)
+
+ end)
context('once', function()
test('returns a version of a function that runs once',function()
- local sq = _.once(function(a) return a*a end)
+ local sq = M.once(function(a) return a*a end)
assert_equal(sq(2),4)
end)
test('successive calls will keep yielding the original answer',function()
- local sq = _.once(function(a) return a*a end)
+ local sq = M.once(function(a) return a*a end)
for i = 1,10 do
assert_equal(sq(i),1)
end
@@ -112,7 +123,7 @@ context('Utility functions specs', function()
test('returns a version of a function that runs no more than count-th calls',function()
local function say(something) return something end
- local speak3times = _.before(say, 3)
+ local speak3times = M.before(say, 3)
assert_equal(speak3times('a'), 'a')
assert_equal(speak3times('b'), 'b')
assert_equal(speak3times('c'), 'c')
@@ -128,7 +139,7 @@ context('Utility functions specs', function()
test('returns a function that will respond on its count-th call',function()
local function a(r) return (r) end
- a = _.after(a,5)
+ a = M.after(a,5)
for i = 1,10 do
if i < 5 then
assert_nil(a(i))
@@ -145,15 +156,15 @@ context('Utility functions specs', function()
test('can compose commutative functions',function()
local greet = function(name) return "hi: " .. name end
local exclaim = function(sentence) return sentence .. "!" end
- assert_equal(_.compose(greet,exclaim)('moe'),'hi: moe!')
- assert_equal(_.compose(exclaim,greet)('moe'),'hi: moe!')
+ assert_equal(M.compose(greet,exclaim)('moe'),'hi: moe!')
+ assert_equal(M.compose(exclaim,greet)('moe'),'hi: moe!')
end)
test('composes mutiple functions',function()
local function f(x) return x^2 end
local function g(x) return x+1 end
local function h(x) return x/2 end
- local compositae = _.compose(f,g,h)
+ local compositae = M.compose(f,g,h)
assert_equal(compositae(10),36)
assert_equal(compositae(20),121)
end)
@@ -162,10 +173,10 @@ context('Utility functions specs', function()
local function f(s) return (s or '')..'f' end
local function g(s) return (s or '')..'g' end
local function h(s) return (s or '')..'h' end
- assert_equal(_.compose(f,g,h)(),'hgf')
- assert_equal(_.compose(h,g,f)(),'fgh')
- assert_equal(_.compose(f,h,g)(),'ghf')
- assert_equal(_.compose(g,h,f)(),'fhg')
+ assert_equal(M.compose(f,g,h)(),'hgf')
+ assert_equal(M.compose(h,g,f)(),'fgh')
+ assert_equal(M.compose(f,h,g)(),'ghf')
+ assert_equal(M.compose(g,h,f)(),'fhg')
end)
end)
@@ -176,8 +187,8 @@ context('Utility functions specs', function()
local function f(x) return x^2 end
local function g(x) return x+1 end
local function h(x) return x/2 end
- assert_equal(_.pipe(10,f,g,h),36)
- assert_equal(_.pipe(20,f,g,h),121)
+ assert_equal(M.pipe(10,f,g,h),36)
+ assert_equal(M.pipe(20,f,g,h),121)
end)
end)
@@ -185,10 +196,10 @@ context('Utility functions specs', function()
context('complement', function()
test('returns a function which returns the logical complement of a given function',function()
- assert_false(_.complement(function() return true end)())
- assert_true(_.complement(function() return false end)())
- assert_true(_.complement(function() return nil end)())
- assert_false(_.complement(function() return 1 end)())
+ assert_false(M.complement(function() return true end)())
+ assert_true(M.complement(function() return false end)())
+ assert_true(M.complement(function() return nil end)())
+ assert_false(M.complement(function() return 1 end)())
end)
end)
@@ -199,7 +210,7 @@ context('Utility functions specs', function()
local function f(x) return x^2 end
local function g(x) return x+1 end
local function h(x) return x/2 end
- local rf, rg, rh = _.juxtapose(10, f, g, h)
+ local rf, rg, rh = M.juxtapose(10, f, g, h)
assert_equal(rf, 100)
assert_equal(rg, 11)
assert_equal(rh, 5)
@@ -211,7 +222,7 @@ context('Utility functions specs', function()
test('wraps a function and passes args',function()
local greet = function(name) return "hi: " .. name end
- local backwards = _.wrap(greet, function(f,arg)
+ local backwards = M.wrap(greet, function(f,arg)
return f(arg) ..'\nhi: ' .. arg:reverse()
end)
assert_equal(backwards('john'),'hi: john\nhi: nhoj')
@@ -223,12 +234,12 @@ context('Utility functions specs', function()
test('calls a given function n times',function()
local f = ('Lua programming'):gmatch('.')
- local r = _.times(3,f)
- assert_true(_.isEqual(r,{'L','u','a'}))
+ local r = M.times(f, 3)
+ assert_true(M.isEqual(r,{'L','u','a'}))
local count = 0
local function counter() count = count+1 end
- _.times(10,counter)
+ M.times(counter, 10)
assert_equal(count,10)
end)
@@ -237,7 +248,7 @@ context('Utility functions specs', function()
context('bind', function()
test('binds a value to the first arg of a function',function()
- local sqrt2 = _.bind(math.sqrt,2)
+ local sqrt2 = M.bind(math.sqrt,2)
assert_equal(sqrt2(),math.sqrt(2))
end)
@@ -246,9 +257,9 @@ context('Utility functions specs', function()
context('bind2', function()
test('binds a value to the second arg of a function',function()
- local last2 = _.bind2(_.last,2)
+ local last2 = M.bind2(M.last,2)
local r = last2({1,2,3,4,5,6})
- assert_true(_.isEqual(r, {5,6}))
+ assert_true(M.isEqual(r, {5,6}))
end)
end)
@@ -259,14 +270,14 @@ context('Utility functions specs', function()
local function out(...)
return table.concat {...}
end
- out = _.bindn(out,'OutPut',':',' ')
+ out = M.bindn(out,'OutPut',':',' ')
assert_equal(out(1,2,3),'OutPut: 123')
assert_equal(out('a','b','c','d'),'OutPut: abcd')
end)
end)
- context('bindAll', function()
+ context('bindall', function()
test('binds methods to object',function()
local window = {
@@ -274,7 +285,7 @@ context('Utility functions specs', function()
setName = function(w,name) w.name = name end,
getName = function(w) return w.name end,
}
- window = _.bindAll(window, 'setPos', 'setName', 'getName')
+ window = M.bindall(window, 'setPos', 'setName', 'getName')
window.setPos(10,15)
window.setName('fooApp')
@@ -285,25 +296,44 @@ context('Utility functions specs', function()
end)
end)
+
+ context('cond', function()
+
+ test('return a function which runs a set of predicates',function()
+ local multipleOf = M.cond({
+ {function(v) return v%2==0 end, function(v) return v..' is multiple of 2' end},
+ {function(v) return v%3==0 end, function(v) return v..' is multiple of 3' end},
+ {function(v) return v%5==0 end, function(v) return v..' is multiple of 5' end},
+ {function() return true end, function(v) return 'could not find an answer for '..v end}
+ })
+ for i = 15, 20 do
+ assert_equal(multipleOf(i),
+ i%2 == 0 and i..' is multiple of 2' or
+ i%3 == 0 and i..' is multiple of 3' or
+ 'could not find an answer for '..i)
+ end
+ end)
+
+ end)
context('uniqueId', function()
test('returns an unique (for the current session) integer Id',function()
local ids = {}
for i = 1,100 do
- local newId = _.uniqueId()
- assert_false(_.include(ids,newId))
- _.push(ids,newId)
+ local newId = M.uniqueId()
+ assert_false(M.include(ids,newId))
+ M.push(ids,newId)
end
end)
test('accepts a string template to format the returned id',function()
local ids = {}
for i = 1,100 do
- local newId = _.uniqueId('ID:%s')
+ local newId = M.uniqueId('ID:%s')
assert_equal(newId,'ID:'..newId:sub(4))
- assert_false(_.include(ids,newId))
- _.push(ids,newId)
+ assert_false(M.include(ids,newId))
+ M.push(ids,newId)
end
end)
@@ -311,10 +341,10 @@ context('Utility functions specs', function()
local ids = {}
local formatter = function(ID) return '$'..ID..'$' end
for i = 1,100 do
- local newId = _.uniqueId(formatter)
+ local newId = M.uniqueId(formatter)
assert_not_nil(newId:match('^%$%d+%$$'))
- assert_false(_.include(ids,newId))
- _.push(ids,newId)
+ assert_false(M.include(ids,newId))
+ M.push(ids,newId)
end
end)
@@ -323,45 +353,125 @@ context('Utility functions specs', function()
context('iterator', function()
test('creates an iterator which continuously applies f on an input',function()
- local next_even = _.iterator(function(x) return x + 2 end, 0)
+ local next_even = M.iterator(function(x) return x + 2 end, 0)
assert_equal(next_even(), 2)
assert_equal(next_even(), 4)
assert_equal(next_even(), 6)
assert_equal(next_even(), 8)
assert_equal(next_even(),10)
end)
+
+ test('can be set to run up to a maximum number of calls',function()
+ local next_even = M.iterator(function(x) return x + 2 end, 0, 3)
+ assert_equal(next_even(), 2)
+ assert_equal(next_even(), 4)
+ assert_equal(next_even(), 6)
+ assert_nil(next_even())
+ end)
end)
context('array', function()
test('iterates a given iterator and returns its values in an array',function()
- local letters = _.array(('Lua'):gmatch('.'))
- assert_true(_.isEqual(letters,{'L','u','a'}))
+ local letters = M.array(('Lua'):gmatch('.'))
+ assert_true(M.isEqual(letters,{'L','u','a'}))
- local numbers = _.array(pairs(_.range(1,10)))
- assert_true(_.isEqual(numbers,_.range(1,10)))
+ local numbers = M.array(pairs(M.range(1,10)))
+ assert_true(M.isEqual(numbers,M.range(1,10)))
end)
- end)
+ end)
+
+ context('castArray', function()
+
+ test('converts value to an array',function()
+ assert_true(M.isEqual(M.castArray(1),{1}))
+ assert_true(M.isEqual(M.castArray(print),{print}))
+ assert_true(M.isEqual(M.castArray(true),{true}))
+ end)
+
+ test('leaves given value untouched if it is an array',function()
+ local t1 = {1,2}
+ local t2 = {nil, true, false}
+ assert_true(M.isEqual(M.castArray(t1),t1))
+ assert_true(M.isEqual(M.castArray(t2),t2))
+ end)
+
+ end)
context('flip', function()
test('creates a function which runs f with arguments flipped',function()
local function f(...) return table.concat({...}) end
- local flipped = _.flip(f)
+ local flipped = M.flip(f)
assert_equal(flipped('a','b','c'),'cba')
end)
- end)
+ end)
+
+ context('nthArg', function()
+
+ test('creates a function which returns the nth arg',function()
+ local f2 = M.nthArg(2)
+ local f3 = M.nthArg(3)
+ local f4 = M.nthArg(4)
+ assert_equal(f2(4,8,5,4,6),8)
+ assert_equal(f3(4,8,5,4,6),5)
+ assert_equal(f4(4,8,5,4,6),4)
+ end)
+
+ test('if n is negative, will count from the end',function()
+ local f2 = M.nthArg(-2)
+ local f3 = M.nthArg(-3)
+ local f4 = M.nthArg(-4)
+ assert_equal(f2(4,8,5,4,6),4)
+ assert_equal(f3(4,8,5,4,6),5)
+ assert_equal(f4(4,8,5,4,6),8)
+ end)
+
+ end)
+
+ context('unary', function()
+
+ test('creates a function which accepts only one arg',function()
+ local f = M.unary(function(...) return ... end)
+ assert_equal(f(1),1)
+ assert_equal(f(1,2),1)
+ assert_equal(f(1,2,3),1)
+ end)
+
+ end)
+
+ context('ary', function()
+
+ test('creates a function which accepts up to n args',function()
+ local f = M.ary(function(...) return ... end, 2)
+ assert_true(M.isEqual({f(1,2)},{1,2}))
+ assert_true(M.isEqual({f(1,2,3)},{1,2}))
+ assert_true(M.isEqual({f(1,2,3,4)},{1,2}))
+ end)
+
+ end)
+
+ context('rearg', function()
+
+ test('creates a function with args reordered',function()
+ local f = M.rearg(function(...) return ... end, {3,2,1})
+ assert_true(M.isEqual({f(1,2,3)},{3,2,1}))
+ assert_true(M.isEqual({f(2,1,3)},{3,1,2}))
+ assert_true(M.isEqual({f(3,2,1)},{1,2,3}))
+ end)
+
+ end)
context('over', function()
test('returns a function which applies a set of transforms to its args',function()
- local minmax = _.over(math.min, math.max)
- local maxmin = _.over(math.max, math.min)
- assert_true(_.isEqual(minmax(5,10,12,4,3),{3,12}))
- assert_true(_.isEqual(maxmin(5,10,12,4,3),{12,3}))
+ local minmax = M.over(math.min, math.max)
+ local maxmin = M.over(math.max, math.min)
+ assert_true(M.isEqual(minmax(5,10,12,4,3),{3,12}))
+ assert_true(M.isEqual(maxmin(5,10,12,4,3),{12,3}))
end)
end)
@@ -383,7 +493,7 @@ context('Utility functions specs', function()
end)
test('checks if all predicates passes truth with args. ',function()
- local allok = _.overEvery(alleven, allpositive)
+ local allok = M.overEvery(alleven, allpositive)
assert_false(allok(2,4,-1,8))
assert_false(allok(10,3,2,6))
assert_true(allok(8,4,6,10))
@@ -408,7 +518,7 @@ context('Utility functions specs', function()
end)
test('checks if all predicates passes truth with args. ',function()
- local anyok = _.overSome(alleven, allpositive)
+ local anyok = M.overSome(alleven, allpositive)
assert_false(anyok(2,4,-1,8))
assert_true(anyok(10,3,2,6))
assert_false(anyok(-1,-5,-3))
@@ -422,27 +532,41 @@ context('Utility functions specs', function()
local function f(x, y) return {x, y} end
local function triple(x) return x*3 end
local function square(x) return x^2 end
- local new_f = _.overArgs(f, triple, square)
- assert_true(_.isEqual(new_f(1,2), {3,4}))
- assert_true(_.isEqual(new_f(10,10), {30,100}))
+ local new_f = M.overArgs(f, triple, square)
+ assert_true(M.isEqual(new_f(1,2), {3,4}))
+ assert_true(M.isEqual(new_f(10,10), {30,100}))
end)
test('when supplied more args than transforms, remaining are left as-is',function()
local function f(x, y, z, k) return {x, y, z, k} end
local function triple(x) return x*3 end
local function square(x) return x^2 end
- local new_f = _.overArgs(f, triple, square)
- assert_true(_.isEqual(new_f(1,2,3,4), {3,4,3,4}))
- assert_true(_.isEqual(new_f(10,10,10,10), {30,100,10,10}))
+ local new_f = M.overArgs(f, triple, square)
+ assert_true(M.isEqual(new_f(1,2,3,4), {3,4,3,4}))
+ assert_true(M.isEqual(new_f(10,10,10,10), {30,100,10,10}))
end)
end)
+ context('converge', function()
+
+ test('', function()
+ local function pow2(x) return x*x end
+ local function pow3(x) return x*x*x end
+ local function sum(a,b) return a+b end
+ local poly = M.converge(sum, pow2, pow3)
+ assert_equal(poly(5), 150)
+ assert_equal(poly(1), 2)
+ assert_equal(poly(3), 36)
+ end)
+
+ end)
+
context('partial', function()
test('applies partially f',function()
local function diff(a, b) return a - b end
- local diffFrom20 = _.partial(diff, 20)
+ local diffFrom20 = M.partial(diff, 20)
assert_equal(diffFrom20(5), 15)
assert_equal(diffFrom20(10), 10)
assert_equal(diffFrom20(-5), 25)
@@ -450,7 +574,7 @@ context('Utility functions specs', function()
test('\'_\' can be used as a placeholder',function()
local function diff(a, b) return a - b end
- local remove10 = _.partial(diff, '_',10)
+ local remove10 = M.partial(diff, '_',10)
assert_equal(remove10(5), -5)
assert_equal(remove10(10), 0)
assert_equal(remove10(15), 5)
@@ -462,16 +586,16 @@ context('Utility functions specs', function()
test('applies partial but from the right',function()
local function concat(a,b,c,d) return a..b..c..d end
- assert_equal(_.partialRight(concat,'a','b','c')('d'), 'dabc')
- assert_equal(_.partialRight(concat,'a','b')('c','d'), 'cdab')
- assert_equal(_.partialRight(concat,'a')('b','c','d'), 'bcda')
+ assert_equal(M.partialRight(concat,'a','b','c')('d'), 'dabc')
+ assert_equal(M.partialRight(concat,'a','b')('c','d'), 'cdab')
+ assert_equal(M.partialRight(concat,'a')('b','c','d'), 'bcda')
end)
test('\'_\' can be used as a placeholder',function()
local function concat(a,b,c,d) return a..b..c..d end
- assert_equal(_.partialRight(concat,'a','_','c')('d','b'), 'badc')
- assert_equal(_.partialRight(concat,'a','b','_')('c','d'), 'dabc')
- assert_equal(_.partialRight(concat,'_','a')('b','c','d'), 'cdba')
+ assert_equal(M.partialRight(concat,'a','_','c')('d','b'), 'badc')
+ assert_equal(M.partialRight(concat,'a','b','_')('c','d'), 'dabc')
+ assert_equal(M.partialRight(concat,'_','a')('b','c','d'), 'cdba')
end)
end)
@@ -480,20 +604,20 @@ context('Utility functions specs', function()
test('curries a function for a specific number of args',function()
local function sumOf5args(a,b,c,d,e) return a+b+c+d+e end
- local curried_sumOf5args = _.curry(sumOf5args, 5)
+ local curried_sumOf5args = M.curry(sumOf5args, 5)
assert_equal(curried_sumOf5args(1)(2)(3)(4)(5),15)
assert_equal(curried_sumOf5args(8)(-2)(4)(-10)(1),1)
end)
test('n_args defaults to 2 when not supplied',function()
local function prod(x,y) return x*y end
- local curried_prod = _.curry(prod)
- assert_equal(curried_prod(2)(3), (_.curry(prod,2))(2)(3))
- assert_equal(curried_prod(-2)(6), (_.curry(prod,2))(-2)(6))
+ local curried_prod = M.curry(prod)
+ assert_equal(curried_prod(2)(3), (M.curry(prod,2))(2)(3))
+ assert_equal(curried_prod(-2)(6), (M.curry(prod,2))(-2)(6))
end)
test('n_args can be equal to 1',function()
- local curried_identity = _.curry(_.identity,1)
+ local curried_identity = M.curry(M.identity,1)
assert_equal(curried_identity('value'), 'value')
assert_equal(curried_identity(1), 1)
assert_equal(curried_identity(true), true)
@@ -502,14 +626,14 @@ context('Utility functions specs', function()
test('giving more args than n_args will raise an error',function()
local function add(a,b) return a+b end
- local curried_add = _.curry(add, 2)
+ local curried_add = M.curry(add, 2)
assert_error(function() curried_add(1)(2)(3) end)
assert_error(function() curried_add(4)(5)(6)(7)(8) end)
end)
test('When given less than n_args, it will wait for missing args',function()
local function add(a,b,c) return a+b+c end
- local curried_add = _.curry(add, 3)
+ local curried_add = M.curry(add, 3)
local c1 = curried_add(1)
local c2 = c1(2)
local c3 = c2(3)
@@ -525,11 +649,11 @@ context('Utility functions specs', function()
test('returns the execution time of a function and its results', function()
local function f(...) return ... end
- local duration, r = _.time(f, 'a')
+ local duration, r = M.time(f, 'a')
assert_type(duration, 'number')
assert_equal(r, 'a')
- local duration, a, b, c = _.time(f, 1, 2, 3)
+ local duration, a, b, c = M.time(f, 1, 2, 3)
assert_type(duration, 'number')
assert_true(a == 1 and b == 2 and c == 3)
end)
diff --git a/spec/import_spec.lua b/spec/import_spec.lua
index c158510..1c11c7a 100644
--- a/spec/import_spec.lua
+++ b/spec/import_spec.lua
@@ -1,4 +1,4 @@
-require 'luacov'
+--require 'luacov'
local _ = require 'moses'
context('Import specs', function()
@@ -6,27 +6,15 @@ context('Import specs', function()
test('imports all library function to a given context', function()
local funcs = _.functions()
local context = _.import({})
- assert_true(_.all(funcs, function(k, n) return _.has(context, n) end))
+ assert_true(_.all(funcs, function(n) return _.has(context, n) end))
end)
test('passing "noConflict" will preserve already existing keys', function()
local funcs = _.functions()
local context = _.import({each = 1, all = 2}, true)
- assert_true(_.all(funcs, function(k, n) return _.has(context, n) end))
+ assert_true(_.all(funcs, function(n) return _.has(context, n) end))
assert_equal(context.each, 1)
assert_equal(context.all, 2)
end)
-
- test('The context will default to the global _G if not supplied', function()
- local oldG = _.clone(_G,true)
- assert_not_equal(_G, oldG)
- _.import()
- local funcs = _.functions()
- _.each(funcs, function(__, fname)
- assert_not_nil(_G[fname])
- assert_true(type(_G[fname]) == 'function')
- end)
- _G = oldG
- end)
end) \ No newline at end of file
diff --git a/spec/object_spec.lua b/spec/object_spec.lua
index 139083a..f9d2936 100644
--- a/spec/object_spec.lua
+++ b/spec/object_spec.lua
@@ -1,14 +1,14 @@
-require 'luacov'
-local _ = require 'moses'
+--require 'luacov'
+local M = require 'moses'
context('Object functions specs', function()
context('keys', function()
test('collects a given object attributes',function()
- assert_true(_.isEqual(_.keys({1,2,3}),{1,2,3}))
- assert_true(_.isEqual(_.keys({4,5,6}),{1,2,3}))
- assert_true(_.same(_.keys({x = 1, y = 2, 3}),{'x','y',1}))
+ assert_true(M.isEqual(M.keys({1,2,3}),{1,2,3}))
+ assert_true(M.isEqual(M.keys({4,5,6}),{1,2,3}))
+ assert_true(M.same(M.keys({x = 1, y = 2, 3}),{'x','y',1}))
end)
end)
@@ -16,21 +16,41 @@ context('Object functions specs', function()
context('values', function()
test('collects an given object values',function()
- assert_true(_.isEqual(_.values({1,2,3}),{1,2,3}))
- assert_true(_.isEqual(_.values({4,5,6}),{4,5,6}))
- assert_true(_.same(_.values({x = 1, y = 2, 3}),{1,2,3}))
+ assert_true(M.isEqual(M.values({1,2,3}),{1,2,3}))
+ assert_true(M.isEqual(M.values({4,5,6}),{4,5,6}))
+ assert_true(M.same(M.values({x = 1, y = 2, 3}),{1,2,3}))
end)
- end)
+ end)
+
+ context('path', function()
+
+ test('return the value at a given path in object',function()
+ local entity = {
+ pos = {x = 1},
+ engine = {
+ left = {status = 'active'},
+ right = {damage = 10}
+ },
+ boost = false
+ }
+ assert_equal(M.path(entity, 'pos','x'), 1)
+ assert_equal(M.path(entity, 'engine','left','status'), 'active')
+ assert_equal(M.path(entity, 'engine','right','damage'), 10)
+ assert_equal(M.path(entity, 'boost'), false)
+ assert_nil(M.path(entity, 'x'))
+ end)
+
+ end)
context('kvpairs', function()
test('converts key-values pairs in object to array-list of k,v pairs',function()
- local obj = _.kvpairs({x = 1, y = 2, z = 3})
+ local obj = M.kvpairs({x = 1, y = 2, z = 3})
table.sort(obj, function(a,b) return a[1] < b[1] end)
- assert_true(_.isEqual(obj[1],{'x',1}))
- assert_true(_.isEqual(obj[2],{'y',2}))
- assert_true(_.isEqual(obj[3],{'z',3}))
+ assert_true(M.isEqual(obj[1],{'x',1}))
+ assert_true(M.isEqual(obj[2],{'y',2}))
+ assert_true(M.isEqual(obj[3],{'z',3}))
end)
end)
@@ -38,7 +58,7 @@ context('Object functions specs', function()
context('toObj', function()
test('converts an array-list of {k,v} pairs to an object',function()
- local obj = _.toObj({{'x',1},{'y',2},{'z',3}})
+ local obj = M.toObj({{'x',1},{'y',2},{'z',3}})
assert_equal(obj.x,1)
assert_equal(obj.y,2)
assert_equal(obj.z,3)
@@ -49,10 +69,10 @@ context('Object functions specs', function()
context('property', function()
test('Returns a function that will return the key property of any passed-in object.',function()
- assert_equal(_.property('sin')(math), math.sin)
- assert_equal(_.property('find')(string), string.find)
- assert_equal(_.property('insert')(table), table.insert)
- assert_equal(_.property('yield')(coroutine), coroutine.yield)
+ assert_equal(M.property('sin')(math), math.sin)
+ assert_equal(M.property('find')(string), string.find)
+ assert_equal(M.property('insert')(table), table.insert)
+ assert_equal(M.property('yield')(coroutine), coroutine.yield)
end)
end)
@@ -60,10 +80,10 @@ context('Object functions specs', function()
context('propertyOf', function()
test('Returns a function which will return the value of an object property.',function()
- assert_equal(_.propertyOf(math)('cos'), math.cos)
- assert_equal(_.propertyOf(string)('char'), string.char)
- assert_equal(_.propertyOf(table)('remove'), table.remove)
- assert_equal(_.propertyOf(_)('propertyOf'), _.propertyOf)
+ assert_equal(M.propertyOf(math)('cos'), math.cos)
+ assert_equal(M.propertyOf(string)('char'), string.char)
+ assert_equal(M.propertyOf(table)('remove'), table.remove)
+ assert_equal(M.propertyOf(M)('propertyOf'), M.propertyOf)
end)
end)
@@ -72,19 +92,19 @@ context('Object functions specs', function()
context('toBoolean', function()
test('converts a value to a boolean',function()
- assert_true(type(_.toBoolean(true)) == 'boolean')
- assert_true(type(_.toBoolean(1)) == 'boolean')
- assert_true(type(_.toBoolean(false)) == 'boolean')
- assert_true(type(_.toBoolean(nil)) == 'boolean')
- assert_true(type(_.toBoolean({})) == 'boolean')
- assert_true(type(_.toBoolean(1/0)) == 'boolean')
+ assert_true(type(M.toBoolean(true)) == 'boolean')
+ assert_true(type(M.toBoolean(1)) == 'boolean')
+ assert_true(type(M.toBoolean(false)) == 'boolean')
+ assert_true(type(M.toBoolean(nil)) == 'boolean')
+ assert_true(type(M.toBoolean({})) == 'boolean')
+ assert_true(type(M.toBoolean(1/0)) == 'boolean')
- assert_true(_.toBoolean(true))
- assert_true(_.toBoolean(1))
- assert_false(_.toBoolean(false))
- assert_false(_.toBoolean(nil))
- assert_true(_.toBoolean({}))
- assert_true(_.toBoolean(1/0))
+ assert_true(M.toBoolean(true))
+ assert_true(M.toBoolean(1))
+ assert_false(M.toBoolean(false))
+ assert_false(M.toBoolean(nil))
+ assert_true(M.toBoolean({}))
+ assert_true(M.toBoolean(1/0))
end)
end)
@@ -92,32 +112,32 @@ context('Object functions specs', function()
context('extend', function()
test('extends a destination objects with key-values a source object',function()
- assert_true(_.isEqual(_.extend({},{a = 'b'}),{a = 'b'}))
+ assert_true(M.isEqual(M.extend({},{a = 'b'}),{a = 'b'}))
end)
test('source properties overrides destination properties',function()
- assert_true(_.isEqual(_.extend({a = 'a'},{a = 'b'}),{a = 'b'}))
+ assert_true(M.isEqual(M.extend({a = 'a'},{a = 'b'}),{a = 'b'}))
end)
test('leaves source object untouched',function()
local source = {i = 'i'}
- assert_true(_.isEqual(_.extend({a = 'a'},source),{a = 'a',i = 'i'}))
- assert_true(_.isEqual(source,{i = 'i'}))
+ assert_true(M.isEqual(M.extend({a = 'a'},source),{a = 'a',i = 'i'}))
+ assert_true(M.isEqual(source,{i = 'i'}))
end)
test('can extend destination from multiple sources',function()
local sourceA = {a = 'a'}; local sourceBC = {b = 'b', c = 'c'}
- assert_true(_.isEqual(_.extend({},sourceA, sourceBC),{a = 'a', b = 'b', c = 'c'}))
+ assert_true(M.isEqual(M.extend({},sourceA, sourceBC),{a = 'a', b = 'b', c = 'c'}))
end)
test('extending from multiple source, latter properties overrides',function()
local sourceA = {a = 'a'}; local sourceBC = {b = 'b', a = 'c'}
- assert_true(_.isEqual(_.extend({},sourceA, sourceBC),{a = 'c', b = 'b'}))
+ assert_true(M.isEqual(M.extend({},sourceA, sourceBC),{a = 'c', b = 'b'}))
end)
test('will not copy nil values',function()
local sourceA = {a = nil}; local sourceBC = {b = 'b', c = nil}
- assert_true(_.isEqual(_.extend({},sourceA, sourceBC),{b = 'b'}))
+ assert_true(M.isEqual(M.extend({},sourceA, sourceBC),{b = 'b'}))
end)
end)
@@ -126,7 +146,7 @@ context('Object functions specs', function()
test('collects function names within an object',function()
local x = {}
function x.a() return end; function x.b() return end
- assert_true(_.isEqual(_.functions(x),{'a','b'}))
+ assert_true(M.isEqual(M.functions(x),{'a','b'}))
end)
test('collects metatable functions if "recurseMt" arg is supplied',function()
@@ -134,14 +154,14 @@ context('Object functions specs', function()
function x.a() return end; function x.b() return end
local xx = setmetatable({},x)
function xx.c() return end
- assert_true(_.same(_.functions(xx),{'c'}))
- assert_true(_.same(_.functions(xx,true),{'a','b','c'}))
+ assert_true(M.same(M.functions(xx),{'c'}))
+ assert_true(M.same(M.functions(xx,true),{'a','b','c'}))
end)
test('when given no obj as argument, returns all library functions',function()
- local functions = _.functions()
- _.each(functions, function(k,v)
- assert_true(_.isFunction(_[v]))
+ local functions = M.functions()
+ M.each(functions, function(v)
+ assert_true(M.isFunction(M[v]))
end)
end)
@@ -151,32 +171,32 @@ context('Object functions specs', function()
test('clones the attributes of an object',function()
local vector = {x = 0, y = 0}
- assert_true(_.isEqual(_.clone(vector),vector))
+ assert_true(M.isEqual(M.clone(vector),vector))
end)
test('By default, cloning is deep (clones nested tables)',function()
local particle = {position = {x = 0,y=0},mass = 1}
- local particle_clone = _.clone (particle)
- assert_true(_.isEqual(particle_clone,particle))
+ local particle_clone = M.clone (particle)
+ assert_true(M.isEqual(particle_clone,particle))
particle_clone.position.x = 3
- assert_false(_.isEqual(particle_clone,particle))
+ assert_false(M.isEqual(particle_clone,particle))
end)
test('Unless "shallow" arg is provided',function()
local particle = {position = {x = 0,y=0},mass = 1}
- local particle_clone = _.clone (particle,true)
- assert_true(_.isEqual(particle_clone,particle))
+ local particle_clone = M.clone (particle,true)
+ assert_true(M.isEqual(particle_clone,particle))
particle_clone.position.x = 3
- assert_true(_.isEqual(particle_clone,particle))
+ assert_true(M.isEqual(particle_clone,particle))
end)
test('Non objects are simply returned',function()
- assert_equal(_.clone(1),1)
- assert_equal(_.clone(false),false)
- assert_equal(_.clone(true),true)
- assert_equal(_.clone(nil),nil)
- assert_equal(_.clone('hello'),'hello')
- assert_equal(_.clone(print),print)
+ assert_equal(M.clone(1),1)
+ assert_equal(M.clone(false),false)
+ assert_equal(M.clone(true),true)
+ assert_equal(M.clone(nil),nil)
+ assert_equal(M.clone('hello'),'hello')
+ assert_equal(M.clone(print),print)
end)
end)
@@ -185,13 +205,13 @@ context('Object functions specs', function()
test('tap-into a method chain', function()
local t = {}
- local catchMax = function(k) t[#t+1] = _.max(k) end
- local catchMin = function(k) t[#t+1] = _.min(k) end
+ local catchMax = function(k) t[#t+1] = M.max(k) end
+ local catchMin = function(k) t[#t+1] = M.min(k) end
- _.chain({1,2,3})
- :map(function(i,j) return j*2 end)
+ M.chain({1,2,3})
+ :map(function(j) return j*2 end)
:tap(catchMax)
- :map(function(i,k) return k^2 end)
+ :map(function(k) return k^2 end)
:tap(catchMin)
:value()
@@ -204,11 +224,11 @@ context('Object functions specs', function()
context('has', function()
test('checks if an object has an attribute',function()
- assert_true(_.has(_,'has'))
- assert_true(_.has(table,'concat'))
- assert_true(_.has(string,'format'))
- assert_true(_.has(os,'time'))
- assert_true(_.has(math,'random'))
+ assert_true(M.has(M,'has'))
+ assert_true(M.has(table,'concat'))
+ assert_true(M.has(string,'format'))
+ assert_true(M.has(os,'time'))
+ assert_true(M.has(math,'random'))
end)
end)
@@ -217,27 +237,27 @@ context('Object functions specs', function()
test('collect specified properties',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.pick(object,'a','c'),{a = 1, c = 3}))
+ assert_true(M.isEqual(M.pick(object,'a','c'),{a = 1, c = 3}))
end)
test('given args can be nested as well',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.pick(object,{{'b','a'}},'c'),{a = 1,b = 2, c = 3}))
+ assert_true(M.isEqual(M.pick(object,{{'b','a'}},'c'),{a = 1,b = 2, c = 3}))
end)
test('will ignore properties the object do not have',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.pick(object,{{'k'}},'c'),{c = 3}))
+ assert_true(M.isEqual(M.pick(object,{{'k'}},'c'),{c = 3}))
end)
test('returns an empty table when given no properties to pick',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.pick(object),{}))
+ assert_true(M.isEqual(M.pick(object),{}))
end)
test('should also pick attributes having falsy values',function()
local object = {a = false, b = false, c = true}
- assert_true(_.isEqual(_.pick(object,'a','b'),{a = false,b = false}))
+ assert_true(M.isEqual(M.pick(object,'a','b'),{a = false,b = false}))
end)
end)
@@ -246,22 +266,22 @@ context('Object functions specs', function()
test('collect all properties leaving those given as args',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.omit(object,'a','c'),{b=2}))
+ assert_true(M.isEqual(M.omit(object,'a','c'),{b=2}))
end)
test('given args can be nested as well',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.omit(object,{{'b'}},'c'),{a = 1}))
+ assert_true(M.isEqual(M.omit(object,{{'b'}},'c'),{a = 1}))
end)
test('will ignore properties the object do not have',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.omit(object,{{'k'}},'c'),{a = 1, b=2}))
+ assert_true(M.isEqual(M.omit(object,{{'k'}},'c'),{a = 1, b=2}))
end)
test('returns the original object clone when given no properties to omit',function()
local object = {a = 1, b = 2, c = 3}
- assert_true(_.isEqual(_.omit(object),{a = 1, b = 2, c = 3}))
+ assert_true(M.isEqual(M.omit(object),{a = 1, b = 2, c = 3}))
end)
end)
@@ -269,15 +289,15 @@ context('Object functions specs', function()
context('template', function()
test('applies a template on an object',function()
- assert_true(_.isEqual(_.template({},{a = 1, b = 2, c = 3}),{a = 1, b = 2, c = 3}))
+ assert_true(M.isEqual(M.template({},{a = 1, b = 2, c = 3}),{a = 1, b = 2, c = 3}))
end)
test('does not override existing properies',function()
- assert_true(_.isEqual(_.template({a = 10, b = 10},{a = 1, b = 2, c = 3}),{a = 10, b = 10, c = 3}))
+ assert_true(M.isEqual(M.template({a = 10, b = 10},{a = 1, b = 2, c = 3}),{a = 10, b = 10, c = 3}))
end)
test('returns the object when given no template arg',function()
- assert_true(_.isEqual(_.template({a = 10, b = 10}),{a = 10, b = 10}))
+ assert_true(M.isEqual(M.template({a = 10, b = 10}),{a = 10, b = 10}))
end)
end)
@@ -285,39 +305,39 @@ context('Object functions specs', function()
context('isEqual', function()
test('compares values',function()
- assert_true(_.isEqual(1,1))
- assert_true(_.isEqual(1.0,1))
- assert_false(_.isEqual(1,2))
- assert_false(_.isEqual(2,2.0001))
+ assert_true(M.isEqual(1,1))
+ assert_true(M.isEqual(1.0,1))
+ assert_false(M.isEqual(1,2))
+ assert_false(M.isEqual(2,2.0001))
end)
test('compares objects by reference and components',function()
local oldprint = print
- assert_true(_.isEqual(print,oldprint))
+ assert_true(M.isEqual(print,oldprint))
local t = {}
local v = t
- assert_true(_.isEqual(t,v))
- assert_true(_.isEqual({},{}))
+ assert_true(M.isEqual(t,v))
+ assert_true(M.isEqual({},{}))
- assert_false(_.isEqual('a','b'))
+ assert_false(M.isEqual('a','b'))
- assert_false(_.isEqual(true, false))
- assert_false(_.isEqual(nil, false))
- assert_false(_.isEqual(true, nil))
+ assert_false(M.isEqual(true, false))
+ assert_false(M.isEqual(nil, false))
+ assert_false(M.isEqual(true, nil))
end)
test('compares nested properties',function()
- assert_true(_.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =0}}}))
- assert_false(_.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =1}}}))
+ assert_true(M.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =0}}}))
+ assert_false(M.isEqual({x = 0,{x1 = 0,{x2 =0}}}, {x = 0,{x1 = 0,{x2 =1}}}))
end)
test('can compare tables on the basis of their metatable',function()
local a, b = {x = 1, y = 2}, {x = 2, y = 1}
setmetatable(a,{__eq = function(a,b) return (a.x and b.x and a.y and b.y)~=nil end})
- assert_false(_.isEqual(a, b))
- assert_true(_.isEqual(a, b, true))
+ assert_false(M.isEqual(a, b))
+ assert_true(M.isEqual(a, b, true))
end)
@@ -326,18 +346,18 @@ context('Object functions specs', function()
context('result', function()
test('calls an object method, passing it as a first arg the object itself',function()
- assert_equal(_.result('a','len'),1)
- assert_equal(_.result('hello','reverse'),'olleh')
- assert_equal(_.result({'a','b','c'},table.concat),'abc')
+ assert_equal(M.result('a','len'),1)
+ assert_equal(M.result('hello','reverse'),'olleh')
+ assert_equal(M.result({'a','b','c'},table.concat),'abc')
end)
test('handles extra-args to be passed to the so-called method',function()
- assert_equal(_.result('Hello','match','%u'),'H')
- assert_equal(_.result({'a','b','c'},table.concat,' '),'a b c')
+ assert_equal(M.result('Hello','match','%u'),'H')
+ assert_equal(M.result({'a','b','c'},table.concat,' '),'a b c')
end)
test('returns the property itself if not callable',function()
- assert_equal(_.result({size = 0},'size'),0)
+ assert_equal(M.result({size = 0},'size'),0)
end)
end)
@@ -345,23 +365,23 @@ context('Object functions specs', function()
context('isTable', function()
test('returns "true" if arg is table or array',function()
- assert_true(_.isTable({}))
- assert_true(_.isTable({1,2}))
- assert_true(_.isTable({x = 1, 2}))
- assert_true(_.isTable(string))
- assert_true(_.isTable(table))
- assert_true(_.isTable(math))
+ assert_true(M.isTable({}))
+ assert_true(M.isTable({1,2}))
+ assert_true(M.isTable({x = 1, 2}))
+ assert_true(M.isTable(string))
+ assert_true(M.isTable(table))
+ assert_true(M.isTable(math))
end)
test('returns "false" otherwise',function()
- assert_false(_.isTable(1))
- assert_false(_.isTable(''))
- assert_false(_.isTable(function() end))
- assert_false(_.isTable(print))
- assert_false(_.isTable(false))
- assert_false(_.isTable(nil))
- assert_false(_.isTable(true))
+ assert_false(M.isTable(1))
+ assert_false(M.isTable(''))
+ assert_false(M.isTable(function() end))
+ assert_false(M.isTable(print))
+ assert_false(M.isTable(false))
+ assert_false(M.isTable(nil))
+ assert_false(M.isTable(true))
end)
end)
@@ -369,20 +389,20 @@ context('Object functions specs', function()
context('isCallable', function()
test('returns "true" if arg is callable',function()
- assert_true(_.isCallable(print))
- assert_true(_.isCallable(function() end))
- assert_true(_.isCallable(string.gmatch))
- assert_true(_.isCallable(setmetatable({},{__index = string}).upper))
- assert_true(_.isCallable(setmetatable({},{__call = function() return end})))
+ assert_true(M.isCallable(print))
+ assert_true(M.isCallable(function() end))
+ assert_true(M.isCallable(string.gmatch))
+ assert_true(M.isCallable(setmetatable({},{__index = string}).upper))
+ assert_true(M.isCallable(setmetatable({},{__call = function() return end})))
end)
test('returns "false" otherwise',function()
- assert_false(_.isCallable(1))
- assert_false(_.isCallable(''))
- assert_false(_.isCallable({}))
- assert_false(_.isCallable(false))
- assert_false(_.isCallable(nil))
- assert_false(_.isCallable(true))
+ assert_false(M.isCallable(1))
+ assert_false(M.isCallable(''))
+ assert_false(M.isCallable({}))
+ assert_false(M.isCallable(false))
+ assert_false(M.isCallable(nil))
+ assert_false(M.isCallable(true))
end)
end)
@@ -390,29 +410,29 @@ context('Object functions specs', function()
context('isArray', function()
test('returns "true" if arg is an array',function()
- assert_true(_.isArray({}))
- assert_true(_.isArray({1,2,3}))
- assert_true(_.isArray({'a','b','c',{}}))
- assert_true(_.isArray({false,true}))
- assert_true(_.isArray({1,nil}))
+ assert_true(M.isArray({}))
+ assert_true(M.isArray({1,2,3}))
+ assert_true(M.isArray({'a','b','c',{}}))
+ assert_true(M.isArray({false,true}))
+ assert_true(M.isArray({1,nil}))
end)
test('returns "false" otherwise',function()
- assert_false(_.isArray(1))
- assert_false(_.isArray(''))
- assert_false(_.isArray(false))
- assert_false(_.isArray(nil))
- assert_false(_.isArray(true))
- assert_false(_.isArray(print))
- assert_false(_.isArray({a = 1, x = 1}))
- assert_false(_.isArray({a = 1, 1, 2,3}))
- assert_false(_.isArray({1,nil,2}))
- assert_false(_.isArray({1,nil,3,k=4}))
- assert_false(_.isArray({a=1}))
+ assert_false(M.isArray(1))
+ assert_false(M.isArray(''))
+ assert_false(M.isArray(false))
+ assert_false(M.isArray(nil))
+ assert_false(M.isArray(true))
+ assert_false(M.isArray(print))
+ assert_false(M.isArray({a = 1, x = 1}))
+ assert_false(M.isArray({a = 1, 1, 2,3}))
+ assert_false(M.isArray({1,nil,2}))
+ assert_false(M.isArray({1,nil,3,k=4}))
+ assert_false(M.isArray({a=1}))
end)
test('returns false on "sparse arrays"',function()
- assert_false(_.isArray({[1] = true, [10] = false}))
+ assert_false(M.isArray({[1] = true, [10] = false}))
end)
end)
@@ -420,10 +440,10 @@ context('Object functions specs', function()
context('isIterable', function()
test('checks if the given object is iterable with pairs',function()
- assert_true(_.isIterable({}))
- assert_false(_.isIterable(function() end))
- assert_false(_.isIterable(false))
- assert_false(_.isIterable(1))
+ assert_true(M.isIterable({}))
+ assert_false(M.isIterable(function() end))
+ assert_false(M.isIterable(false))
+ assert_false(M.isIterable(1))
end)
end)
@@ -431,27 +451,27 @@ context('Object functions specs', function()
context('isEmpty', function()
test('returns "true" if arg is an empty array',function()
- assert_true(_.isEmpty({}))
+ assert_true(M.isEmpty({}))
end)
test('returns "false" otherwise',function()
- assert_false(_.isEmpty({1,2,3}))
- assert_false(_.isEmpty({'a','b','c',{}}))
- assert_false(_.isEmpty({nil,false,true}))
+ assert_false(M.isEmpty({1,2,3}))
+ assert_false(M.isEmpty({'a','b','c',{}}))
+ assert_false(M.isEmpty({nil,false,true}))
end)
test('booleans, nil and functions are considered empty',function()
- assert_true(_.isEmpty(print))
- assert_true(_.isEmpty(nil))
- assert_true(_.isEmpty(false))
- assert_true(_.isEmpty(true))
+ assert_true(M.isEmpty(print))
+ assert_true(M.isEmpty(nil))
+ assert_true(M.isEmpty(false))
+ assert_true(M.isEmpty(true))
end)
test('handles strings',function()
- assert_true(_.isEmpty(''))
- assert_false(_.isEmpty('a'))
- assert_false(_.isEmpty('bcd'))
- assert_false(_.isEmpty(' '))
+ assert_true(M.isEmpty(''))
+ assert_false(M.isEmpty('a'))
+ assert_false(M.isEmpty('bcd'))
+ assert_false(M.isEmpty(' '))
end)
end)
@@ -459,18 +479,18 @@ context('Object functions specs', function()
context('isString', function()
test('returns "true" if arg is a string',function()
- assert_true(_.isString(''))
- assert_true(_.isString('a'))
- assert_true(_.isString(' '))
- assert_true(_.isString(type(nil)))
+ assert_true(M.isString(''))
+ assert_true(M.isString('a'))
+ assert_true(M.isString(' '))
+ assert_true(M.isString(type(nil)))
end)
test('returns "false" otherwise',function()
- assert_false(_.isString(false))
- assert_false(_.isString(print))
- assert_false(_.isString(nil))
- assert_false(_.isString(true))
- assert_false(_.isString({}))
+ assert_false(M.isString(false))
+ assert_false(M.isString(print))
+ assert_false(M.isString(nil))
+ assert_false(M.isString(true))
+ assert_false(M.isString({}))
end)
end)
@@ -478,17 +498,17 @@ context('Object functions specs', function()
context('isFunction', function()
test('returns "true" if arg is a function',function()
- assert_true(_.isFunction(print))
- assert_true(_.isFunction(string.match))
- assert_true(_.isFunction(function() end))
+ assert_true(M.isFunction(print))
+ assert_true(M.isFunction(string.match))
+ assert_true(M.isFunction(function() end))
end)
test('returns "false" otherwise',function()
- assert_false(_.isFunction({}))
- assert_false(_.isFunction(nil))
- assert_false(_.isFunction(false))
- assert_false(_.isFunction(true))
- assert_false(_.isFunction('a'))
+ assert_false(M.isFunction({}))
+ assert_false(M.isFunction(nil))
+ assert_false(M.isFunction(false))
+ assert_false(M.isFunction(true))
+ assert_false(M.isFunction('a'))
end)
end)
@@ -496,17 +516,17 @@ context('Object functions specs', function()
context('isNil', function()
test('returns "true" if arg is nil',function()
- assert_true(_.isNil(nil))
- assert_true(_.isNil())
- assert_true(_.isNil(a))
+ assert_true(M.isNil(nil))
+ assert_true(M.isNil())
+ assert_true(M.isNil(a))
end)
test('returns "false" otherwise',function()
- assert_false(_.isNil(false))
- assert_false(_.isNil(true))
- assert_false(_.isNil(table))
- assert_false(_.isNil(function() end))
- assert_false(_.isNil('a'))
+ assert_false(M.isNil(false))
+ assert_false(M.isNil(true))
+ assert_false(M.isNil(table))
+ assert_false(M.isNil(function() end))
+ assert_false(M.isNil('a'))
end)
end)
@@ -514,21 +534,21 @@ context('Object functions specs', function()
context('isNumber', function()
test('returns "true" if arg is a number',function()
- assert_true(_.isNumber(1))
- assert_true(_.isNumber(0.5))
- assert_true(_.isNumber(math.pi))
- assert_true(_.isNumber(1/0))
- assert_true(_.isNumber(math.huge))
- assert_true(_.isNumber(0/0))
+ assert_true(M.isNumber(1))
+ assert_true(M.isNumber(0.5))
+ assert_true(M.isNumber(math.pi))
+ assert_true(M.isNumber(1/0))
+ assert_true(M.isNumber(math.huge))
+ assert_true(M.isNumber(0/0))
end)
test('returns "false" otherwise',function()
- assert_false(_.isNumber(print))
- assert_false(_.isNumber(nil))
- assert_false(_.isNumber(true))
- assert_false(_.isNumber(false))
- assert_false(_.isNumber({1}))
- assert_false(_.isNumber('1'))
+ assert_false(M.isNumber(print))
+ assert_false(M.isNumber(nil))
+ assert_false(M.isNumber(true))
+ assert_false(M.isNumber(false))
+ assert_false(M.isNumber({1}))
+ assert_false(M.isNumber('1'))
end)
end)
@@ -536,20 +556,20 @@ context('Object functions specs', function()
context('isNaN', function()
test('returns "true" if arg is NaN',function()
- assert_true(_.isNaN(0/0))
+ assert_true(M.isNaN(0/0))
end)
test('returns "false" for not NaN values',function()
- assert_false(_.isNaN(1/0))
- assert_false(_.isNaN(math.huge))
- assert_false(_.isNaN(math.pi))
- assert_false(_.isNaN(1))
- assert_false(_.isNaN(''))
- assert_false(_.isNaN('0'))
- assert_false(_.isNaN({}))
- assert_false(_.isNaN(nil))
- assert_false(_.isNaN(false))
- assert_false(_.isNaN(true))
+ assert_false(M.isNaN(1/0))
+ assert_false(M.isNaN(math.huge))
+ assert_false(M.isNaN(math.pi))
+ assert_false(M.isNaN(1))
+ assert_false(M.isNaN(''))
+ assert_false(M.isNaN('0'))
+ assert_false(M.isNaN({}))
+ assert_false(M.isNaN(nil))
+ assert_false(M.isNaN(false))
+ assert_false(M.isNaN(true))
end)
end)
@@ -557,22 +577,22 @@ context('Object functions specs', function()
context('isFinite', function()
test('returns "true" if arg is a finite number',function()
- assert_true(_.isFinite(1))
- assert_true(_.isFinite(0))
- assert_true(_.isFinite(math.pi))
- assert_true(_.isFinite(99e99))
+ assert_true(M.isFinite(1))
+ assert_true(M.isFinite(0))
+ assert_true(M.isFinite(math.pi))
+ assert_true(M.isFinite(99e99))
end)
test('returns "false" otherwise',function()
- assert_false(_.isFinite(math.huge))
- assert_false(_.isFinite(1/0))
- assert_false(_.isFinite(0/0))
+ assert_false(M.isFinite(math.huge))
+ assert_false(M.isFinite(1/0))
+ assert_false(M.isFinite(0/0))
end)
test('returns "false" for non-numbers',function()
- assert_false(_.isFinite(''))
- assert_false(_.isFinite(function() end))
- assert_false(_.isFinite({}))
+ assert_false(M.isFinite(''))
+ assert_false(M.isFinite(function() end))
+ assert_false(M.isFinite({}))
end)
end)
@@ -580,20 +600,20 @@ context('Object functions specs', function()
context('isBoolean', function()
test('returns "true" if arg is a boolean or a thruthy statement',function()
- assert_true(_.isBoolean(true))
- assert_true(_.isBoolean(false))
- assert_true(_.isBoolean(1==1))
- assert_true(_.isBoolean(print==tostring))
+ assert_true(M.isBoolean(true))
+ assert_true(M.isBoolean(false))
+ assert_true(M.isBoolean(1==1))
+ assert_true(M.isBoolean(print==tostring))
end)
test('returns "false" otherwise',function()
- assert_false(_.isBoolean(''))
- assert_false(_.isBoolean(nil))
- assert_false(_.isBoolean({}))
- assert_false(_.isBoolean(function() end))
+ assert_false(M.isBoolean(''))
+ assert_false(M.isBoolean(nil))
+ assert_false(M.isBoolean({}))
+ assert_false(M.isBoolean(function() end))
- assert_false(_.isBoolean(0))
- assert_false(_.isBoolean('1'))
+ assert_false(M.isBoolean(0))
+ assert_false(M.isBoolean('1'))
end)
end)
@@ -601,12 +621,12 @@ context('Object functions specs', function()
context('isInteger', function()
test('returns "true" if arg is a integer, "false" otherwise',function()
- assert_true(_.isInteger(1))
- assert_true(_.isInteger(0))
- assert_false(_.isInteger(math.pi))
- assert_true(_.isInteger(1/0))
- assert_true(_.isInteger(math.huge))
- assert_false(_.isInteger(0/0))
+ assert_true(M.isInteger(1))
+ assert_true(M.isInteger(0))
+ assert_false(M.isInteger(math.pi))
+ assert_true(M.isInteger(1/0))
+ assert_true(M.isInteger(math.huge))
+ assert_false(M.isInteger(0/0))
end)
end)
diff --git a/spec/op_spec.lua b/spec/op_spec.lua
new file mode 100644
index 0000000..f603a6b
--- /dev/null
+++ b/spec/op_spec.lua
@@ -0,0 +1,162 @@
+--require 'luacov'
+local M = require 'moses'
+
+context('Operators specs', function()
+
+ context('Arithmetic operators', function()
+
+ test('add returns a + b', function()
+ assert_equal(M.operator.add(1,2), 3)
+ assert_equal(M.operator.add(0,0), 0)
+ assert_equal(M.operator.add(0,-5), -5)
+ end)
+
+ test('sub returns a - b', function()
+ assert_equal(M.operator.sub(1,2), -1)
+ assert_equal(M.operator.sub(0,0), 0)
+ assert_equal(M.operator.sub(0,-5), 5)
+ end)
+
+ test('mul returns a * b', function()
+ assert_equal(M.operator.mul(1,2), 2)
+ assert_equal(M.operator.mul(0,0), 0)
+ assert_equal(M.operator.mul(0,-5), 0)
+ end)
+
+ test('div returns a / b', function()
+ assert_equal(M.operator.div(1,2), 0.5)
+ assert_equal(M.operator.div(5,5), 1)
+ assert_equal(M.operator.div(8,-2), -4)
+ end)
+
+ test('mod returns a % b', function()
+ assert_equal(M.operator.mod(6,3), 0)
+ assert_equal(M.operator.mod(5,2), 1)
+ end)
+
+ test('exp returns a ^ b', function()
+ assert_equal(M.operator.exp(3,3), 27)
+ assert_equal(M.operator.exp(5,2), 25)
+ end)
+
+ test('unm returns -a', function()
+ assert_equal(M.operator.unm(3), -3)
+ assert_equal(M.operator.unm(-5), 5)
+ end)
+
+ test('floordiv returns a//b', function()
+ assert_equal(M.operator.floordiv(5,2), 2)
+ end)
+
+ test('intdiv performs integer division', function()
+ assert_equal(M.operator.intdiv(5,2), 2)
+ assert_equal(M.operator.intdiv(-5,2), -2)
+ end)
+
+ end)
+
+ context('Relational operators', function()
+
+ test('eq returns a == b', function()
+ assert_equal(M.operator.eq(5,5), true)
+ assert_equal(M.operator.eq(5,4.99), false)
+ end)
+
+ test('neq returns a ~= b', function()
+ assert_equal(M.operator.neq(5,5), false)
+ assert_equal(M.operator.neq(5,4.99), true)
+ end)
+
+ test('lt returns a < b', function()
+ assert_equal(M.operator.lt(5,5), false)
+ assert_equal(M.operator.lt(4.99,5), true)
+ end)
+
+ test('gt returns a > b', function()
+ assert_equal(M.operator.gt(5,5), false)
+ assert_equal(M.operator.gt(5,4.99), true)
+ end)
+
+ test('le returns a <= b', function()
+ assert_equal(M.operator.le(5,5), true)
+ assert_equal(M.operator.le(4.99,5), true)
+ assert_equal(M.operator.le(5,4.99), false)
+ end)
+
+ test('ge returns a >= b', function()
+ assert_equal(M.operator.ge(5,5), true)
+ assert_equal(M.operator.ge(4.99,5), false)
+ assert_equal(M.operator.ge(5,4.99), true)
+ end)
+
+ end)
+
+ context('Logical operators', function()
+
+ test('land returns a and b', function()
+ assert_equal(M.operator.land(true, true),true)
+ assert_equal(M.operator.land(true, false),false)
+ assert_equal(M.operator.land(false, true),false)
+ assert_equal(M.operator.land(false, false),false)
+ assert_equal(M.operator.land(true, nil),nil)
+ assert_equal(M.operator.land(false, nil),false)
+ end)
+
+ test('lor returns a or b', function()
+ assert_equal(M.operator.lor(true, true),true)
+ assert_equal(M.operator.lor(true, false),true)
+ assert_equal(M.operator.lor(false, true),true)
+ assert_equal(M.operator.lor(false, false),false)
+ assert_equal(M.operator.lor(true, nil),true)
+ assert_equal(M.operator.lor(false, nil),nil)
+ end)
+
+ test('lnot returns not a', function()
+ assert_equal(M.operator.lnot(true),false)
+ assert_equal(M.operator.lnot(false),true)
+ assert_equal(M.operator.lnot(nil),true)
+ end)
+
+ end)
+
+ context('Length operator', function()
+
+ test('length returns #a', function()
+ assert_equal(M.operator.length({}),0)
+ assert_equal(M.operator.length({2}),1)
+ assert_equal(M.operator.length({3,5,3}),3)
+ assert_equal(M.operator.length('hello'),5)
+ end)
+
+ end)
+
+ context('Concatenation operator', function()
+
+ test('concat returns a..b', function()
+ assert_equal(M.operator.concat('a','b'),'ab')
+ assert_equal(M.operator.concat('1','2'),'12')
+ end)
+
+ end)
+
+ context('Aliases', function()
+
+ test('op is an alias to operator', function()
+ assert_equal(M.operator, M.op)
+ end)
+
+ test('pow is an alias to exp', function()
+ assert_equal(M.operator.exp, M.operator.pow)
+ end)
+
+ test('neg is an alias to unm', function()
+ assert_equal(M.operator.neg, M.operator.unm)
+ end)
+
+ test('len is alias to length', function()
+ assert_equal(M.operator.length,M.operator.len)
+ end)
+
+ end)
+
+end) \ No newline at end of file
diff --git a/spec/table_spec.lua b/spec/table_spec.lua
index 209969a..ac5c46b 100644
--- a/spec/table_spec.lua
+++ b/spec/table_spec.lua
@@ -1,53 +1,53 @@
-require 'luacov'
-local _ = require 'moses'
+--require 'luacov'
+local M = require 'moses'
context('Table functions specs', function()
context('clear', function()
test('', function()
- local t = _.clear({'a', true, 'hello'})
- assert_true(_.isEqual(t,{}))
+ local t = M.clear({'a', true, 'hello'})
+ assert_true(M.isEqual(t,{}))
assert_nil(next(t))
end)
end)
context('each', function()
-
- test('provides values and iteration count ', function()
- local t = {1,2,3}
- local inc = 0
- _.each(t,function(i,v)
- inc = inc+1
- assert_equal(i,inc)
- assert_equal(t[i],v)
- end)
- end)
-
- test('can reference the given table', function()
- local t = {1,2,3}
- _.each(t,function(i,v,mul)
- t[i] = v*mul
- end,5)
- assert_true(_.isEqual(t,{5,10,15}))
- end)
-
- test('iterates over non-numeric keys and objects', function()
- local t = {one = 1, two = 2, three = 3}
- local copy = {}
- _.each(t,function(i,v) copy[i] = v end)
- assert_true(_.isEqual(t,copy))
- end)
-
- end)
+
+ test('provides values and iteration count ', function()
+ local t = {4,2,1}
+ local inc = 0
+ M.each(t,function(v, i)
+ inc = inc+1
+ assert_equal(i,inc)
+ assert_equal(t[i],v)
+ end)
+ end)
+
+ test('can reference the given table', function()
+ local t = {1,2,3}
+ M.each(t,function(v,i,mul)
+ t[i] = v*mul
+ end,5)
+ assert_true(M.isEqual(t,{5,10,15}))
+ end)
+
+ test('iterates over non-numeric keys and objects', function()
+ local t = {one = 1, two = 2, three = 3}
+ local copy = {}
+ M.each(t,function(v,i) copy[i] = v end)
+ assert_true(M.isEqual(t,copy))
+ end)
+
+ end)
context('eachi', function()
test('provides values and iteration count for integer keys only, in a sorted way', function()
- local t = {1,2,3}
+ local t = {4,2,1}
local inc = 0
- _.eachi(t,function(i,v)
+ M.eachi(t,function(v,i)
inc = inc+1
assert_equal(i,inc)
assert_equal(t[i],v)
@@ -59,7 +59,7 @@ context('Table functions specs', function()
local rk = {-1, 0, 1, 2}
local rv = {6, 1, 3, 5}
local inc = 0
- _.eachi(t,function(i,v)
+ M.eachi(t,function(v,i)
inc = inc+1
assert_equal(i,rk[inc])
assert_equal(v,rv[inc])
@@ -72,43 +72,66 @@ context('Table functions specs', function()
test('returns an array of values at numeric keys', function()
local t = {4,5,6}
- local values = _.at(t,1,2,3)
- assert_true(_.isEqual(values, t))
+ local values = M.at(t,1,2,3)
+ assert_true(M.isEqual(values, t))
local t = {a = 4, bb = true, ccc = false}
- local values = _.at(t,'a', 'ccc')
- assert_true(_.isEqual(values, {4, false}))
+ local values = M.at(t,'a', 'ccc')
+ assert_true(M.isEqual(values, {4, false}))
end)
end)
+ context('adjust', function()
+
+ test('adjusts a given value in a table using a function', function()
+ local double = function(v) return v * 2 end
+ local t = {1,2,3}
+ assert_true(M.isEqual(M.adjust(t,1,double),{2,2,3}))
+ assert_true(M.isEqual(M.adjust(t,2,double),{1,4,3}))
+ assert_true(M.isEqual(M.adjust(t,3,double),{1,2,6}))
+ end)
+
+ test('adjusts a given value in a table using a value', function()
+ local t = {1,2,3}
+ assert_true(M.isEqual(M.adjust(t,1,5),{5,2,3}))
+ assert_true(M.isEqual(M.adjust(t,2,-2),{1,-2,3}))
+ end)
+
+ test('throws an error if key is not found in table', function()
+ local double = function(v) return v * 2 end
+ local t = {x = 1}
+ assert_error(function() M.adjust(t,'y', 2) end)
+ end)
+
+ end)
+
context('count', function()
test('count the occurences of value in a list', function()
- assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},1),2)
- assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},2),3)
- assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},3),4)
- assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},4),1)
- assert_equal(_.count({1,1,2,3,3,3,2,4,3,2},5),0)
- assert_equal(_.count({false, false, true},false),2)
- assert_equal(_.count({false, false, true},true),1)
- assert_equal(_.count({{1,1},{1,1},{1,1},{2,2}},{1,1}),3)
- assert_equal(_.count({{1,1},{1,1},{1,1},{2,2}},{2,2}),1)
+ assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},1),2)
+ assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},2),3)
+ assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},3),4)
+ assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},4),1)
+ assert_equal(M.count({1,1,2,3,3,3,2,4,3,2},5),0)
+ assert_equal(M.count({false, false, true},false),2)
+ assert_equal(M.count({false, false, true},true),1)
+ assert_equal(M.count({{1,1},{1,1},{1,1},{2,2}},{1,1}),3)
+ assert_equal(M.count({{1,1},{1,1},{1,1},{2,2}},{2,2}),1)
end)
test('defaults to size when value is not given', function()
- assert_equal(_.count({1,1,2,3,3,3,2,4,3,2}),_.size({1,1,2,3,3,3,2,4,3,2}))
- assert_equal(_.count({false, false, true}),_.size({false, false, true}))
+ assert_equal(M.count({1,1,2,3,3,3,2,4,3,2}),M.size({1,1,2,3,3,3,2,4,3,2}))
+ assert_equal(M.count({false, false, true}),M.size({false, false, true}))
end)
end)
context('countf', function()
-
test('count the occurences of values passing an iterator test in a list', function()
- assert_equal(_.countf({1,2,3,4,5,6}, function(i,v)
+ assert_equal(M.countf({1,2,3,4,5,6}, function(v)
return v%2==0
end),3)
- assert_equal(_.countf({print, pairs, os, assert, ipairs}, function(i,v)
+ assert_equal(M.countf({print, pairs, os, assert, ipairs}, function(v)
return type(v)=='function'
end),4)
end)
@@ -120,12 +143,12 @@ context('Table functions specs', function()
local times = 3
local t = {1,2,3,4,5}
local kv = {}
- for k,v in _.cycle(t,times) do
+ for v,k in M.cycle(t,times) do
assert_equal(t[k],v)
kv[#kv+1] = v
end
for k,v in ipairs(kv) do
- assert_equal(_.count(kv,v),times)
+ assert_equal(M.count(kv,v),times)
end
end)
@@ -134,38 +157,38 @@ context('Table functions specs', function()
local t = {x = 1, z = 2}
local keys = {}
local values = {}
- for k,v in _.cycle(t,times) do
+ for v,k in M.cycle(t,times) do
assert_equal(t[k],v)
keys[#keys+1] = k
values[#values+1] = v
end
for k,v in ipairs(keys) do
- assert_equal(_.count(keys,v),times)
+ assert_equal(M.count(keys,v),times)
end
for k,v in ipairs(values) do
- assert_equal(_.count(values,v),times)
+ assert_equal(M.count(values,v),times)
end
end)
test('n defaults to 1, if not supplied', function()
local t = {1,2,3,4,5}
- for k,v in _.cycle(t) do
+ for v,k in M.cycle(t) do
t[k] = v + 1
end
- _.each(t, function(k, v)
+ M.each(t, function(v, k)
assert_equal(v, k + 1)
end)
end)
test('if n is negative or equal to 0, it does nothing', function()
local t = {1,2,3,4,5}
- for k,v in _.cycle(t, 0) do
+ for v,k in M.cycle(t, 0) do
t[k] = v + 1
end
- for k,v in _.cycle(t, -2) do
+ for v,k in M.cycle(t, -2) do
t[k] = v + 1
end
- _.each(t, function(k, v)
+ M.each(t, function(v, k)
assert_equal(v, k)
end)
end)
@@ -174,19 +197,19 @@ context('Table functions specs', function()
context('map', function()
test('applies an iterator function over each key-value pair ', function()
- assert_true(_.isEqual(_.map({1,2,3},function(i,v)
+ assert_true(M.isEqual(M.map({1,2,3},function(v)
return v+10
end),{11,12,13}))
end)
test('iterates over non-numeric keys and objects', function()
- assert_true(_.isEqual(_.map({a = 1, b = 2},function(k,v)
+ assert_true(M.isEqual(M.map({a = 1, b = 2},function(v,k)
return k..v
end),{a = 'a1',b = 'b2'}))
end)
test('maps key-value pairs to key-value pairs', function()
- assert_true(_.isEqual(_.map({a = 1, b = 2}, function(k, v)
+ assert_true(M.isEqual(M.map({a = 1, b = 2}, function(v, k)
return k .. k, v + 10
end), {aa = 11, bb = 12}))
end)
@@ -196,18 +219,18 @@ context('Table functions specs', function()
context('reduce', function()
test('folds a collection (left to right) from an initial state', function()
- assert_equal(_.reduce({1,2,3,4},function(memo,v) return memo+v end,0),10)
+ assert_equal(M.reduce({1,2,3,4},function(memo,v) return memo+v end,0),10)
end)
test('initial state defaults to the first value when not given', function()
- assert_equal(_.reduce({'a','b','c'},function(memo,v) return memo..v end),'abc')
+ assert_equal(M.reduce({'a','b','c'},function(memo,v) return memo..v end),'abc')
end)
test('supports arrays of booleans', function()
- assert_equal(_.reduce({true, false, true, true},function(memo,v) return memo and v end), false)
- assert_equal(_.reduce({true, true, true},function(memo,v) return memo and v end), true)
- assert_equal(_.reduce({false, false, false},function(memo,v) return memo and v end), false)
- assert_equal(_.reduce({false, false, true},function(memo,v) return memo or v end), true)
+ assert_equal(M.reduce({true, false, true, true},function(memo,v) return memo and v end), false)
+ assert_equal(M.reduce({true, true, true},function(memo,v) return memo and v end), true)
+ assert_equal(M.reduce({false, false, false},function(memo,v) return memo and v end), false)
+ assert_equal(M.reduce({false, false, true},function(memo,v) return memo or v end), true)
end)
end)
@@ -215,10 +238,10 @@ context('Table functions specs', function()
context('reduceby', function()
test('folds a collection (left to right) for specific values', function()
- local function even(_,v) return v%2==0 end
- local function odd(_,v) return v%2~=0 end
- assert_equal(_.reduceby({1,2,3,4},function(memo,v) return memo+v end,0,even), 6)
- assert_equal(_.reduceby({1,2,3,4},function(memo,v) return memo+v end,0,odd), 4)
+ local function even(v) return v%2==0 end
+ local function odd(v) return v%2~=0 end
+ assert_equal(M.reduceby({1,2,3,4},function(memo,v) return memo+v end,even,0), 6)
+ assert_equal(M.reduceby({1,2,3,4},function(memo,v) return memo+v end,odd,0), 4)
end)
end)
@@ -226,11 +249,11 @@ context('Table functions specs', function()
context('reduceRight', function()
test('folds a collection (right to left) from an initial state', function()
- assert_equal(_.reduceRight({1,2,4,16},function(memo,v) return memo/v end,256),2)
+ assert_equal(M.reduceRight({1,2,4,16},function(memo,v) return memo/v end,256),2)
end)
test('initial state defaults to the first value when not given', function()
- assert_equal(_.reduceRight({'a','b','c'},function(memo,v) return memo..v end),'cba')
+ assert_equal(M.reduceRight({'a','b','c'},function(memo,v) return memo..v end),'cba')
end)
end)
@@ -238,13 +261,13 @@ context('Table functions specs', function()
context('mapReduce', function()
test('folds a collection (left to right) saving intermediate states', function()
- assert_true(_.isEqual(_.mapReduce({1,2,4,16},function(memo,v)
+ assert_true(M.isEqual(M.mapReduce({1,2,4,16},function(memo,v)
return memo*v
end,0),{0,0,0,0}))
end)
test('initial state defaults to the first value when not given', function()
- assert_true(_.isEqual(_.mapReduce({'a','b','c'},function(memo,v)
+ assert_true(M.isEqual(M.mapReduce({'a','b','c'},function(memo,v)
return memo..v
end),{'a','ab','abc'}))
end)
@@ -254,13 +277,13 @@ context('Table functions specs', function()
context('mapReduceRight', function()
test('folds a collection (right to left) saving intermediate states', function()
- assert_true(_.isEqual(_.mapReduceRight({1,2,4,16},function(memo,v)
+ assert_true(M.isEqual(M.mapReduceRight({1,2,4,16},function(memo,v)
return memo/v
end,256),{16,4,2,2}))
end)
test('initial state defaults to the first value when not given', function()
- assert_true(_.isEqual(_.mapReduceRight({'a','b','c'},function(memo,v)
+ assert_true(M.isEqual(M.mapReduceRight({'a','b','c'},function(memo,v)
return memo..v
end),{'c','cb','cba'}))
end)
@@ -270,19 +293,19 @@ context('Table functions specs', function()
context('include', function()
test('looks for a value in a collection, returns true when found', function()
- assert_true(_.include({6,8,10,16,29},16))
+ assert_true(M.include({6,8,10,16,29},16))
end)
test('returns false when value was not found', function()
- assert_false(_.include({6,8,10,16,29},1))
+ assert_false(M.include({6,8,10,16,29},1))
end)
test('can lookup for a object', function()
- assert_true(_.include({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,{3}}}))
+ assert_true(M.include({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,{3}}}))
end)
test('given an iterator, return the first value passing a truth test', function()
- assert_true(_.include({'a','B','c'}, function(array_value)
+ assert_true(M.include({'a','B','c'}, function(array_value)
return (array_value:upper() == array_value)
end))
end)
@@ -292,19 +315,19 @@ context('Table functions specs', function()
context('detect', function()
test('looks for the first occurence of value, returns the key where it was found', function()
- assert_equal(_.detect({6,8,10,16},8),2)
+ assert_equal(M.detect({6,8,10,16},8),2)
end)
test('returns nil when value was not found', function()
- assert_nil(_.detect({nil,true,0,true,true},false))
+ assert_nil(M.detect({nil,true,0,true,true},false))
end)
test('can lookup for a object', function()
- assert_equal(_.detect({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,6}}),2)
+ assert_equal(M.detect({6,{18,{2,6}},10,{18,{2,{3}}},29},{18,{2,6}}),2)
end)
test('given an iterator, return the key of the first value passing a truth test', function()
- assert_equal(_.detect({'a','B','c'}, function(array_value)
+ assert_equal(M.detect({'a','B','c'}, function(array_value)
return (array_value:upper() == array_value)
end),2)
end)
@@ -320,9 +343,9 @@ context('Table functions specs', function()
{a = 2, b = 4},
{a = 3, b = 4}
}
- assert_true(_.isEqual(_.where(set, {a = 2}), {set[2],set[3]}))
- assert_true(_.isEqual(_.where(set, {b = 4}), {set[3],set[4]}))
- assert_true(_.isEqual(_.where(set, {a = 2, b = 2}), {set[2]}))
+ assert_true(M.isEqual(M.where(set, {a = 2}), {set[2],set[3]}))
+ assert_true(M.isEqual(M.where(set, {b = 4}), {set[3],set[4]}))
+ assert_true(M.isEqual(M.where(set, {a = 2, b = 2}), {set[2]}))
end)
test('returns nil when value was not found', function()
@@ -330,8 +353,8 @@ context('Table functions specs', function()
{a = 1, b = 2},
{a = 2, b = 2},
}
- assert_nil(_.where(set, {a = 3}))
- assert_nil(_.where(set, {b = 1}))
+ assert_nil(M.where(set, {a = 3}))
+ assert_nil(M.where(set, {b = 1}))
end)
end)
@@ -342,14 +365,14 @@ context('Table functions specs', function()
local a = {a = 1, b = 2}
local b = {a = 2, b = 3}
local c = {a = 3, b = 4}
- assert_equal(_.findWhere({a, b, c}, {a = 3, b = 4}), c)
+ assert_equal(M.findWhere({a, b, c}, {a = 3, b = 4}), c)
end)
test('returns nil when value was not found', function()
local a = {a = 1, b = 2}
local b = {a = 2, b = 3}
local c = {a = 3, b = 4}
- assert_nil(_.findWhere({a, b, c}, {a = 3, b = 0}))
+ assert_nil(M.findWhere({a, b, c}, {a = 3, b = 0}))
end)
end)
@@ -357,13 +380,13 @@ context('Table functions specs', function()
context('select', function()
test('collects all values passing a truth test with an iterator', function()
- assert_true(_.isEqual(_.select({1,2,3,4,5,6,7}, function(key,value)
+ assert_true(M.isEqual(M.select({7,6,5,4,3,2,1}, function(value)
return (value%2==0)
- end),{2,4,6}))
+ end),{6,4,2}))
- assert_true(_.isEqual(_.select({1,2,3,4,5,6,7}, function(key,value)
+ assert_true(M.isEqual(M.select({7,6,5,4,3,2,1}, function(value)
return (value%2~=0)
- end),{1,3,5,7}))
+ end),{7,5,3,1}))
end)
end)
@@ -371,13 +394,13 @@ context('Table functions specs', function()
context('reject', function()
test('collects all values failing a truth test with an iterator', function()
- assert_true(_.isEqual(_.reject({1,2,3,4,5,6,7}, function(key,value)
+ assert_true(M.isEqual(M.reject({7,6,5,4,3,2,1}, function(value)
return (value%2==0)
- end),{1,3,5,7}))
+ end),{7,5,3,1}))
- assert_true(_.isEqual(_.reject({1,2,3,4,5,6,7}, function(key,value)
+ assert_true(M.isEqual(M.reject({7,6,5,4,3,2,1}, function(value)
return (value%2~=0)
- end),{2,4,6}))
+ end),{6,4,2}))
end)
end)
@@ -385,11 +408,11 @@ context('Table functions specs', function()
context('all', function()
test('returns whether all elements matches a truth test', function()
- assert_true(_.all({2,4,6}, function(key,value)
+ assert_true(M.all({2,4,6}, function(value)
return (value%2==0)
end))
- assert_false(_.all({false,true,false}, function(key,value)
+ assert_false(M.all({false,true,false}, function(value)
return value == false
end))
end)
@@ -399,20 +422,20 @@ context('Table functions specs', function()
context('invoke', function()
test('calls an iterator over each object, passing it as a first arg', function()
- assert_true(_.isEqual(_.invoke({'a','bea','cdhza'},string.len),
+ assert_true(M.isEqual(M.invoke({'a','bea','cdhza'},string.len),
{1,3,5}))
- assert_true(_.isEqual(_.invoke({{2,3,2},{13,8,10},{0,-5}},_.sort),
+ assert_true(M.isEqual(M.invoke({{2,3,2},{13,8,10},{0,-5}},M.sort),
{{2,2,3},{8,10,13},{-5,0}}))
- assert_true(_.isEqual(_.invoke({{x = 1, y = 2},{x = 3, y=4}},'x'), {1,3}))
+ assert_true(M.isEqual(M.invoke({{x = 1, y = 2},{x = 3, y=4}},'x'), {1,3}))
end)
test('given a string, calls the matching object property the same way', function()
local a = {}; function a:call() return self end
local b, c, d = {}, {}, {}
b.call, c.call, d.call = a.call, a.call, a.call
- assert_true(_.isEqual(_.invoke({a,b,c,d},'call'),
+ assert_true(M.isEqual(M.invoke({a,b,c,d},'call'),
{a,b,c,d}))
end)
@@ -426,9 +449,9 @@ context('Table functions specs', function()
{name = 'John', age = 23},{name = 'Peter', age = 17},
{name = 'Steve', age = 15},{age = 33}}
- assert_true(_.isEqual(_.pluck(peoples,'age'),
+ assert_true(M.isEqual(M.pluck(peoples,'age'),
{23,17,15,33}))
- assert_true(_.isEqual(_.pluck(peoples,'name'),
+ assert_true(M.isEqual(M.pluck(peoples,'name'),
{'John','Peter','Steve'}))
end)
@@ -441,12 +464,12 @@ context('Table functions specs', function()
local peoples = {
{name = 'John', age = 23},{name = 'Peter', age = 17},
{name = 'Steve', age = 15},{age = 33}}
- assert_equal(_.max(_.pluck(peoples,'age')),33)
- assert_equal(_.max(peoples,function(people) return people.age end),33)
+ assert_equal(M.max(M.pluck(peoples,'age')),33)
+ assert_equal(M.max(peoples,function(people) return people.age end),33)
end)
test('directly compares items when given no iterator', function()
- assert_equal(_.max({'a','b','c'}),'c')
+ assert_equal(M.max({'a','b','c'}),'c')
end)
end)
@@ -457,35 +480,14 @@ context('Table functions specs', function()
local peoples = {
{name = 'John', age = 23},{name = 'Peter', age = 17},
{name = 'Steve', age = 15},{age = 33}}
- assert_equal(_.min(_.pluck(peoples,'age')),15)
- assert_equal(_.min(peoples,function(people) return people.age end),15)
+ assert_equal(M.min(M.pluck(peoples,'age')),15)
+ assert_equal(M.min(peoples,function(people) return people.age end),15)
end)
test('directly compares items when given no iterator', function()
- assert_equal(_.min({'a','b','c'}),'a')
+ assert_equal(M.min({'a','b','c'}),'a')
end)
- end)
-
- context('shuffle', function()
-
- test('shuffles values and objects in a collection', function()
- local values = {'a','b','c','d'}
- assert_true(_.same(_.shuffle (values),values))
- end)
-
- test('can accept a seed value to init randomization', function()
- local values = {'a','b','c','d'}
- local seed = os.time()
- assert_true(_.same(_.shuffle(values,seed),values))
- end)
-
- test('shuffled table has the same elements in a different order', function()
- local values = {'a','b','c','d'}
- assert_true(_.same(_.shuffle(values),values))
- assert_true(_.same(_.shuffle(values),values))
- end)
-
end)
context('same', function()
@@ -493,9 +495,9 @@ context('Table functions specs', function()
test('returns whether all objects from both given tables exists in each other', function()
local a = {'a','b','c','d'}
local b = {'b','a','d','c'}
- assert_true(_.same(a,b))
+ assert_true(M.same(a,b))
b[#b+1] = 'e'
- assert_false(_.same(a,b))
+ assert_false(M.same(a,b))
end)
end)
@@ -503,13 +505,13 @@ context('Table functions specs', function()
context('sort', function()
test('sorts a collection with respect to a given comparison function', function()
- assert_true(_.isEqual(_.sort({'b','a','d','c'}, function(a,b)
+ assert_true(M.isEqual(M.sort({'b','a','d','c'}, function(a,b)
return a:byte() < b:byte()
end),{'a','b','c','d'}))
end)
test('uses "<" operator when no comparison function is given', function()
- assert_true(_.isEqual(_.sort({'b','a','d','c'}),{'a','b','c','d'}))
+ assert_true(M.isEqual(M.sort({'b','a','d','c'}),{'a','b','c','d'}))
end)
end)
@@ -517,24 +519,24 @@ context('Table functions specs', function()
context('sortBy', function()
test('sort values on the result of a transform function', function()
- assert_true(_.isEqual(_.sortBy({1,2,3,4,5}, math.sin), {5,4,3,1,2}))
+ assert_true(M.isEqual(M.sortBy({1,2,3,4,5}, math.sin), {5,4,3,1,2}))
end)
- test('the transform function defaults to _.identity', function()
- assert_true(_.isEqual(_.sortBy({1,2,3,4,5}), {1,2,3,4,5}))
+ test('the transform function defaults to M.identity', function()
+ assert_true(M.isEqual(M.sortBy({1,2,3,4,5}), {1,2,3,4,5}))
end)
test('transform function can be a string name property', function()
local unsorted = {{item = 1, value = 10},{item = 2, value = 5},{item = 3, value = 8}}
local sorted = {{item = 2, value = 5},{item = 3, value = 8},{item = 1, value = 10}}
- assert_true(_.isEqual(_.sortBy(unsorted, 'value'), sorted))
+ assert_true(M.isEqual(M.sortBy(unsorted, 'value'), sorted))
end)
test('can use a custom comparison function', function()
local unsorted = {{item = 1, value = 10},{item = 2, value = 5},{item = 3, value = 8}}
local sorted = {{item = 1, value = 10},{item = 3, value = 8},{item = 2, value = 5}}
local function comp(a,b) return a > b end
- assert_true(_.isEqual(_.sortBy(unsorted, 'value', comp), sorted))
+ assert_true(M.isEqual(M.sortBy(unsorted, 'value', comp), sorted))
end)
end)
@@ -543,24 +545,20 @@ context('Table functions specs', function()
test('splits a collection into subsets of items behaving the same', function()
- assert_true(_.isEqual(_.groupBy({0,1,2,3,4,5,6},function(i,value)
+ assert_true(M.isEqual(M.groupBy({0,1,2,3,4,5,6},function(value)
return value%2==0 and 'even' or 'odd'
end),{even = {0,2,4,6},odd = {1,3,5}}))
- assert_true(_.isEqual(_.groupBy({0,'a',true, false,nil,b,0.5},function(i,value)
- return type(value)
- end),{number = {0,0.5},string = {'a'},boolean = {true,false}}))
+ assert_true(M.isEqual(M.groupBy({0,'a',true, false,nil,b,0.5},type),{number = {0,0.5},string = {'a'},boolean = {true,false}}))
- assert_true(_.isEqual(_.groupBy({'one','two','three','four','five'},function(i,value)
- return value:len()
- end),{[3] = {'one','two'},[4] = {'four','five'},[5] = {'three'}}))
+ assert_true(M.isEqual(M.groupBy({'one','two','three','four','five'},string.len),{[3] = {'one','two'},[4] = {'four','five'},[5] = {'three'}}))
end)
test('can takes extra-args', function()
- assert_true(_.isEqual(_.groupBy({3,9,10,12,15}, function(k,v,x) return v%x == 0 end,2), {[false] = {3,9,15}, [true] = {10,12}}))
- assert_true(_.isEqual(_.groupBy({3,9,10,12,15}, function(k,v,x) return v%x == 0 end,3), {[false] = {10}, [true] = {3,9,12,15}}))
+ assert_true(M.isEqual(M.groupBy({3,9,10,12,15}, function(v,k,x) return v%x == 0 end,2), {[false] = {3,9,15}, [true] = {10,12}}))
+ assert_true(M.isEqual(M.groupBy({3,9,10,12,15}, function(v,k,x) return v%x == 0 end,3), {[false] = {10}, [true] = {3,9,12,15}}))
end)
@@ -570,17 +568,13 @@ context('Table functions specs', function()
test('splits a collection in subsets and counts items inside', function()
- assert_true(_.isEqual(_.countBy({0,1,2,3,4,5,6},function(i,value)
+ assert_true(M.isEqual(M.countBy({0,1,2,3,4,5,6},function(value)
return value%2==0 and 'even' or 'odd'
end),{even = 4,odd = 3}))
- assert_true(_.isEqual(_.countBy({0,'a',true, false,nil,b,0.5},function(i,value)
- return type(value)
- end),{number = 2,string = 1,boolean = 2}))
+ assert_true(M.isEqual(M.countBy({0,'a',true, false,nil,b,0.5},type),{number = 2,string = 1,boolean = 2}))
- assert_true(_.isEqual(_.countBy({'one','two','three','four','five'},function(i,value)
- return value:len()
- end),{[3] = 2,[4] = 2,[5] = 1}))
+ assert_true(M.isEqual(M.countBy({'one','two','three','four','five'},string.len),{[3] = 2,[4] = 2,[5] = 1}))
end)
@@ -589,34 +583,34 @@ context('Table functions specs', function()
context('size', function()
test('counts the very number of objects in a collection', function()
- assert_equal(_.size {1,2,3},3)
+ assert_equal(M.size {1,2,3},3)
end)
test('counts nested tables elements as an unique value', function()
- assert_equal(_.size {1,2,3,{4,5}},4)
+ assert_equal(M.size {1,2,3,{4,5}},4)
end)
test('leaves nil values', function()
- assert_equal(_.size {1,2,3,nil,8},4)
+ assert_equal(M.size {1,2,3,nil,8},4)
end)
test('counts objects', function()
- assert_equal(_.size {one = 1,2,b = 3, [{}] = 'nil', 'c', [function() end] = 'foo'},6)
+ assert_equal(M.size {one = 1,2,b = 3, [{}] = 'nil', 'c', [function() end] = 'foo'},6)
end)
test('returns the size of the first arg when it is a table', function()
- assert_equal(_.size ({1,2},3,4,5),2)
+ assert_equal(M.size ({1,2},3,4,5),2)
end)
test('counts the number of non-nil args when the first one is not a table', function()
- assert_equal(_.size (1,3,4,5),4)
- assert_equal(_.size (nil,1,3,4,5),4)
- assert_equal(_.size (nil,1,3,4,nil,5),4)
+ assert_equal(M.size (1,3,4,5),4)
+ assert_equal(M.size (nil,1,3,4,5),4)
+ assert_equal(M.size (nil,1,3,4,nil,5),4)
end)
test('handles nil', function()
- assert_equal(_.size(),0)
- assert_equal(_.size(nil),0)
+ assert_equal(M.size(),0)
+ assert_equal(M.size(nil),0)
end)
@@ -625,20 +619,20 @@ context('Table functions specs', function()
context('containsKeys', function()
test('returns whether a table has all the keys from a given list', function()
- assert_true(_.containsKeys({1,2,3},{1,2,3}))
- assert_true(_.containsKeys({x = 1, y = 2},{x = 1,y =2}))
+ assert_true(M.containsKeys({1,2,3},{1,2,3}))
+ assert_true(M.containsKeys({x = 1, y = 2},{x = 1,y =2}))
end)
test('does not compare values', function()
- assert_true(_.containsKeys({1,2,3},{4,5,6}))
- assert_true(_.containsKeys({x = 1, y = 2},{x = 4,y = -1}))
+ assert_true(M.containsKeys({1,2,3},{4,5,6}))
+ assert_true(M.containsKeys({x = 1, y = 2},{x = 4,y = -1}))
end)
test('is not commutative', function()
- assert_true(_.containsKeys({1,2,3,4},{4,5,6}))
- assert_true(_.containsKeys({x = 1, y = 2,z = 5},{x = 4,y = -1}))
- assert_false(_.containsKeys({1,2,3},{4,5,6,7}))
- assert_false(_.containsKeys({x = 1, y = 2},{x = 4,y = -1,z = 0}))
+ assert_true(M.containsKeys({1,2,3,4},{4,5,6}))
+ assert_true(M.containsKeys({x = 1, y = 2,z = 5},{x = 4,y = -1}))
+ assert_false(M.containsKeys({1,2,3},{4,5,6,7}))
+ assert_false(M.containsKeys({x = 1, y = 2},{x = 4,y = -1,z = 0}))
end)
end)
@@ -646,20 +640,20 @@ context('Table functions specs', function()
context('sameKeys', function()
test('returns whether both tables features the same keys', function()
- assert_true(_.sameKeys({1,2,3},{1,2,3}))
- assert_true(_.sameKeys({x = 1, y = 2},{x = 1,y =2}))
+ assert_true(M.sameKeys({1,2,3},{1,2,3}))
+ assert_true(M.sameKeys({x = 1, y = 2},{x = 1,y =2}))
end)
test('does not compare values', function()
- assert_true(_.sameKeys({1,2,3},{4,5,6}))
- assert_true(_.sameKeys({x = 1, y = 2},{x = 4,y = -1}))
+ assert_true(M.sameKeys({1,2,3},{4,5,6}))
+ assert_true(M.sameKeys({x = 1, y = 2},{x = 4,y = -1}))
end)
test('is commutative', function()
- assert_false(_.sameKeys({1,2,3,4},{4,5,6}))
- assert_false(_.sameKeys({x = 1, y = 2,z = 5},{x = 4,y = -1}))
- assert_false(_.sameKeys({1,2,3},{4,5,6,7}))
- assert_false(_.sameKeys({x = 1, y = 2},{x = 4,y = -1,z = 0}))
+ assert_false(M.sameKeys({1,2,3,4},{4,5,6}))
+ assert_false(M.sameKeys({x = 1, y = 2,z = 5},{x = 4,y = -1}))
+ assert_false(M.sameKeys({1,2,3},{4,5,6,7}))
+ assert_false(M.sameKeys({x = 1, y = 2},{x = 4,y = -1,z = 0}))
end)
end)