Skip to content

Commit

Permalink
implemented takeWhile re reconbot#275
Browse files Browse the repository at this point in the history
  • Loading branch information
wellcaffeinated committed May 4, 2022
1 parent 9c7eb28 commit 9bf8baf
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export { pipeline } from './pipeline'
export { reduce } from './reduce'
export { take, CurriedTakeResult } from './take'
export { takeLast, CurriedTakeLastResult } from './take-last'
export { takeWhile } from './take-while'
export { tap } from './tap'
export { throttle } from './throttle'
export { time, TimeConfig, CurriedTimeResult } from './time'
Expand Down
40 changes: 40 additions & 0 deletions lib/take-while-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { assert } from 'chai'
import { takeWhile } from './'
import { asyncFromArray } from './util-test'

describe('takeWhile', () => {
const isTruthy = (i : any) => !!i
const asyncIsTruthy = async (i : any) => !!i

it('takes iterators while truthy', async () => {
const numbers: number[] = []
for await (const num of takeWhile(isTruthy, [1, 2, null, undefined, 3])) {
numbers.push(num as number)
}
assert.deepEqual(numbers, [1, 2])
})
it('takes async iterators while truthy', async () => {
const numbers: number[] = []
for await (const num of takeWhile(isTruthy, asyncFromArray([1, 2, null, undefined, 3]))) {
numbers.push(num as number)
}
assert.deepEqual(numbers, [1, 2])
})
it('async filters iterators', async () => {
const numbers: number[] = []
for await (const num of takeWhile(asyncIsTruthy, [1, 2, null, undefined, 3])) {
numbers.push(num as number)
}
assert.deepEqual(numbers, [1, 2])
})

it('is curryable', async () => {
const numbers: number[] = []
const values = asyncFromArray([1, 2, null, 3])
const untilFalsy = takeWhile(isTruthy)
for await (const num of untilFalsy(values)) {
numbers.push(num as number)
}
assert.deepEqual(numbers, [1, 2])
})
})
45 changes: 45 additions & 0 deletions lib/take-while.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { AnyIterable } from './types'

async function* _takeWhile<T>(predicate: (data: T) => boolean | Promise<boolean>, iterable: AnyIterable<T>) {
for await (const data of iterable) {
if (!await predicate(data)) {
return
}
yield data
}
}

/**
* Takes a `predicate` and a `iterable`, and returns a new async iterator of the same type containing the members of the given iterable until the `predicate` returns false.
```ts
import { takeWhile } from 'streaming-iterables'
import { getPokemon } from 'iterable-pokedex'
const firstSlowOnes = takeWhile(pokemon => pokemon.baseStats.speed < 100)
for await (const pokemon of firstSlowOnes(getPokemon())) {
console.log(pokemon)
}
// Abomasnow
// Abra
// Absol
```
*/
export function takeWhile<T, S extends T>(
predicate: (data: T) => data is S
): <A extends T>(curriedIterable: AnyIterable<A>) => AsyncGenerator<S>
export function takeWhile<T>(
predicate: (data: T) => boolean | Promise<boolean>
): <A>(curriedIterable: AnyIterable<A>) => AsyncGenerator<A>
export function takeWhile<T, S extends T>(predicate: (data: T) => data is S, iterable: AnyIterable<T>): AsyncGenerator<S>
export function takeWhile<T>(
predicate: (data: T) => boolean | Promise<boolean>,
iterable: AnyIterable<T>
): AsyncGenerator<T>
export function takeWhile<T>(predicate: (data: T) => boolean | Promise<boolean>, iterable?: AnyIterable<T>) {
if (iterable === undefined) {
return (curriedIterable: AnyIterable<any>) => _takeWhile(predicate, curriedIterable)
}
return _takeWhile(predicate, iterable)
}

0 comments on commit 9bf8baf

Please sign in to comment.