39 Commits

Author SHA1 Message Date
Rose Liverman
e2a9e009af Merge branch 'rxi:master' into master 2025-07-20 17:53:40 -06:00
rxi
98847e7812 Updated copyright year; 2018 => 2020 2020-02-12 21:11:41 +00:00
rxi
6389f859c6 Made lume.reduce check initial value for nil instead of non-truthy
Fixes #32
2020-02-12 21:09:33 +00:00
rxi
d8c2eddc10 Merge pull request #30 from jaythomas/cleanup
Remove unnecessary expression; Add test
2019-03-14 23:10:46 +00:00
Jay Thomas
9e0f56e3e9 Remove unnecessary expression; Add test
First half of the expression returns a boolean already so the second
half is redundant
2019-03-08 09:58:40 -05:00
Paul Liverman III
c3089b0eb0 upd readme 2018-04-23 02:43:11 -07:00
Paul Liverman III
fb7b826942 added seed() fn, corrected err with local math_random 2018-04-23 02:41:29 -07:00
Paul Liverman III
0eccde530a upd version / ReadMe 2018-04-23 02:35:20 -07:00
Paul Liverman III
cea8f76bb3 lume uses love.math.random if available 2018-04-23 02:33:27 -07:00
Paul Liverman III
78805a5e42 using a local for math.random calls 2018-04-23 02:31:26 -07:00
rxi
0980d07eaa Fixed lume.ripairs() for falsey values; added test 2018-04-08 15:22:13 +01:00
rxi
09035882f1 Updated copyright year, moved full license to lume.lua 2018-03-10 15:30:04 +00:00
rxi
2b10ce1f98 Fixed README punctuation for lume.reduce 2018-03-10 14:57:56 +00:00
rxi
64aae8d473 Renamed lume.set -> lume.unique 2018-03-10 14:54:27 +00:00
rxi
758067dd33 Removed lume.rgba (superseded by lume.color) 2018-03-10 14:52:02 +00:00
rxi
b539dc74c7 Version 2.3.0 2017-05-06 08:20:35 +01:00
rxi
c517bd7c12 Changed header type used on function names in README 2017-05-06 08:11:21 +01:00
rxi
4fc4520a4c Added clearer example for lume.array() in README 2017-05-06 08:09:19 +01:00
rxi
1942218390 Updated copyright year: 2016 -> 2017 2017-05-06 08:06:14 +01:00
rxi
da0d1bbae7 Updated copyright year: 2015 -> 2016 2016-12-04 14:13:39 +00:00
rxi
03dcf81394 Removed local reference to math.random() 2016-12-04 14:09:58 +00:00
rxi
b569915d3e Added lume.vector(), updated README and tests 2016-09-19 21:56:24 +01:00
rxi
59f90934aa Added lume.isarray() to README 2016-02-21 16:43:18 +00:00
rxi
f226cf2e64 Exposed internal isarray() function as lume.isarray() 2016-02-21 16:33:21 +00:00
rxi
a20a39c8ee Version 2.2.3 2015-11-28 10:40:50 +00:00
rxi
faa5d8252f Removed some unused iterator vars 2015-10-21 19:10:53 +01:00
rxi
bf32432dac Merge pull request #8 from technomancy/luacheck
Pacify Luacheck.
2015-10-21 19:05:56 +01:00
Phil Hagelberg
b861303333 Pacify Luacheck.
Mostly just renaming unused args.
2015-10-19 07:21:47 +07:00
rxi
27278fb887 Version 2.2.2 2015-09-28 21:45:14 +01:00
rxi
8627638db0 Added support for NaN, inf and -inf to lume.serialize; updated tests 2015-09-23 19:32:25 +01:00
rxi
1559803c70 Updated README for lume.serialize changes 2015-09-04 18:59:59 +01:00
rxi
258e523219 Version 2.2.1 2015-08-30 19:47:53 +01:00
rxi
16848d83a5 Fixed number printing in lume.trace for Lua5.3 2015-08-15 11:37:32 +01:00
rxi
ca338b8833 Removed .gitignore file 2015-08-15 11:32:37 +01:00
rxi
ca36473904 Renaming of internal serialize func map 2015-08-15 11:31:50 +01:00
rxi
717745fe79 Updated README example for lume.trace() 2015-08-14 20:56:41 +01:00
rxi
688de3368e Lots of tweaks to lume.serialize(); circular reference detection 2015-08-14 20:50:42 +01:00
rxi
7412706277 Moved some stuff around in "test" directory 2015-08-14 20:32:00 +01:00
rxi
78144dbdb8 Changed lume.trace() to output in a nicer format, updated test 2015-08-14 20:29:29 +01:00
6 changed files with 225 additions and 167 deletions

3
.gitignore vendored
View File

@@ -1,3 +0,0 @@
__*
*.tmp
*.swp

View File

@@ -1,4 +1,4 @@
Copyright (c) 2015, rxi Copyright (c) 2020 rxi
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

159
README.md
View File

