lz

Lazy functional programming

lz

the fastest¹ functional lazy library for JavaScript.

this isn't an FP do-it-all library² -- this is a collection of useful functions for working with lists and text as efficiently as possible.

var three = lz.cycle(['', '', 'fizz'])
var five = lz.cycle(['', '', '', '', 'buzz'])
var fizzbuzz = lz.zipWith(function (ab) { return a + b }, three, five)
 
fizzbuzz.take(5).toArray()
  // Return factorial of 4 
  // note you should use `new` but you don't have to 
  new lz([1, 2, 3, 4]).scanl(function (ab) { return a * b }).at(3)
  lz.range(1, 999)
  .filter(function (n) { return n % 3 === 0 || n % 5 === 0 })
  .foldl(function (ab) { return a + b })

The following functions return this (Object lz)

Lazily removes falsy (undefined, null, "", 0, NaN) values from the list.

[true, false, true, false]
  .lz()
  .compact()
  .take(2)
  .toArray()
// = [true, true] 

Lazily concatenate the list passed in to the current list.

['hello']
  .lz()
  .concat(['laziness'])
  .take(2)
  .toArray()
// = ['hello', 'laziness'] 
 
[1]
  .lz()
  .concat(lz.cycle([2]))
  .take(4)
  .toArray()
/// = [1, 2, 2, 2] 

Generates an infinite loop composed of the elements of the current list.

['Na']
  .lz()
  .cycle()
  .take(10)
  .toString(' ') + ' Batman!'
// = Na Na Na Na Na Na Na Na Na Na Batman! 

Removes the amount provided, starting from the current position, from the collection.

[null, null, 1, 2, 3].lz().drop(2).toArray()
// = [1, 2, 3] 

Drops elements from the collection until the function provided returns false.

[1, 2, 3, 4, 5]
  .lz()
  .dropWhile(function (n) { return n < 4 })
  .toArray()
// = [4, 5] 

Lazily removes elements from the collection if the return value from the function provided is not true.

[{ color: 'red' }, { color: 'blue' }, { color: 'pink' }, { color: 'red' }]
  .lz()
  .filter(function (x) { return x.color === 'red' })
  .toArray()
// = [{ color: 'red' }, { color: 'red' }] 

Flattens a nested Array. If shallow is truthy Array is flattened to a single level.

[[1], [2], [3]].lz().flatten().toArray()
// = [1, 2, 3] 

Returns all the elements from the collection except for the last one.

[1, 2, 3, 4, 5].lz().init().toArray()
// = [1, 2, 3, 4] 

Lazily applies the function provided to each element and replaces the element with the value returned from the function.

['m', 'a', 'p']
  .lz()
  .map(function (a) { return a.toUpperCase() })
  .toArray()
  .join('')
// = 'MAP' 

Similar to a map and a fold. Lazily returns a list of successive reduced values from the left.

[1, 2, 3]
  .lz()
  .scanl(function (ab) { return a + b })
  .toArray()
// = [1, 3, 6] 

Array prototype method.

Extract the elements after the head of a list.

[1, 2, 3, 4, 5].lz().last().toArray()
// = [2, 3, 4, 5] 

Replaces the collection with the amount taken from the current collection.

lz('my name is lz').take(2).toString()
// = 'my' 

Replaces the collection with the values taken from the current collection which when applied to the callback function return true.

[1, 2, 3, 4, 5]
  .lz()
  .takeWhile(function (n) { return n < 4 })
  .toArray()
// = [1, 2, 3] 

Takes the current list and the list passed in and applies the function to each element in both lists generating a new list from the result.

[1, 2]
  .lz()
  .zipWith(function (ab) { return a + b }, [2, 1])
  .toArray()
// = [3, 3] 

These functions return a value.

Applies the function to each element in the collection, returns false if the return value from the function for any of the elements is false, otherwise returns true.

[2, 4, 6, 8, 10]
  .lz()
  .all(function (n) { return n % 2 === 0 })
// = true 

