prelude.coffee is a JavaScript functional programming library. It is written for and in, CoffeeScript. It is a fork of prelude.ls, LiveScript's excellent recommended base library, which is based in part off of Haskell's Prelude module.
As in the popular JQuery library and in the tradition of CoffeeScript's syntax supporting it, callables come last in the argument list.
scan1 [1..4], (x, y) -> (x + y) / x #=> [1, 3, 2, 3]
zipWith(['A', 'J'], ['V', 'M'], function (a, b) { return a + ' and ' + b }) //=> ['A and V', 'J and M']
When it makes sense, working on an object will return an object, and a string will return a string.
filter {a: 3, b: 4, c: 5, d: 6}, even #=> {b: 4, d: 6}
map({d: 3, e: 4}, function (x) { return x * 2; }); //=> {d: 6, e: 8}
Because CoffeeScript does not have bult-in support for declaring curried functions and because functions are easilly declarable lambdas, only a few special functions return a partially applied function.
sum = (list) -> fold 0, list, plus sum [1..3] #=> 6
var hasX = elem('X'); hasX('hello there Doctor X'); //=> true
Install via cloning from github: git clone git@github.com:xixixao/prelude-ls.git
into a node-modules folder and then you can require it as a standard node module.
For the browser, just include the prelude-min.js
file. It is a valid RequireJS module, or if you are not using RequireJS, it will install itself as prelude
under the global namespace.
To import all prelude.ls functions to somewhere, you can use prelude.installPrelude target
. For instance, calling prelude.installPrelude window
in the browser will install all the functions as global variables. In node, you can do require('prelude-ls').installPrelude global
.
To import selectively, you can use typical {join, concat} = prelude
syntax or pass in a list of functions to not include prelude.installPrelude window, ['exp']
.
Examples of usage in CoffeeScript on the left, examples using JavaScript on the right. The examples may not be related.
Functions which are 'curried' will return a partially applied function when called with less than the specified number of arguments. Eg. plus3 = plus 3
and then plus3 8 #=> 11
.
Use the toMap
function to turn an object or an array into a "Function", a mapping from keys to values. "Iterable" refers to objects, arrays and strings. "List" refers to arrays and strings. Iterating over a string only works on IE8+.
Applies the supplied callable to each item in the collection, returns a new collection with the results. The length of the result is the same as the length of the input.
map [1..5], times 2 #=> [2, 4, 6, 8, 10] map 'haha', call 'toUpperCase' #=> 'HAHA' map {a: 2, b: 3}, plus 2 #=> {a: 4, b: 5} map ['one', 'two'], {one: 1, two: 2} #=> [1, 2] map {power: 1, light: 0}, ['off', 'on'] #=> {power: 'on', light: 'off'} map [num: 3; num: 1], lookup 'num' #=> [3, 1]
map([1, 2, 3, 4, 5], times(2)); //=> [2, 4, 6, 8, 10] map(aList, someFunction); //=> a list of something map(['HA', 'ha'], toMap({ha: 1, HA: 2})); //=> [2, 1] var mapAddTwo = flip(map, add(2)); //=> a function
Filters a collection, removing all items that do not pass the test of applying the supplied callable to each item.
filter [1..5], (x) -> x < 3 #=> [1, 2] filter {a: 3, b: 4, c: 0}, even #=> {b: 4, c: 0} filter 'hahaha', equals 'a' #=> 'aaa'
filter([1, 2, 3, 4, 5], odd); //=> [1, 3, 5] filter({x: 4, y: 2, z: 8}, function(x){ return x <= 2; }); //=> {y: 2}
Like filter
, but instead of adding item to results it passes the test, adds those items who don't pass the test.
reject [1..5], odd #=> [2, 4] reject {a: 2, b: 'ha'}, (x) -> typeOf(x) is 'String' #=> {a: 2} reject 'mmhmm', equals 'h' #=> 'mmmm'
reject({a: 3, b: 8, c: 1}, even); //=> {a: 3, c: 1}
Equivalent to [(filter f, xs), (reject f, xs)]
, but more efficient, only using one loop.
partition 'abcdefcf', flip elem, ['abc'] #=> ['abcc', 'deff']
partition([1, 2, 3, 4, 5], even); //=> [[2, 4], [1, 3, 5]]
Returns the first item to pass the test.
find [2, 4, 6, 7, 8, 9, 10], odd #=> 7
find({b: 3, a: 2}, function(x){ return x <= 3; }); //=> 2
Applies function to each item in the collection (item in list or object, character in string), returns the original collection. Used for side effects.
each [['a'], ['b'], ['c']], call 'push', 'boom' #=> [['a', 'boom'], ['b', 'boom'], ['c', 'boom']]
var count = 4; each({a:1, b:2, c:3}, function(x){ count += x; }); count; //=> 10
The first item of the list, or first character of the string.
head [1..5] #=> 1 head 'hello' #=> 'h'
head([9, 8, 7]); //=> 9 head('world'); //-> 'w'
Everything but the first item of the list, or everything but the first character in the string.
tail [1..5] #=> [2, 3, 4, 5] tail 'hello' #=> 'ello'
tail([9, 8, 7]); //=> [8, 7] tail('world'); //-> 'orld'
The last item of the list, or the last character of the string.
last [1..5] #=> 5 last 'hello' #=> 'o'
last([9, 8, 7]); //=> 7 last('world'); //-> 'd'
Everything but the last item of the list, or everything but the last character in the string.
initial [1..5] #=> [1, 2, 3, 4] initial 'hello' #=> 'hell'
initial([9, 8, 7]); //=> [9, 8] initial('world'); //-> 'worl'
Whether the collection is empty, eg. []
, {}
, or ''
.
empty [] #=> true empty {} #=> true empty '' #=> true
empty([]); //=> true empty({}); //=> true empty('')' //=> true
Returns a list of the values of the object.
values a: 2, b: 3, c: 9 #=> [2, 3, 9]
values({moo: 'haha'}); //=> ['haha']
Returns a list of the keys of the object.
keys a: 2, b: 3, c: 9 #=> ['a', 'b', 'c']
keys([1, 2, 3]); //=> [0, 1, 2]
Returns the number of items in the collection.
length [1, 4, 2] #=> 3 length h: 2, j: 23 #=> 2 length 'antwoord' #=> 8
length([3]); //=> 1 length {} //=> 0 length 'doh' //=> 3
Returns a new list made by adding the supplied item to the front of the given list. Also mashes together strings.
cons 1, [2, 3] #=> [1, 2, 3] cons 4, 5 #=> [4, 5] cons 'a', 'bc' #=> 'abc'
cons(2, [4, 6]); //=> [2, 4, 6]
Returns a new list - either putting two lists together, or appending an item to a list. Also mashes together strings.
append [1, 2], [3, 4] #=> [1, 2, 3, 4] append [1, 2] 3 #=> [1, 2, 3] append 'abc', 'def' #=> 'abcdef'
append([4, 5], [6, 7]); //=> [4, 5, 6, 7] append([4, 5], 6); //=> [4, 5, 6] append('ha', 'ha'); //=> 'haha'
Joins a list with the specified separator.
join '|', [1...4] #=> '1|2|3'
join('*', [4, 5, 6]); //=> '4*5*6'
Reverses a list or a string.
reverse [1..3] #=> [3, 2, 1] reverse 'goat' #=> 'taog'
reverse([3, 4, 5]); //=> [5, 4, 3] reverse('Moo'); //=> 'ooM'
Takes a collection of items, and using the function supplied, folds them into a single value. Requires an initial value (memo), which will be the result in case of an empty collection. The function supplied must take two arguments.
fold 0, [1..5], plus #=> 15 product = fold 1, times fold someFunc, anObject
fold(function(x, y){ return x + y; }, 0, {a: 4, b: 5, c: 6}); //=> 15
Like fold
, except assumes a non-empty collection, and thus doesn't require an initial value.
fold1 [1..3], plus #=> 6
fold1(aFunction, aList);
Like fold
, except from the right.
foldr 9, [1, 2, 3, 4], minus #=> -1
foldr(aFunction, initValue, aList);
Like foldr
, except assumes a non-empty collection, and thus doesn't require an initial value.
foldr1 [1, 2, 3, 4, 9], minus #=> -1
foldr1(aFunction, aList);
Unfold builds a list from a seed value (x
). It takes a function which either returns undefined
when it is done producing the list, or returns [a, b]
, a
is prepended to the list, and b
is used as the next element in the recursive call.
unfold 10, (x) -> if x > 0 then [x, x - 1] #=> [10,9,8,7,6,5,4,3,2,1]
Returns true if each item in the collection is true.
andList [true, 2 + 2 == 4] #=> true andList [true, true, false] #=> false
andList(aListAllTrue); //=> true
Returns true if any item in the collection is true.
orList [false, false, true, false] #=> true
orList({a: false, b: true}); //=> true
Returns true if any of the items in the collection are true when applied to the test.
any [3, 5, 7, 8, 9], even #=> true
any([2, 4, 6, 8], odd); #=> false
Returns true if all the items in the collection are true when applied to the test.
all ['ha', 'ma', 'la'], (x) -> typeOf(x) is 'String' #=> true
all('mmmhmm', function(x){ return x == 'm'; }); //=> false
Sorts a list, does not modify the input.
sort [3, 1, 5, 2, 4, 6] #=> [1,2,3,4,5,6]
Takes a function which compares two items and returns either -1
, 0
, or 1
, and a list, and sorts using that function. The original list is not modified.
obj = one: 1, two: 2, three: 3 sortBy ['three', 'one', 'two'], (compare toMap obj) #=> ['one', 'two', 'three']
Takes a function, applies it to both x
and y
, and produces either -1
, 0
, or 1
. Useful when combined with sortBy
, and just given the first argument.
compare [1..3], [0..5], lookup 'length' #=> -1 compare [1..9], [0..5], lookup 'length' #=> 0 compare [1..4], [4..7], lookup 'length' #=> 1
Sums up the values in the list or object. 0 if empty.
sum [1..5] #=> 15 sum x: 1, y: 2, z: 3 #=> 6
sum([4, 5, 6]); //=> 15
Gets the product of all the items in the list or objects. 1 if empty.
product [1, 2, 3] #=> 6
product([4, 3, 2]); //=> 24
Gets the mean of the values in the list or object.
mean [1..5] #=> 3
mean([4, 3]); //=> 3.5
Concatenates a list of lists together.
concat [[1], [2, 3], [4]] #=> [1, 2, 3, 4] concat ['aa', 'bb', 'cc', 'dd'] #=> 'aabbccdd'
concat([['a', 'b'], ['c']]); //=> ['a', 'b', 'c']
Maps the callable on the list, then concats.
concatMap [1, 2, 3], (x) -> [1..x] #=> [1,1,2,1,2,3] concatMap ['aa', 'bb', 'cc', 'dd'], call 'toUpperCase' #=> 'AABBCCDD'
concatMap([1, 2, 3]], function(x){ return [x];}); //=> [1, 2, 3]
Takes a list of comparable items, and returns the biggest of them.
maximum [4, 1, 9, 3] #=> 9
maximum(['b', 'a', 'd']); //=> 'd'
Takes a list of comparable items, and returns the smallest of them.
minimum ['abcdef'] #=> 'a'
minimum([3, 2, 8]); //=> 2
Like a fold, except instead of just returning the final value, returns a list composed of the initial value, the intermediate values, and then the final value. Requires an initial value (memo) in case of an empty collection. The function supplied needs to take two arguments.
scan (plus), 0, [1..3] #=> [0, 1, 3, 6]
scan(someFunc, 0, [1, 2, 3]);
Like scan
, except assumes non-empty collection, and thus doesn't require an initial value.
scan1 [1..3], plus #=> [1, 3, 6]
scan1([1, 2, 3], someFunc);
Like scan
, except from the right.
scanr (plus), 0, [1..3] #=> [6, 5, 3, 0]
scanr(someFunc, 0, [1, 2, 3]);
Like scanr
, except assumes non-empty collection, and thus doesn't require an initial value.
scanr1 [1..3], plus #=> [6, 5, 3]
scanr1([1, 2, 3], someFunc);
Takes its second argument, and repeats it n times.
replicate 4, 'a' #=> ['a', 'a', 'a', 'a']
replicate(4, 2); //=> [3, 3, 3, 3]
Returns the first n items in the list or string.
take 2, [1..5] #=> [1, 2] take 4, 'hello' #=> 'hell'
take(4, []); //=> [] var takeTwo = take(2);
Returns the result of dropping the first n items of the list or string.
drop 2, [1..5] #=> [3, 4, 5] drop 1, 'goat' #=> 'oat'
drop(6, [3, 4]); //=> [] drop(3, 'foot'); //=> 't'
Equivalent to [(take n, xs), (drop n, xs)]
splitAt 2, [1..5] #=> [[1, 2], [3, 4, 5]]
splitAt(4, 'hello'); //=> ['hell', 'o']
Takes the first items of the list or string which pass the test.
takeWhile 'cabdek', flip elem, ['abcd'] #=> 'cabd'
takeWhile([2, 4, 5, 6], even); //=> [2, 4]
Drops the first items of the list or string which pass the test.
dropWhile [2, 4, 5, 6], even #=> [5, 6]
dropWhile([3, 1, 2, 5], odd); //=> [2, 5]
Equivalent to [(takeWhile f, xs), (dropWhile f, xs)]
span [2, 4, 5, 6], even #=> [[2, 4], [5, 6]]
span([3, 1, 2, 5], odd); //=> [[3, 1], [2, 5]]
Equivalent to span xs, (x) -> not f x
breakIt [1..5], equals 3 #=> [[1, 2], [3, 4, 5]]
breakIt(even, [2, 4, 5, 6] //=> [[], [2, 4, 5, 6]]
Converts a list of lists (pairs) into an object.
listToObj [['a', 1], ['b', 2]] #=> {a: 1, b: 2}
listToObj([['d', 5], ['e', 6]]); //=> {d: 5, e: 6}
Turns an object or an array into a function, a mapping from keys to values.
f = toMap m: 4, c: 6 f 'm' #=> 4
var g = toMap(['a', 'b']); g(1); //=> 'b'
Zips together its arguments into a list of lists.
zip [1, 2], [4, 5] #=> [[1, 4], [2, 5]]
zip([1, 2], [9, 8]); //=> [[1, 9], [2, 8]]
As zip
, but applies the supplied function to the lists and creates a list of the results. The supplied function must take two arguments.
zipWith [1, 2, 3], [3, 2, 1], plus #=> [4, 4, 4] zipWith [4, 5, 3], [6, 5, 4], equals #=> [false, true, false]
zipWith([3, 2, 1], [8, 2, 9], binaryFunction);
Zips together its arguments into a list of lists. Can take any number of arguments, but is not curried.
zipAll [1, 2, 3], [4, 5, 6], [7, 8, 9] #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
zipAll([1, 2], [9, 8]); //=> [[1, 9], [2, 8]]
As zipAll
, but applies the supplied function to the lists and creates a list of the results. The supplied function must take in as many arguments as there are lists being inputed.
zipAllWith [1, 2], [3, 2], [1, 1], (x, y, z) -> x + y + z #=> [5, 5, 5]
zipWith([3, 2, 1], [8, 2, 9], binaryFunction);
Compose takes a series of functions as arguments, and composes them, returning a single function which when called will apply all the functions. Note that compose composes function forwards. It is an alternative to doing (x) -> f4 f3 f2 f1 x
.
f = compose (plus 2), (times 2), minus 2 f 3 #=> 8
var g = compose(f1, f2, f3, f4); g();
Returns the function supplied, curried. Meaning, when the returned function is called with less than its number of arguments, it will return a new, partially applied function. This works on functions with a variable number of arguments as well. Note that curry will always return a function and the function itself is not curried.
curriedPow = curry Math.pow fourToThe = curriedPow 4 fourToThe 2 #=> 16
var add = curry(function(x, y){ return x + y; }); var addFour = add(4); addFour(3); //=> 6
A function which does nothing. It simply returns its argument.
id 5 #=> 5
id('something'); //=> 'something'
Returns a function with the arguments flipped. Works with binary functions.
invertedPower = flip pow invertedPower 2, 3 #=> 9
var divide = function(x, y){ return x / y; }; var divideBy = flip(divide); divideBy(2, 1); //=> 0.5
Fix-point function for anonymous recursion, implemented with the Y combinator.
(fix (fib) -> (n) -> if n <= 1 then 1 else fib(n - 1) + fib(n - 2))(9) #=> 55
fix(function(fib){ return function(n){ if (n <= 1) { return 1; } return fib(n - 1) + fib(n - 2); }; })(9); //=> 55
Splits a string at newlines into a list.
lines '''one two three''' #=> ['one', 'two', 'three']
lines('a'nb''nc''); //=> ['a', 'b', 'c']
Joins a list of strings into a single string using newlines.
unlines ['one', 'two', 'three'] #=> 'one # two # three'
unlines(['a', 'b', 'c']); #=> 'a'nb''nc''
Splits a string at spaces, returning a list of strings.
words 'hello, what is that?' #=> ['hello,', 'what', 'is', 'that?']
words('at the end of the'); //=> ['at', 'the', 'end', 'of', 'the']
Joins a list of strings into a single string using spaces.
unwords ['one', 'two', 'three'] #=> 'one two three'
unwords(['a', 'b', 'c']); //=> 'a b c'
Takes two arguments which can be compared using >
, returns the larger one.
max 3, 1 #=> 3 max 'a', 'c' #=> "c"
max(4, 5); //=> 5 max('d', 'g'); //=> "g"
Takes two arguments which can be compared using >
, returns the smaller one.
min 3, 1 #=> 1 min 'a', 'c' #=> "a"
min(4, 5); //=> 4 min('d', 'g'); //=> "d"
Takes an argument, most often a number, but also anything that can be coerced into a number, eg. '3'
, and returns it as a number, negated.
negate 3 #=> -3 negate -2 #=> 2
negate(-1); //=> 1 negate('5'); //=> -5
Takes a number and returns its absolute value. A number's absolute value is
abs -2 #=> 2 abs 2 #=> 2
negate(-1); //=> 1 negate('5'); //=> -5
Takes a number and returns either -1, 0, or 1 depending on the sign of the number.
signum -5 #=> -1 signum 0 #=> 0 signum 9 #=> 1
signum(-1); //=> -1 signum( 0); //=> 0 signum( 1); //=> 1
Division truncated toward 0.
quot -20, 3 #=> -6
quot(-20, 3); //=> -6
Remainder, like the %
operator.
rem -20, 3 #=> -2
rem(-20, 3); //=> -2
Division truncated down toward negative infinity.
div -20, 3 #=> -7
div(-20, 3); //=> -7
Remainder, modulo, with proper mathematical semantics.
mod -20, 3 #=> 1
mod(20, -3); //=> -1
Returns e to the argument.
exp 1 #=> 2.718281828459045
exp(1); #=> 2.718281828459045
Natural log.
ln 10 #=> 2.302585092994046
ln(10); //=> 2.302585092994046
Power. First raised to the power of the second.
pow -2, 2 #=> 4
pow(4, 2) #=> 16
Number truncated toward 0.
truncate -1.5 #=> -1 truncate 1.5 #=> 1
truncate(-1.8); //=> -1 truncate( 1.2); //=> 1
Number rounded to nearest whole number.
round 0.6 #=> 1 round 0.5 #=> 1 round 0.4 #=> 0
round(-1.3); //=> -1 round(-1.8); //=> -2 round( 9.5); //=> 10