@@ -2,6 +2,10 @@
A collection of functions for Lua, geared towards game development. A collection of functions for Lua, geared towards game development.
This fork incorporates randomization from the LOVE engine's math library if
available, uses a local for random calls, and adds a function for setting the
seed for its randomizer.
## Installation ## Installation
@@ -15,10 +19,10 @@ lume = require "lume"
## Function Reference ## Function Reference
### lume.clamp(x, min, max) #### lume.clamp(x, min, max)
Returns the number `x` clamped between the numbers `min` and `max` Returns the number `x` clamped between the numbers `min` and `max`
### lume.round(x [, increment]) #### lume.round(x [, increment])
Rounds `x` to the nearest integer; rounds away from zero if we're midway Rounds `x` to the nearest integer; rounds away from zero if we're midway
between two integers. If `increment` is set then the number is rounded to the between two integers. If `increment` is set then the number is rounded to the
nearest increment. nearest increment.
@@ -27,44 +31,55 @@ lume.round(2.3) -- Returns 2
lume.round(123.4567, .1) -- Returns 123.5 lume.round(123.4567, .1) -- Returns 123.5
``` ```
### lume.sign(x) #### lume.sign(x)
Returns `1` if `x` is 0 or above, returns `-1` when `x` is negative. Returns `1` if `x` is 0 or above, returns `-1` when `x` is negative.
### lume.lerp(a, b, amount) #### lume.lerp(a, b, amount)
Returns the linearly interpolated number between `a` and `b`, `amount` should Returns the linearly interpolated number between `a` and `b`, `amount` should
be in the range of 0 - 1; if `amount` is outside of this range it is clamped. be in the range of 0 - 1; if `amount` is outside of this range it is clamped.
```lua ```lua
lume.lerp(100, 200, .5) -- Returns 150 lume.lerp(100, 200, .5) -- Returns 150
``` ```
### lume.smooth(a, b, amount) #### lume.smooth(a, b, amount)
Similar to `lume.lerp()` but uses cubic interpolation instead of linear Similar to `lume.lerp()` but uses cubic interpolation instead of linear
interpolation. interpolation.
### lume.pingpong(x) #### lume.pingpong(x)
Ping-pongs the number `x` between 0 and 1. Ping-pongs the number `x` between 0 and 1.
### lume.distance(x1, y1, x2, y2 [, squared]) #### lume.distance(x1, y1, x2, y2 [, squared])
Returns the distance between the two points. If `squared` is true then the Returns the distance between the two points. If `squared` is true then the
squared distance is returned -- this is faster to calculate and can still be squared distance is returned -- this is faster to calculate and can still be
used when comparing distances. used when comparing distances.
### lume.angle(x1, y1, x2, y2) #### lume.angle(x1, y1, x2, y2)
Returns the angle between the two points. Returns the angle between the two points.
### lume.random([a [, b]]) #### lume.vector(angle, magnitude)
Given an `angle` and `magnitude`, returns a vector.
```lua
local x, y = lume.vector(0, 10) -- Returns 10, 0
```
#### lume.seed([low [, high]])
Sets random seed. If using LOVE engine's math library, both `low` and `high`
arguments are used, else, only one argument is accepted.
#### lume.random([a [, b]])
Returns a random number between `a` and `b`. If only `a` is supplied a number Returns a random number between `a` and `b`. If only `a` is supplied a number
between `0` and `a` is returned. If no arguments are supplied a random number between `0` and `a` is returned. If no arguments are supplied a random number
between `0` and `1` is returned. between `0` and `1` is returned.
### lume.randomchoice(t) #### lume.randomchoice(t)
Returns a random value from array `t`. If the array is empty an error is Returns a random value from array `t`. If the array is empty an error is
raised. raised.
```lua ```lua
lume.randomchoice({true, false}) -- Returns either true or false lume.randomchoice({true, false}) -- Returns either true or false
``` ```
### lume.weightedchoice(t) #### lume.weightedchoice(t)
Takes the argument table `t` where the keys are the possible choices and the Takes the argument table `t` where the keys are the possible choices and the
value is the choice's weight. A weight should be 0 or above, the larger the value is the choice's weight. A weight should be 0 or above, the larger the
number the higher the probability of that choice being picked. If the table is number the higher the probability of that choice being picked. If the table is
@@ -74,7 +89,14 @@ lume.weightedchoice({ ["cat"] = 10, ["dog"] = 5, ["frog"] = 0 })
-- Returns either "cat" or "dog" with "cat" being twice as likely to be chosen. -- Returns either "cat" or "dog" with "cat" being twice as likely to be chosen.
``` ```
### lume.push(t, ...) #### lume.isarray(x)
Returns `true` if `x` is an array -- the value is assumed to be an array if it
is a table which contains a value at the index `1`. This function is used
internally and can be overridden if you wish to use a different method to detect
arrays.
#### lume.push(t, ...)
Pushes all the given values to the end of the table `t` and returns the pushed Pushes all the given values to the end of the table `t` and returns the pushed
values. Nil values are ignored. values. Nil values are ignored.
```lua ```lua
@@ -82,7 +104,7 @@ local t = { 1, 2, 3 }
lume.push(t, 4, 5) -- `t` becomes { 1, 2, 3, 4, 5 } lume.push(t, 4, 5) -- `t` becomes { 1, 2, 3, 4, 5 }
``` ```
### lume.remove(t, x) #### lume.remove(t, x)
Removes the first instance of the value `x` if it exists in the table `t`. Removes the first instance of the value `x` if it exists in the table `t`.
Returns `x`. Returns `x`.
```lua ```lua
@@ -90,7 +112,7 @@ local t = { 1, 2, 3 }
lume.remove(t, 2) -- `t` becomes { 1, 3 } lume.remove(t, 2) -- `t` becomes { 1, 3 }
``` ```
### lume.clear(t) #### lume.clear(t)
Nils all the values in the table `t`, this renders the table empty. Returns Nils all the values in the table `t`, this renders the table empty. Returns
`t`. `t`.
```lua ```lua
@@ -98,7 +120,7 @@ local t = { 1, 2, 3 }
lume.clear(t) -- `t` becomes {} lume.clear(t) -- `t` becomes {}
``` ```
### lume.extend(t, ...) #### lume.extend(t, ...)
Copies all the fields from the source tables to the table `t` and returns `t`. Copies all the fields from the source tables to the table `t` and returns `t`.
If a key exists in multiple tables the right-most table's value is used. If a key exists in multiple tables the right-most table's value is used.
```lua ```lua
@@ -106,10 +128,10 @@ local t = { a = 1, b = 2 }
lume.extend(t, { b = 4, c = 6 }) -- `t` becomes { a = 1, b = 4, c = 6 } lume.extend(t, { b = 4, c = 6 }) -- `t` becomes { a = 1, b = 4, c = 6 }
``` ```
### lume.shuffle(t) #### lume.shuffle(t)
Returns a shuffled copy of the array `t`. Returns a shuffled copy of the array `t`.
### lume.sort(t [, comp]) #### lume.sort(t [, comp])
Returns a copy of the array `t` with all its items sorted. If `comp` is a Returns a copy of the array `t` with all its items sorted. If `comp` is a
function it will be used to compare the items when sorting. If `comp` is a function it will be used to compare the items when sorting. If `comp` is a
string it will be used as the key to sort the items by. string it will be used as the key to sort the items by.
@@ -119,13 +141,13 @@ lume.sort({ {z=2}, {z=3}, {z=1} }, "z") -- Returns { {z=1}, {z=2}, {z=3} }
lume.sort({ 1, 3, 2 }, function(a, b) return a > b end) -- Returns { 3, 2, 1 } lume.sort({ 1, 3, 2 }, function(a, b) return a > b end) -- Returns { 3, 2, 1 }
``` ```
### lume.array(...) #### lume.array(...)
Iterates the supplied iterator and returns an array filled with the values. Iterates the supplied iterator and returns an array filled with the values.
```lua ```lua
lume.array(pairs({a = 1, b = 2})) -- Returns {"a", "b"} lume.array(string.gmatch("Hello world", "%a+")) -- Returns {"Hello", "world"}
``` ```
### lume.each(t, fn, ...) #### lume.each(t, fn, ...)
Iterates the table `t` and calls the function `fn` on each value followed by Iterates the table `t` and calls the function `fn` on each value followed by
the supplied additional arguments; if `fn` is a string the method of that name the supplied additional arguments; if `fn` is a string the method of that name
is called for each value. The function returns `t` unmodified. is called for each value. The function returns `t` unmodified.
@@ -134,14 +156,14 @@ lume.each({1, 2, 3}, print) -- Prints "1", "2", "3" on separate lines
lume.each({a, b, c}, "move", 10, 20) -- Does x:move(10, 20) on each value lume.each({a, b, c}, "move", 10, 20) -- Does x:move(10, 20) on each value
``` ```
### lume.map(t, fn) #### lume.map(t, fn)
Applies the function `fn` to each value in table `t` and returns a new table Applies the function `fn` to each value in table `t` and returns a new table
with the resulting values. with the resulting values.
```lua ```lua
lume.map({1, 2, 3}, function(x) return x * 2 end) -- Returns {2, 4, 6} lume.map({1, 2, 3}, function(x) return x * 2 end) -- Returns {2, 4, 6}
``` ```
### lume.all(t [, fn]) #### lume.all(t [, fn])
Returns true if all the values in `t` table are true. If a `fn` function is Returns true if all the values in `t` table are true. If a `fn` function is
supplied it is called on each value, true is returned if all of the calls to supplied it is called on each value, true is returned if all of the calls to
`fn` return true. `fn` return true.
@@ -149,7 +171,7 @@ supplied it is called on each value, true is returned if all of the calls to
lume.all({1, 2, 1}, function(x) return x == 1 end) -- Returns false lume.all({1, 2, 1}, function(x) return x == 1 end) -- Returns false
``` ```
### lume.any(t [, fn]) #### lume.any(t [, fn])
Returns true if any of the values in `t` table are true. If a `fn` function is Returns true if any of the values in `t` table are true. If a `fn` function is
supplied it is called on each value, true is returned if any of the calls to supplied it is called on each value, true is returned if any of the calls to
`fn` return true. `fn` return true.
@@ -157,23 +179,23 @@ supplied it is called on each value, true is returned if any of the calls to
lume.any({1, 2, 1}, function(x) return x == 1 end) -- Returns true lume.any({1, 2, 1}, function(x) return x == 1 end) -- Returns true
``` ```
### lume.reduce(t, fn [, first]) #### lume.reduce(t, fn [, first])
Applies `fn` on two arguments cumulative to the items of the array `t`, from Applies `fn` on two arguments cumulative to the items of the array `t`, from
left to right, so as to reduce the array to a single value. If a `first` value left to right, so as to reduce the array to a single value. If a `first` value
is specified the accumulator is initialised to this, otherwise the first value is specified the accumulator is initialised to this, otherwise the first value
in the array is used. If the array is empty and no `first` value is specified in the array is used. If the array is empty and no `first` value is specified
an error is raised, an error is raised.
```lua ```lua
lume.reduce({1, 2, 3}, function(a, b) return a + b end) -- Returns 6 lume.reduce({1, 2, 3}, function(a, b) return a + b end) -- Returns 6
``` ```
### lume.set(t) #### lume.unique(t)
Returns a copy of the `t` array with all the duplicate values removed. Returns a copy of the `t` array with all the duplicate values removed.
```lua ```lua
lume.set({2, 1, 2, "cat", "cat"}) -- Returns {1, 2, "cat"} lume.unique({2, 1, 2, "cat", "cat"}) -- Returns {1, 2, "cat"}
``` ```
### lume.filter(t, fn [, retainkeys]) #### lume.filter(t, fn [, retainkeys])
Calls `fn` on each value of `t` table. Returns a new table with only the values Calls `fn` on each value of `t` table. Returns a new table with only the values
where `fn` returned true. If `retainkeys` is true the table is not treated as where `fn` returned true. If `retainkeys` is true the table is not treated as
an array and retains its original keys. an array and retains its original keys.
@@ -181,7 +203,7 @@ an array and retains its original keys.
lume.filter({1, 2, 3, 4}, function(x) return x % 2 == 0 end) -- Returns {2, 4} lume.filter({1, 2, 3, 4}, function(x) return x % 2 == 0 end) -- Returns {2, 4}
``` ```
### lume.reject(t, fn [, retainkeys]) #### lume.reject(t, fn [, retainkeys])
The opposite of `lume.filter()`: Calls `fn` on each value of `t` table; returns The opposite of `lume.filter()`: Calls `fn` on each value of `t` table; returns
a new table with only the values where `fn` returned false. If `retainkeys` is a new table with only the values where `fn` returned false. If `retainkeys` is
true the table is not treated as an array and retains its original keys. true the table is not treated as an array and retains its original keys.
@@ -189,34 +211,34 @@ true the table is not treated as an array and retains its original keys.
lume.reject({1, 2, 3, 4}, function(x) return x % 2 == 0 end) -- Returns {1, 3} lume.reject({1, 2, 3, 4}, function(x) return x % 2 == 0 end) -- Returns {1, 3}
``` ```
### lume.merge(...) #### lume.merge(...)
Returns a new table with all the given tables merged together. If a key exists Returns a new table with all the given tables merged together. If a key exists
in multiple tables the right-most table's value is used. in multiple tables the right-most table's value is used.
```lua ```lua
lume.merge({a=1, b=2, c=3}, {c=8, d=9}) -- Returns {a=1, b=2, c=8, d=9} lume.merge({a=1, b=2, c=3}, {c=8, d=9}) -- Returns {a=1, b=2, c=8, d=9}
``` ```
### lume.concat(...) #### lume.concat(...)
Returns a new array consisting of all the given arrays concatenated into one. Returns a new array consisting of all the given arrays concatenated into one.
```lua ```lua
lume.concat({1, 2}, {3, 4}, {5, 6}) -- Returns {1, 2, 3, 4, 5, 6} lume.concat({1, 2}, {3, 4}, {5, 6}) -- Returns {1, 2, 3, 4, 5, 6}
``` ```
### lume.find(t, value) #### lume.find(t, value)
Returns the index/key of `value` in `t`. Returns `nil` if that value does not Returns the index/key of `value` in `t`. Returns `nil` if that value does not
exist in the table. exist in the table.
```lua ```lua
lume.find({"a", "b", "c"}, "b") -- Returns 2 lume.find({"a", "b", "c"}, "b") -- Returns 2
``` ```
### lume.match(t, fn) #### lume.match(t, fn)
Returns the value and key of the value in table `t` which returns true when Returns the value and key of the value in table `t` which returns true when
`fn` is called on it. Returns `nil` if no such value exists. `fn` is called on it. Returns `nil` if no such value exists.
```lua ```lua
lume.match({1, 5, 8, 7}, function(x) return x % 2 == 0 end) -- Returns 8, 3 lume.match({1, 5, 8, 7}, function(x) return x % 2 == 0 end) -- Returns 8, 3
``` ```
### lume.count(t [, fn]) #### lume.count(t [, fn])
Counts the number of values in the table `t`. If a `fn` function is supplied it Counts the number of values in the table `t`. If a `fn` function is supplied it
is called on each value, the number of times it returns true is counted. is called on each value, the number of times it returns true is counted.
```lua ```lua
@@ -224,47 +246,47 @@ lume.count({a = 2, b = 3, c = 4, d = 5}) -- Returns 4
lume.count({1, 2, 4, 6}, function(x) return x % 2 == 0 end) -- Returns 3 lume.count({1, 2, 4, 6}, function(x) return x % 2 == 0 end) -- Returns 3
``` ```
### lume.slice(t [, i [, j]]) #### lume.slice(t [, i [, j]])
Mimics the behaviour of Lua's `string.sub`, but operates on an array rather Mimics the behaviour of Lua's `string.sub`, but operates on an array rather
than a string. Creates and returns a new array of the given slice. than a string. Creates and returns a new array of the given slice.
```lua ```lua
lume.slice({"a", "b", "c", "d", "e"}, 2, 4) -- Returns {"b", "c", "d"} lume.slice({"a", "b", "c", "d", "e"}, 2, 4) -- Returns {"b", "c", "d"}
``` ```
### lume.first(t [, n]) #### lume.first(t [, n])
Returns the first element of an array or nil if the array is empty. If `n` is Returns the first element of an array or nil if the array is empty. If `n` is
specificed an array of the first `n` elements is returned. specificed an array of the first `n` elements is returned.
```lua ```lua
lume.first({"a", "b", "c"}) -- Returns "a" lume.first({"a", "b", "c"}) -- Returns "a"
``` ```
### lume.last(t [, n]) #### lume.last(t [, n])
Returns the last element of an array or nil if the array is empty. If `n` is Returns the last element of an array or nil if the array is empty. If `n` is
specificed an array of the last `n` elements is returned. specificed an array of the last `n` elements is returned.
```lua ```lua
lume.last({"a", "b", "c"}) -- Returns "c" lume.last({"a", "b", "c"}) -- Returns "c"
``` ```
### lume.invert(t) #### lume.invert(t)
Returns a copy of the table where the keys have become the values and the Returns a copy of the table where the keys have become the values and the
values the keys. values the keys.
```lua ```lua
lume.invert({a = "x", b = "y"}) -- returns {x = "a", y = "b"} lume.invert({a = "x", b = "y"}) -- returns {x = "a", y = "b"}
``` ```
### lume.pick(t, ...) #### lume.pick(t, ...)
Returns a copy of the table filtered to only contain values for the given keys. Returns a copy of the table filtered to only contain values for the given keys.
```lua ```lua
lume.pick({ a = 1, b = 2, c = 3 }, "a", "c") -- Returns { a = 1, c = 3 } lume.pick({ a = 1, b = 2, c = 3 }, "a", "c") -- Returns { a = 1, c = 3 }
``` ```
### lume.keys(t) #### lume.keys(t)
Returns an array containing each key of the table. Returns an array containing each key of the table.
### lume.clone(t) #### lume.clone(t)
Returns a shallow copy of the table `t`. Returns a shallow copy of the table `t`.
### lume.fn(fn, ...) #### lume.fn(fn, ...)
Creates a wrapper function around function `fn`, automatically inserting the Creates a wrapper function around function `fn`, automatically inserting the
arguments into `fn` which will persist every time the wrapper is called. Any arguments into `fn` which will persist every time the wrapper is called. Any
arguments which are passed to the returned function will be inserted after the arguments which are passed to the returned function will be inserted after the
@@ -274,7 +296,7 @@ local f = lume.fn(print, "Hello")
f("world") -- Prints "Hello world" f("world") -- Prints "Hello world"
``` ```
### lume.once(fn, ...) #### lume.once(fn, ...)
Returns a wrapper function to `fn` which takes the supplied arguments. The Returns a wrapper function to `fn` which takes the supplied arguments. The
wrapper function will call `fn` on the first call and do nothing on any wrapper function will call `fn` on the first call and do nothing on any
subsequent calls. subsequent calls.
@@ -284,7 +306,7 @@ f() -- Prints "Hello"
f() -- Does nothing f() -- Does nothing
``` ```
### lume.memoize(fn) #### lume.memoize(fn)
Returns a wrapper function to `fn` where the results for any given set of Returns a wrapper function to `fn` where the results for any given set of
arguments are cached. `lume.memoize()` is useful when used on functions with arguments are cached. `lume.memoize()` is useful when used on functions with
slow-running computations. slow-running computations.
@@ -292,7 +314,7 @@ slow-running computations.
fib = lume.memoize(function(n) return n < 2 and n or fib(n-1) + fib(n-2) end) fib = lume.memoize(function(n) return n < 2 and n or fib(n-1) + fib(n-2) end)
``` ```
### lume.combine(...) #### lume.combine(...)
Creates a wrapper function which calls each supplied argument in the order they Creates a wrapper function which calls each supplied argument in the order they
were passed to `lume.combine()`; nil arguments are ignored. The wrapper were passed to `lume.combine()`; nil arguments are ignored. The wrapper
function passes its own arguments to each of its wrapped functions when it is function passes its own arguments to each of its wrapped functions when it is
@@ -303,21 +325,21 @@ local f = lume.combine(function(a, b) print(a + b) end,
f(3, 4) -- Prints "7" then "12" on a new line f(3, 4) -- Prints "7" then "12" on a new line
``` ```
### lume.call(fn, ...) #### lume.call(fn, ...)
Calls the given function with the provided arguments and returns its values. If Calls the given function with the provided arguments and returns its values. If
`fn` is `nil` then no action is performed and the function returns `nil`. `fn` is `nil` then no action is performed and the function returns `nil`.
```lua ```lua
lume.call(print, "Hello world") -- Prints "Hello world" lume.call(print, "Hello world") -- Prints "Hello world"
``` ```
### lume.time(fn, ...) #### lume.time(fn, ...)
Inserts the arguments into function `fn` and calls it. Returns the time in Inserts the arguments into function `fn` and calls it. Returns the time in
seconds the function `fn` took to execute followed by `fn`'s returned values. seconds the function `fn` took to execute followed by `fn`'s returned values.
```lua ```lua
lume.time(function(x) return x end, "hello") -- Returns 0, "hello" lume.time(function(x) return x end, "hello") -- Returns 0, "hello"
``` ```
### lume.lambda(str) #### lume.lambda(str)
Takes a string lambda and returns a function. `str` should be a list of Takes a string lambda and returns a function. `str` should be a list of
comma-separated parameters, followed by `->`, followed by the expression which comma-separated parameters, followed by `->`, followed by the expression which
will be evaluated and returned. will be evaluated and returned.
@@ -326,24 +348,24 @@ local f = lume.lambda "x,y -> 2*x+y"
f(10, 5) -- Returns 25 f(10, 5) -- Returns 25
``` ```
### lume.serialize(x) #### lume.serialize(x)
Serializes the argument `x` into a string which can be loaded again using Serializes the argument `x` into a string which can be loaded again using
`lume.deserialize()`. Only booleans, numbers, tables and strings can be `lume.deserialize()`. Only booleans, numbers, tables and strings can be
serialized. Circular references are not handled; all nested tables are serialized. Circular references will result in an error; all nested tables are
serialized as unique tables. serialized as unique tables.
```lua ```lua
lume.serialize({a = "test", b = {1, 2, 3}, false}) lume.serialize({a = "test", b = {1, 2, 3}, false})
-- Returns "{[1]=false,["a"]="test",["b"]={[1]=1,[2]=2,[3]=3,},}" -- Returns "{[1]=false,["a"]="test",["b"]={[1]=1,[2]=2,[3]=3,},}"
``` ```
### lume.deserialize(str) #### lume.deserialize(str)
Deserializes a string created by `lume.serialize()` and returns the resulting Deserializes a string created by `lume.serialize()` and returns the resulting
value. This function should not be run on an untrusted string. value. This function should not be run on an untrusted string.
```lua ```lua
lume.deserialize("{1, 2, 3}") -- Returns {1, 2, 3} lume.deserialize("{1, 2, 3}") -- Returns {1, 2, 3}
``` ```
### lume.split(str [, sep]) #### lume.split(str [, sep])
Returns an array of the words in the string `str`. If `sep` is provided it is Returns an array of the words in the string `str`. If `sep` is provided it is
used as the delimiter, consecutive delimiters are not grouped together and will used as the delimiter, consecutive delimiters are not grouped together and will
delimit empty strings. delimit empty strings.
@@ -352,7 +374,7 @@ lume.split("One two three") -- Returns {"One", "two", "three"}
lume.split("a,b,,c", ",") -- Returns {"a", "b", "", "c"} lume.split("a,b,,c", ",") -- Returns {"a", "b", "", "c"}
``` ```
### lume.trim(str [, chars]) #### lume.trim(str [, chars])
Trims the whitespace from the start and end of the string `str` and returns the Trims the whitespace from the start and end of the string `str` and returns the
new string. If a `chars` value is set the characters in `chars` are trimmed new string. If a `chars` value is set the characters in `chars` are trimmed
instead of whitespace. instead of whitespace.
@@ -360,7 +382,7 @@ instead of whitespace.
lume.trim(" Hello ") -- Returns "Hello" lume.trim(" Hello ") -- Returns "Hello"
``` ```
### lume.wordwrap(str [, limit]) #### lume.wordwrap(str [, limit])
Returns `str` wrapped to `limit` number of characters per line, by default Returns `str` wrapped to `limit` number of characters per line, by default
`limit` is `72`. `limit` can also be a function which when passed a string, `limit` is `72`. `limit` can also be a function which when passed a string,
returns `true` if it is too long for a single line. returns `true` if it is too long for a single line.
@@ -369,7 +391,7 @@ returns `true` if it is too long for a single line.
lume.wordwrap("Hello world. This is a short string", 14) lume.wordwrap("Hello world. This is a short string", 14)
``` ```
### lume.format(str [, vars]) #### lume.format(str [, vars])
Returns a formatted string. The values of keys in the table `vars` can be Returns a formatted string. The values of keys in the table `vars` can be
inserted into the string by using the form `"{key}"` in `str`; numerical keys inserted into the string by using the form `"{key}"` in `str`; numerical keys
can also be used. can also be used.
@@ -378,25 +400,25 @@ lume.format("{b} hi {a}", {a = "mark", b = "Oh"}) -- Returns "Oh hi mark"
lume.format("Hello {1}!", {"world"}) -- Returns "Hello world!" lume.format("Hello {1}!", {"world"}) -- Returns "Hello world!"
``` ```
### lume.trace(...) #### lume.trace(...)
Prints the current filename and line number followed by each argument separated Prints the current filename and line number followed by each argument separated
by a space. by a space.
```lua ```lua
-- Assuming the file is called "example.lua" and the next line is 12: -- Assuming the file is called "example.lua" and the next line is 12:
lume.trace("hello", 1234) -- Prints "[example.lua:12] hello 1234" lume.trace("hello", 1234) -- Prints "example.lua:12: hello 1234"
``` ```
### lume.dostring(str) #### lume.dostring(str)
Executes the lua code inside `str`. Executes the lua code inside `str`.
```lua ```lua
lume.dostring("print('Hello!')") -- Prints "Hello!" lume.dostring("print('Hello!')") -- Prints "Hello!"
``` ```
### lume.uuid() #### lume.uuid()
Generates a random UUID string; version 4 as specified in Generates a random UUID string; version 4 as specified in
[RFC 4122](http://www.ietf.org/rfc/rfc4122.txt). [RFC 4122](http://www.ietf.org/rfc/rfc4122.txt).
### lume.hotswap(modname) #### lume.hotswap(modname)
Reloads an already loaded module in place, allowing you to immediately see the Reloads an already loaded module in place, allowing you to immediately see the
effects of code changes without having to restart the program. `modname` should effects of code changes without having to restart the program. `modname` should
be the same string used when loading the module with require(). In the case of be the same string used when loading the module with require(). In the case of
@@ -407,7 +429,7 @@ lume.hotswap("lume") -- Reloads the lume module
assert(lume.hotswap("inexistant_module")) -- Raises an error assert(lume.hotswap("inexistant_module")) -- Raises an error
``` ```
### lume.ripairs(t) #### lume.ripairs(t)
Performs the same function as `ipairs()` but iterates in reverse; this allows Performs the same function as `ipairs()` but iterates in reverse; this allows
the removal of items from the table during iteration without any items being the removal of items from the table during iteration without any items being
skipped. skipped.
@@ -418,7 +440,7 @@ for i, v in lume.ripairs({ "a", "b", "c" }) do
end end
``` ```
### lume.color(str [, mul]) #### lume.color(str [, mul])
Takes color string `str` and returns 4 values, one for each color channel (`r`, Takes color string `str` and returns 4 values, one for each color channel (`r`,
`g`, `b` and `a`). By default the returned values are between 0 and 1; the `g`, `b` and `a`). By default the returned values are between 0 and 1; the
values are multiplied by the number `mul` if it is provided. values are multiplied by the number `mul` if it is provided.
@@ -429,15 +451,7 @@ lume.color("#00ffff", 256) -- Returns 0, 256, 256, 256
lume.color("rgb(255, 0, 0)", 256) -- Returns 256, 0, 0, 256 lume.color("rgb(255, 0, 0)", 256) -- Returns 256, 0, 0, 256
``` ```
### lume.rgba(color) #### lume.chain(value)
Takes the 32bit integer `color` argument and returns 4 numbers, one for each
channel, with a range of 0 - 255. The returned values can be used as the
arguments to [LÖVE](http://love2d.org)'s setColor() function.
```lua
lume.rgba(0xFF304050) -- Returns 48, 64, 80, 255
```
### lume.chain(value)
Returns a wrapped object which allows chaining of lume functions. The function Returns a wrapped object which allows chaining of lume functions. The function
result() should be called at the end of the chain to return the resulting result() should be called at the end of the chain to return the resulting
value. value.
@@ -488,4 +502,3 @@ lume.count(t, { age = 10 }) -- returns 2
This library is free software; you can redistribute it and/or modify it under This library is free software; you can redistribute it and/or modify it under
the terms of the MIT license. See [LICENSE](LICENSE) for details. the terms of the MIT license. See [LICENSE](LICENSE) for details.

156
lume.lua
View File

@@ -1,25 +1,39 @@
-- --
-- lume -- lume
-- --
-- Copyright (c) 2015 rxi -- Copyright (c) 2020 rxi
-- --
-- This library is free software; you can redistribute it and/or modify it -- Permission is hereby granted, free of charge, to any person obtaining a copy of
-- under the terms of the MIT license. See LICENSE for details. -- this software and associated documentation files (the "Software"), to deal in
-- the Software without restriction, including without limitation the rights to
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do
-- so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in all
-- copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
-- --
local lume = { _version = "2.2.0" } local lume = { _version = "2.4.0-Guard13007-fork" }
local pairs, ipairs = pairs, ipairs local pairs, ipairs = pairs, ipairs
local type, assert, unpack = type, assert, unpack or table.unpack local type, assert, unpack = type, assert, unpack or table.unpack
local tostring, tonumber = tostring, tonumber local tostring, tonumber = tostring, tonumber
local math_floor = math.floor local math_floor = math.floor
local math_ceil = math.ceil local math_ceil = math.ceil
local math_random = math.random
local math_cos = math.cos
local math_atan2 = math.atan2 or math.atan local math_atan2 = math.atan2 or math.atan
local math_sqrt = math.sqrt local math_sqrt = math.sqrt
local math_abs = math.abs local math_abs = math.abs
local math_pi = math.pi local math_random = love and love.math and love.math.random or math.random
local math_randomseed = love and love.math and love.math.setRandomSeed or math.randomseed
local noop = function() local noop = function()
end end
@@ -42,12 +56,8 @@ local iscallable = function(x)
return mt and mt.__call ~= nil return mt and mt.__call ~= nil
end end
local isarray = function(x)
return (type(x) == "table" and x[1] ~= nil) and true or false
end
local getiter = function(x) local getiter = function(x)
if isarray(x) then if lume.isarray(x) then
return ipairs return ipairs
elseif type(x) == "table" then elseif type(x) == "table" then
return pairs return pairs
@@ -117,6 +127,16 @@ function lume.angle(x1, y1, x2, y2)
end end
function lume.vector(angle, magnitude)
return math.cos(angle) * magnitude, math.sin(angle) * magnitude
end
function lume.seed(low, high)
return math_randomseed(low, high)
end
function lume.random(a, b) function lume.random(a, b)
if not a then a, b = 0, 1 end if not a then a, b = 0, 1 end
if not b then b = 0 end if not b then b = 0 end
@@ -131,7 +151,7 @@ end
function lume.weightedchoice(t) function lume.weightedchoice(t)
local sum = 0 local sum = 0
for k, v in pairs(t) do for _, v in pairs(t) do
assert(v >= 0, "weight value less than zero") assert(v >= 0, "weight value less than zero")
sum = sum + v sum = sum + v
end end
@@ -144,6 +164,11 @@ function lume.weightedchoice(t)
end end
function lume.isarray(x)
return type(x) == "table" and x[1] ~= nil
end
function lume.push(t, ...) function lume.push(t, ...)
local n = select("#", ...) local n = select("#", ...)
for i = 1, n do for i = 1, n do
@@ -153,11 +178,11 @@ function lume.push(t, ...)
end end
function lume.remove(t, x) function lume.remove(t, x)
local iter = getiter(t) local iter = getiter(t)
for i, v in iter(t) do for i, v in iter(t) do
if v == x then if v == x then
if isarray(t) then if lume.isarray(t) then
table.remove(t, i) table.remove(t, i)
break break
else else
@@ -172,7 +197,7 @@ end
function lume.clear(t) function lume.clear(t)
local iter = getiter(t) local iter = getiter(t)
for k, v in iter(t) do for k in iter(t) do
t[k] = nil t[k] = nil
end end
return t return t
@@ -250,7 +275,7 @@ end
function lume.all(t, fn) function lume.all(t, fn)
fn = iteratee(fn) fn = iteratee(fn)
local iter = getiter(t) local iter = getiter(t)
for k, v in iter(t) do for _, v in iter(t) do
if not fn(v) then return false end if not fn(v) then return false end
end end
return true return true
@@ -260,7 +285,7 @@ end
function lume.any(t, fn) function lume.any(t, fn)
fn = iteratee(fn) fn = iteratee(fn)
local iter = getiter(t) local iter = getiter(t)
for k, v in iter(t) do for _, v in iter(t) do
if fn(v) then return true end if fn(v) then return true end
end end
return false return false
@@ -268,10 +293,10 @@ end
function lume.reduce(t, fn, first) function lume.reduce(t, fn, first)
local started = first ~= nil
local acc = first local acc = first
local started = first and true or false
local iter = getiter(t) local iter = getiter(t)
for k, v in iter(t) do for _, v in iter(t) do
if started then if started then
acc = fn(acc, v) acc = fn(acc, v)
else else
@@ -284,9 +309,9 @@ function lume.reduce(t, fn, first)
end end
function lume.set(t) function lume.unique(t)
local rtn = {} local rtn = {}
for k, v in pairs(lume.invert(t)) do for k in pairs(lume.invert(t)) do
rtn[#rtn + 1] = k rtn[#rtn + 1] = k
end end
return rtn return rtn
@@ -302,7 +327,7 @@ function lume.filter(t, fn, retainkeys)
if fn(v) then rtn[k] = v end if fn(v) then rtn[k] = v end
end end
else else
for k, v in iter(t) do for _, v in iter(t) do
if fn(v) then rtn[#rtn + 1] = v end if fn(v) then rtn[#rtn + 1] = v end
end end
end end
@@ -319,7 +344,7 @@ function lume.reject(t, fn, retainkeys)
if not fn(v) then rtn[k] = v end if not fn(v) then rtn[k] = v end
end end
else else
for k, v in iter(t) do for _, v in iter(t) do
if not fn(v) then rtn[#rtn + 1] = v end if not fn(v) then rtn[#rtn + 1] = v end
end end
end end
@@ -346,7 +371,7 @@ function lume.concat(...)
local t = select(i, ...) local t = select(i, ...)
if t ~= nil then if t ~= nil then
local iter = getiter(t) local iter = getiter(t)
for k, v in iter(t) do for _, v in iter(t) do
rtn[#rtn + 1] = v rtn[#rtn + 1] = v
end end
end end
@@ -379,14 +404,14 @@ function lume.count(t, fn)
local iter = getiter(t) local iter = getiter(t)
if fn then if fn then
fn = iteratee(fn) fn = iteratee(fn)
for k, v in iter(t) do for _, v in iter(t) do
if fn(v) then count = count + 1 end if fn(v) then count = count + 1 end
end end
else else
if isarray(t) then if lume.isarray(t) then
return #t return #t
end end
for k in iter(t) do count = count + 1 end for _ in iter(t) do count = count + 1 end
end end
return count return count
end end
@@ -435,7 +460,7 @@ end
function lume.keys(t) function lume.keys(t)
local rtn = {} local rtn = {}
local iter = getiter(t) local iter = getiter(t)
for k, v in iter(t) do rtn[#rtn + 1] = k end for k in iter(t) do rtn[#rtn + 1] = k end
return rtn return rtn
end end
@@ -458,12 +483,12 @@ end
function lume.once(fn, ...) function lume.once(fn, ...)
local fn = lume.fn(fn, ...) local f = lume.fn(fn, ...)
local done = false local done = false
return function(...) return function(...)
if done then return end if done then return end
done = true done = true
return fn(...) return f(...)
end end
end end
@@ -489,7 +514,7 @@ end
function lume.combine(...) function lume.combine(...)
local n = select('#', ...) local n = select('#', ...)
if n == 0 then return noop end if n == 0 then return noop end
if n == 1 then if n == 1 then
local fn = select(1, ...) local fn = select(1, ...)
if not fn then return noop end if not fn then return noop end
assert(iscallable(fn), "expected a function or nil") assert(iscallable(fn), "expected a function or nil")
@@ -536,19 +561,41 @@ function lume.lambda(str)
end end
function lume.serialize(x) local serialize
local f = { string = function(v) return string.format("%q", v) end,
number = tostring, boolean = tostring } local serialize_map = {
f.table = function(t) [ "boolean" ] = tostring,
[ "nil" ] = tostring,
[ "string" ] = function(v) return string.format("%q", v) end,
[ "number" ] = function(v)
if v ~= v then return "0/0" -- nan
elseif v == 1 / 0 then return "1/0" -- inf
elseif v == -1 / 0 then return "-1/0" end -- -inf
return tostring(v)
end,
[ "table" ] = function(t, stk)
stk = stk or {}
if stk[t] then error("circular reference") end
local rtn = {} local rtn = {}
stk[t] = true
for k, v in pairs(t) do for k, v in pairs(t) do
rtn[#rtn + 1] = "[" .. f[type(k)](k) .. "]=" .. f[type(v)](v) .. "," rtn[#rtn + 1] = "[" .. serialize(k, stk) .. "]=" .. serialize(v, stk)
end end
return "{" .. table.concat(rtn) .. "}" stk[t] = nil
return "{" .. table.concat(rtn, ",") .. "}"
end end
local err = function(t,k) error("unsupported serialize type: " .. k) end }
setmetatable(f, { __index = err })
return f[type(x)](x) setmetatable(serialize_map, {
__index = function(_, k) error("unsupported serialize type: " .. k) end
})
serialize = function(x, stk)
return serialize_map[type(x)](x, stk)
end
function lume.serialize(x)
return serialize(x)
end end
@@ -579,19 +626,19 @@ function lume.wordwrap(str, limit)
limit = limit or 72 limit = limit or 72
local check local check
if type(limit) == "number" then if type(limit) == "number" then
check = function(str) return #str >= limit end check = function(s) return #s >= limit end
else else
check = limit check = limit
end end
local rtn = {} local rtn = {}
local line = "" local line = ""
for word, spaces in str:gmatch("(%S+)(%s*)") do for word, spaces in str:gmatch("(%S+)(%s*)") do
local str = line .. word local s = line .. word
if check(str) then if check(s) then
table.insert(rtn, line .. "\n") table.insert(rtn, line .. "\n")
line = word line = word
else else
line = str line = s
end end
for c in spaces:gmatch(".") do for c in spaces:gmatch(".") do
if c == "\n" then if c == "\n" then
@@ -618,7 +665,7 @@ end
function lume.trace(...) function lume.trace(...)
local info = debug.getinfo(2, "Sl") local info = debug.getinfo(2, "Sl")
local t = { "[" .. info.short_src .. ":" .. info.currentline .. "]" } local t = { info.short_src .. ":" .. info.currentline .. ":" }
for i = 1, select("#", ...) do for i = 1, select("#", ...) do
local x = select(i, ...) local x = select(i, ...)
if type(x) == "number" then if type(x) == "number" then
@@ -659,7 +706,7 @@ function lume.hotswap(modname)
end end
local err = nil local err = nil
local function onerror(e) local function onerror(e)
for k, v in pairs(_G) do _G[k] = oldglobal[k] end for k in pairs(_G) do _G[k] = oldglobal[k] end
err = lume.trim(e) err = lume.trim(e)
end end
local ok, oldmod = pcall(require, modname) local ok, oldmod = pcall(require, modname)
@@ -684,7 +731,9 @@ end
local ripairs_iter = function(t, i) local ripairs_iter = function(t, i)
i = i - 1 i = i - 1
local v = t[i] local v = t[i]
if v then return i, v end if v ~= nil then
return i, v
end
end end
function lume.ripairs(t) function lume.ripairs(t)
@@ -714,15 +763,6 @@ function lume.color(str, mul)
end end
function lume.rgba(color)
local a = math_floor((color / 16777216) % 256)
local r = math_floor((color / 65536) % 256)
local g = math_floor((color / 256) % 256)
local b = math_floor((color) % 256)
return r, g, b, a
end
local chain_mt = {} local chain_mt = {}
chain_mt.__index = lume.map(lume.filter(lume, iscallable, true), chain_mt.__index = lume.map(lume.filter(lume, iscallable, true),
function(fn) function(fn)
@@ -738,7 +778,7 @@ function lume.chain(value)
end end
setmetatable(lume, { setmetatable(lume, {
__call = function(t, ...) __call = function(_, ...)
return lume.chain(...) return lume.chain(...)
end end
}) })

View File

@@ -1,4 +1,4 @@
local tester = require "tester" local tester = require "util.tester"
package.path = "../?.lua;" .. package.path package.path = "../?.lua;" .. package.path
@@ -20,7 +20,7 @@ end
-- lume.round -- lume.round
tests["lume.round"] = function() tests["lume.round"] = function()
testeq( lume.round(.5), 1 ) testeq( lume.round(.5), 1 )
testeq( lume.round(-.5), -1 ) testeq( lume.round(-.5), -1 )
testeq( lume.round(2.4), 2 ) testeq( lume.round(2.4), 2 )
testeq( lume.round(123, 10), 120 ) testeq( lume.round(123, 10), 120 )
@@ -80,6 +80,18 @@ tests["lume.angle"] = function()
testeq( lume.angle(10, 10, 10, 30), math.rad(90) ) testeq( lume.angle(10, 10, 10, 30), math.rad(90) )
end end
-- lume.vector
tests["lume.vector"] = function()
local function cmp(a, b) return math.abs(a - b) < 10e-6 end
local x, y
x, y = lume.vector(0, 10)
testeq( cmp(x, 10) and cmp(y, 0), true )
x, y = lume.vector(math.pi, 100)
testeq( cmp(x, -100) and cmp(y, 0), true )
x, y = lume.vector(math.pi * 0.25, 100)
testeq( cmp(x, 70.71067811865476) and cmp(y, 70.71067811865476), true )
end
-- lume.random -- lume.random
tests["lume.random"] = function() tests["lume.random"] = function()
testeq( type(lume.random()), "number" ) testeq( type(lume.random()), "number" )
@@ -129,7 +141,6 @@ tests["lume.remove"] = function()
testeq(t, { 2, 4, 5 }) testeq(t, { 2, 4, 5 })
lume.remove(t, 5) lume.remove(t, 5)
testeq(t, { 2, 4 }) testeq(t, { 2, 4 })
local m = { a = 1, b = 2, c = 3 }
local x = lume.remove(t, 123) local x = lume.remove(t, 123)
testeq(x, 123) testeq(x, 123)
end end
@@ -233,6 +244,7 @@ end
tests["lume.reduce"] = function() tests["lume.reduce"] = function()
local concat = function(a, b) return a .. b end local concat = function(a, b) return a .. b end
local add = function(a, b) return a + b end local add = function(a, b) return a + b end
local any = function(a, b) return a or b end
testeq( lume.reduce({"cat", "dog"}, concat, ""), "catdog" ) testeq( lume.reduce({"cat", "dog"}, concat, ""), "catdog" )
testeq( lume.reduce({"cat", "dog"}, concat, "pig"), "pigcatdog" ) testeq( lume.reduce({"cat", "dog"}, concat, "pig"), "pigcatdog" )
testeq( lume.reduce({"me", "ow"}, concat), "meow" ) testeq( lume.reduce({"me", "ow"}, concat), "meow" )
@@ -242,25 +254,27 @@ tests["lume.reduce"] = function()
testeq( lume.reduce({}, concat, "potato"), "potato" ) testeq( lume.reduce({}, concat, "potato"), "potato" )
testeq( lume.reduce({a=1, b=2}, add, 5), 8 ) testeq( lume.reduce({a=1, b=2}, add, 5), 8 )
testeq( lume.reduce({a=1, b=2}, add), 3 ) testeq( lume.reduce({a=1, b=2}, add), 3 )
testeq( lume.reduce({false, false, false}, any), false )
testeq( lume.reduce({false, true, false}, any), true )
tester.test.error(lume.reduce, {}, add) tester.test.error(lume.reduce, {}, add)
end end
-- lume.set -- lume.unique
tests["lume.set"] = function() tests["lume.unique"] = function()
testeq( lume.set({}), {} ) testeq( lume.unique({}), {} )
local t = lume.set({1, 2, 3, 2, 5, 6, 6}) local t = lume.unique({1, 2, 3, 2, 5, 6, 6})
table.sort(t) table.sort(t)
testeq( t, {1, 2, 3, 5, 6} ) testeq( t, {1, 2, 3, 5, 6} )
local t = lume.set({"a", "b", "c", "b", "d"}) local t = lume.unique({"a", "b", "c", "b", "d"})
table.sort(t) table.sort(t)
testeq( t, {"a", "b", "c", "d"} ) testeq( t, {"a", "b", "c", "d"} )
end end
-- lume.filter -- lume.filter
tests["lume.filter"] = function() tests["lume.filter"] = function()
local t = lume.filter({1, 2, 3, 4, 5}, function(x) return x % 2 == 0 end ) local t = lume.filter({1, 2, 3, 4, 5}, function(x) return x % 2 == 0 end )
testeq( t, {2, 4} ) testeq( t, {2, 4} )
local t = lume.filter({a=1, b=2, c=3}, function(x) return x == 2 end, true) local t = lume.filter({a=1, b=2, c=3}, function(x) return x == 2 end, true)
testeq( t, {b=2} ) testeq( t, {b=2} )
local t = lume.filter({{ x=1, y=1 }, { x=2, y=2 }, { x=1, y=3 }}, { x = 1 }) local t = lume.filter({{ x=1, y=1 }, { x=2, y=2 }, { x=1, y=3 }}, { x = 1 })
testeq( t, {{ x=1, y=1 }, {x=1, y=3}} ) testeq( t, {{ x=1, y=1 }, {x=1, y=3}} )
@@ -268,9 +282,9 @@ end
-- lume.reject -- lume.reject
tests["lume.reject"] = function() tests["lume.reject"] = function()
local t = lume.reject({1, 2, 3, 4, 5}, function(x) return x % 2 == 0 end ) local t = lume.reject({1, 2, 3, 4, 5}, function(x) return x % 2 == 0 end )
testeq( t, {1, 3, 5} ) testeq( t, {1, 3, 5} )
local t = lume.reject({a=1, b=2, c=3}, function(x) return x == 2 end, true) local t = lume.reject({a=1, b=2, c=3}, function(x) return x == 2 end, true)
testeq( t, {a=1, c=3} ) testeq( t, {a=1, c=3} )
local t = lume.reject({{ x=1, y=1 }, { x=2, y=2 }, { x=1, y=3 }}, { x = 1 }) local t = lume.reject({{ x=1, y=1 }, { x=2, y=2 }, { x=1, y=3 }}, { x = 1 })
testeq( t, {{ x=2, y=2 }} ) testeq( t, {{ x=2, y=2 }} )
@@ -354,7 +368,7 @@ tests["lume.first"] = function()
local t = { "a", "b", "c", "d", "e" } local t = { "a", "b", "c", "d", "e" }
testeq( lume.first(t), "a" ) testeq( lume.first(t), "a" )
testeq( lume.first(t, 1), { "a" } ) testeq( lume.first(t, 1), { "a" } )
testeq( lume.first(t, 2), { "a", "b" } ) testeq( lume.first(t, 2), { "a", "b" } )
end end
-- lume.last -- lume.last
@@ -362,7 +376,7 @@ tests["lume.last"] = function()
local t = { "a", "b", "c", "d", "e" } local t = { "a", "b", "c", "d", "e" }
testeq( lume.last(t), "e" ) testeq( lume.last(t), "e" )
testeq( lume.last(t, 1), { "e" } ) testeq( lume.last(t, 1), { "e" } )
testeq( lume.last(t, 2), { "d", "e" } ) testeq( lume.last(t, 2), { "d", "e" } )
end end
-- lume.invert -- lume.invert
@@ -385,9 +399,9 @@ end
-- lume.keys -- lume.keys
tests["lume.keys"] = function() tests["lume.keys"] = function()
testeq( lume.keys({}), {} ) testeq( lume.keys({}), {} )
local t = lume.keys({ aaa = 1, bbb = 2, ccc = 3 }) local t = lume.keys({ aaa = 1, bbb = 2, ccc = 3 })
table.sort(t) table.sort(t)
testeq( t, {"aaa", "bbb", "ccc"} ) testeq( t, {"aaa", "bbb", "ccc"} )
local t = lume.keys({ "x", "x", "x" }) local t = lume.keys({ "x", "x", "x" })
testeq( t, {1, 2, 3} ) testeq( t, {1, 2, 3} )
end end
@@ -484,6 +498,10 @@ tests["lume.serialize, lume.deserialize"] = function()
local t = { 1, 2, 3, 4, true, false, "cat", "dog", {1, 2, 3} } local t = { 1, 2, 3, 4, true, false, "cat", "dog", {1, 2, 3} }
local s = lume.serialize(t) local s = lume.serialize(t)
testeq( lume.deserialize(s), t ) testeq( lume.deserialize(s), t )
testeq( lume.deserialize(lume.serialize(math.huge)), math.huge )
testeq( lume.deserialize(lume.serialize(-math.huge)), -math.huge )
local x = lume.deserialize(lume.serialize(0 / 0)) -- nan
testeq( x ~= x, true )
end end
-- lume.split -- lume.split
@@ -535,19 +553,19 @@ tests["lume.trace"] = function()
local oldprint = print local oldprint = print
local file, line, msg local file, line, msg
print = function(x) print = function(x)
file, line, msg = x:match("%[(.-):(.-)%] (.*)") file, line, msg = x:match("(.-):(.-): (.*)")
end end
lume.trace("Hi world", 123.456, 1, nil) lume.trace("Hi world", 123.456, 1, nil)
print = oldprint print = oldprint
testeq( file:match(".lua$"), ".lua" ) testeq( file:match(".lua$"), ".lua" )
testeq( tonumber(line) ~= nil, true ) testeq( tonumber(line) ~= nil, true )
testeq( msg, "Hi world 123.46 1 nil" ) testeq( msg, "Hi world 123.46 1 nil" )
end end
-- lume.dostring -- lume.dostring
tests["lume.dostring"] = function() tests["lume.dostring"] = function()
testeq( lume.dostring([[return "hello!"]]), "hello!" ) testeq( lume.dostring([[return "hello!"]]), "hello!" )
testeq( lume.dostring([[return 12345]]), 12345 ) testeq( lume.dostring([[return 12345]]), 12345 )
end end
-- lume.uuid -- lume.uuid
@@ -565,12 +583,12 @@ end
-- lume.ripairs -- lume.ripairs
tests["lume.ripairs"] = function() tests["lume.ripairs"] = function()
local t = { "a", "b", "c" } local t = { "a", "b", false, "c" }
local r = {} local r = {}
for i, v in lume.ripairs(t) do for i, v in lume.ripairs(t) do
table.insert(r, { i, v }) table.insert(r, { i, v })
end end
testeq( r, { { 3, "c" }, { 2, "b" }, { 1, "a" } }) testeq( r, { { 4, "c" }, { 3, false }, { 2, "b" }, { 1, "a" } })
tester.test.error(lume.ripairs, nil) tester.test.error(lume.ripairs, nil)
end end
@@ -591,18 +609,9 @@ tests["lume.color"] = function()
tester.test.error(lume.color, "rgba(1, 1, 1, 1") tester.test.error(lume.color, "rgba(1, 1, 1, 1")
end end
-- lume.rgba
tests["lume.rgba"] = function()
local r, g, b, a = lume.rgba(0x12345678)
testeq( a, 0x12 )
testeq( r, 0x34 )
testeq( g, 0x56 )
testeq( b, 0x78 )
end
-- lume.chain -- lume.chain
tests["lume.chain"] = function() tests["lume.chain"] = function()
local t = lume.chain({1, 2}):map(function(x) return x * 2 end):result() local t = lume.chain({1, 2}):map(function(x) return x * 2 end):result()
testeq( t, { 2, 4 } ) testeq( t, { 2, 4 } )
testeq( lume.chain(10):result(), 10 ) testeq( lume.chain(10):result(), 10 )
local t = lume({1, 2}):map(function(x) return x * 2 end):result() local t = lume({1, 2}):map(function(x) return x * 2 end):result()
@@ -613,4 +622,3 @@ end
tester.dotests(tests) tester.dotests(tests)
tester.test.global() tester.test.global()
tester.printresults() tester.printresults()