Returns false if any element in the list is falsy, otherwise returns true.

[null].lz().and()
// = false 
 
lz('i am true to you').and()
// = true 

Applies the function to each element in the collection, returns true if the return value from the function for any of the elements is true, otherwise returns false.

[10, 9, 8, 7, 6]
  .lz()
  .any(function (n) { return n === 9 })
// = true 

Returns the element at the index provided. It's zero-based.

lz('chocolate').at(3)
// = 'c' 
 
lz([1, 2, 3]).at(0)
// = 1 

Reduces the list down to a single value from left to right.

[1, 2, 3, 4, 5]
  .lz()
  .foldl(function (ab) { return a + b })
// = 15 

Returns true if the list contains the item provided.

[1, 2, 3, 4, 5]
  .lz()
  .elem(6)
// = false 
 
[null, 0, false, NaN, ]
  .lz()
  .elem(NaN)
// = true 

Extracts the first element of the collection.

lz('first').head()
// = 'f' 

Extracts the last element in the collection.

lz('last').last()
// = 't' 

Returns true if the list is empty or filled with empty values. Otherwise returns false.

[].lz().nil()
// = true 
 
[null, null].lz().nil()
// = true 
 
[false].lz().nil()
// = false 

Returns the largest element in the collection. If a function is provided the callback function will be applied to each element before comparing.

[1, 2, 3].lz().max()
// = 3 

Returns the smallest element in the collection. If a function is provided the callback function will be applied to each element before comparing.

[1, 2, 3].lz().min()
// = 1 

Returns true if any element in the list is truthy, otherwise returns false.

[true, false, true].lz().or()
// = true 

Forceful method which returns an Array. Alias is $().

[1, 2, 3].lz().take(2).toArray()
// = [1, 2] 

Forceful method which returns the result as a String.

lz('Bananas').toString()
// = Bananas 

These functions are part of the lz Object namespace.

Returns a list by applying the function provided to all elements in the list and then concatenating the returned list into the result.

lz.concatMap(function (a) { return [a, a] }, [1, 2, 3])
// = [1, 1, 2, 2, 3, 3] 

See lz.prototype.cycle.

See lz.prototype.flatten.

See lz.prototype.foldl.

Creates an infinite list by applying the function repeatedly to the last element in the list, starting with the number provided.

lz.iterate(function (x) { return x + 1 }, 1).take(5).toArray()
// = [1, 2, 3, 4, 5] 

Convert a string into a list split by lines.

lz.lines('1. One\n2. Two').toArray()
// = ['1. One', '2. Two'] 

See lz.prototype.max.

See lz.prototype.min.

Create a finite or infinite list from a range of numbers.

lz.range(1, Infinity).take(5).toArray()
// = [1, 2, 3, 4, 5] 
 
lz.range(5, 10).toArray()
// = [5, 6, 7, 8, 9, 10] 
 
lz.range(1, 10).filter(function (x) { return x % 3 === 0 }).toArray()
// = [3, 6, 9] 

Creates an infinite list with just a single Number as the value. Same as lz.cycle([Number])

lz.repeat(4).take(7).toArray()
// = [4, 4, 4, 4, 4, 4, 4] 
 
lz.repeat('ya').take(3).toString(' ')
// = 'ya ya ya' 

Creates a finite list with just a single Number as the value. Similar to lz.repeat(Number).take(Number)

lz.replicate(3, 1).toArray()
// = [1, 1, 1] 
 
lz.replicate(1, 3).toArray()
// = [3] 

Convert a string into a list split by words.

lz.lines('My cat is also lazy').toArray()
// = ['My', 'cat', 'is', 'also', 'lazy'] 

See lz.prototype.zipWith.

It's fast-as-fuck™.

I have included benchmarks in the repo so you can run them for yourself.

If you're working with small lists and/or iterating through all elements in a collection then I recommend lo-dash.

If you plan on being lazy or working with infinite lists then this is the right tool for that job.

Your mileage may vary.

MIT