{ throwIteratorFinished } = require './helpers'
ArrayIterator = require './array-iterator'
generatorOf = ( iterable ) -> ->
iterable?() or
iterable.__iterator__?() or
( iterable if typeof iterable.next is 'function' ) or
new ArrayIterator iterable
negationOf = ( predicate ) -> -> not predicate.apply this, arguments
executable = ( object ) ->
if typeof object.call is 'function'
object
else
generatorOf object
identity = (x) -> x
increment = (x) -> x + 1
decrement = (x) -> x - 1
isEven = (x) -> x % 2 is 0
isOdd = (x) -> y = x % 2; y is 1 or y is -1
sum = ->
x = 0; i = 0; while i < arguments.length
x += arguments[i++]
x
multiply = ->
x = 1; i = 0; while i < arguments.length
x *= arguments[i++]
x
iterate = ( fn, seed ) -> ->
value = seed
out = { value, done: no }
next: ->
out.value = value
out.done = no
value = fn value
out
repeat = ( value ) -> ->
out = { value, done: no }
next: -> out
filter = ( predicate, sequence ) -> ->
source = ( executable sequence ).call null
value = undefined
done = no
out = { value, done }
iterator =
next: ->
if done then do throwIteratorFinished else loop
{ value, done } = source.next()
if out.done = done
iterator.next = throwIteratorFinished
out.value = value = undefined
else if predicate value
out.value = value
else continue
return out
remove = ( predicate, sequence ) ->
filter ( negationOf predicate ), sequence
map = ( fn, sequence ) -> ->
source = ( executable sequence ).call null
out = value: undefined, done: no
iterator =
next: ->
do throwIteratorFinished if done
{ value, done } = source.next()
if out.done = done
iterator.next = throwIteratorFinished
out.value = value = undefined
else
out.value = fn value
out
take = ( amount, sequence ) ->
takeWhile ( ( v, i ) -> i < amount ), sequence
takeLast = ( amount, sequence ) ->
takeUntil ( ( v, i ) -> i < amount ), sequence
takeWhile = ( predicate, sequence ) -> ->
source = ( executable sequence ).call null
count = 0
value = undefined
done = no
out = { value, done }
iterator =
next: ->
do throwIteratorFinished if done
{ value, done } = source.next()
if not done and predicate value, count++
out.value = value
out.done = no
else
iterator.next = throwIteratorFinished
out.value = value = undefined
out.done = done = yes
out
takeUntil = ( predicate, sequence ) ->
takeWhile ( negationOf predicate ), sequence
drop = ( amount, sequence ) ->
dropWhile ( ( v, i ) -> i < amount ), sequence
dropLast = ( amount, sequence ) ->
dropUntil ( ( v, i ) -> i < amount ), sequence
dropWhile = ( predicate, sequence ) -> ->
source = ( executable sequence ).call null
count = 0
value = undefined
done = no
while not done and predicate value, count++
{ value, done } = source.next()
out = { value, done }
iterator =
next: ->
do throwIteratorFinished if done
{ value, done } = source.next()
if done
iterator.next = throwIteratorFinished
out.value = value = undefined
out.done = done = yes
else
out.value = value
out.done = no
out
dropUntil = ( predicate, sequence ) ->
dropWhile ( negationOf predicate ), sequence
module.exports = {
negationOf
generatorOf
executable
}
categories =
'value -> value': {
identity
increment
decrement
isEven
isOdd
sum
multiply
}
'value -> sequence': {
iterate
repeat
}
'sequence -> sequence': {
filter
remove
map
take
takeLast
takeWhile
takeUntil
drop
dropLast
dropWhile
dropUntil
}
for categoryName, category of categories
module.exports[ categoryName ] = category
for name, fn of category
module.exports[name] = fn