-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from jsr-core/add-repeat
feat(repeat): add `repeat` module
- Loading branch information
Showing
14 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* Returns an infinite iterable that repeats through the given iterable. | ||
* | ||
* Use {@linkcode https://jsr.io/@core/iterutil/doc/async/cycle/~/cycle cycle} to cycle the iterable | ||
* Use {@linkcode https://jsr.io/@core/iterutil/doc/repeat/~/repeat repeat} to repeat the iterable synchronously. | ||
* | ||
* @param iterable The iterable to repeat. | ||
* @returns The repeatd iterable. | ||
* | ||
* @example | ||
* ```ts | ||
* import { repeat } from "@core/iterutil/async/repeat"; | ||
* | ||
* const iter = repeat([1, 2, 3], 2); | ||
* console.log(await Array.fromAsync(iter)); // [1, 2, 3, 1, 2, 3] | ||
* ``` | ||
*/ | ||
export function repeat<T>( | ||
iterable: Iterable<T> | AsyncIterable<T>, | ||
n: number, | ||
): AsyncIterable<T> { | ||
if (n < 0 || !Number.isSafeInteger(n)) { | ||
throw new RangeError( | ||
`n must be 0 or positive safe integer, but got ${n}.`, | ||
); | ||
} | ||
if (n === 0) { | ||
return async function* () {}(); | ||
} | ||
return async function* () { | ||
const array = await Array.fromAsync(iterable); | ||
if (array.length === 0) { | ||
return; | ||
} | ||
for (let i = 0; i < n; i++) { | ||
yield* array; | ||
} | ||
}(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { assertEquals, assertThrows } from "@std/assert"; | ||
import { assertType, type IsExact } from "@std/testing/types"; | ||
import { toAsyncIterable } from "./to_async_iterable.ts"; | ||
import { repeat } from "./repeat.ts"; | ||
|
||
Deno.test("repeat", async (t) => { | ||
await t.step("with async iterable", async (t) => { | ||
await t.step("with non empty iterable", async () => { | ||
const result = repeat(toAsyncIterable([0, 1, 2]), 2); | ||
const expected = [0, 1, 2, 0, 1, 2]; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
|
||
await t.step("with single value iterable", async () => { | ||
const result = repeat(toAsyncIterable([0]), 2); | ||
const expected = [0, 0]; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
|
||
await t.step("with empty iterable", async () => { | ||
const result = repeat(toAsyncIterable([] as number[]), 2); | ||
const expected: number[] = []; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
}); | ||
|
||
await t.step("with iterable", async (t) => { | ||
await t.step("with non empty iterable", async () => { | ||
const result = repeat([0, 1, 2], 2); | ||
const expected = [0, 1, 2, 0, 1, 2]; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
|
||
await t.step("with single value iterable", async () => { | ||
const result = repeat([0], 2); | ||
const expected = [0, 0]; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
|
||
await t.step("with empty iterable", async () => { | ||
const result = repeat([] as number[], 2); | ||
const expected: number[] = []; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
}); | ||
|
||
await t.step("with n=0", async () => { | ||
const result = repeat([0, 1, 2], 0); | ||
const expected: number[] = []; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
|
||
await t.step("throws RangeError", async (t) => { | ||
await t.step("if the limit is not 0 nor positive safe integer", () => { | ||
assertThrows(() => repeat([], NaN), RangeError); | ||
assertThrows(() => repeat([], Infinity), RangeError); | ||
assertThrows(() => repeat([], -Infinity), RangeError); | ||
assertThrows(() => repeat([], -1), RangeError); | ||
assertThrows(() => repeat([], 1.1), RangeError); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { repeat as base } from "@core/iterutil/async/repeat"; | ||
|
||
/** | ||
* An operator to return a function that repeats the elements of an iterable. | ||
* | ||
* See {@linkcode https://jsr.io/@core/iterutil/doc/async/repeat/~/repeat repeat} for native repeat. | ||
* | ||
* @example | ||
* ```ts | ||
* import { pipe } from "@core/pipe"; | ||
* import { repeat } from "@core/iterutil/pipe/async/repeat"; | ||
* | ||
* const iter = pipe( | ||
* [1, 2, 3], | ||
* repeat(2), | ||
* ); | ||
* console.log(await Array.fromAsync(iter)); // [1, 2, 3, 1, 2, 3] | ||
* ``` | ||
*/ | ||
export function repeat<T>( | ||
n: number, | ||
): (iterable: Iterable<T> | AsyncIterable<T>) => AsyncIterable<T> { | ||
return (iterable: Iterable<T> | AsyncIterable<T>) => base(iterable, n); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { assertEquals } from "@std/assert"; | ||
import { assertType, type IsExact } from "@std/testing/types"; | ||
import { pipe } from "@core/pipe"; | ||
import { repeat } from "./repeat.ts"; | ||
|
||
Deno.test("repeat", async (t) => { | ||
await t.step("usage", async () => { | ||
const result = pipe([0, 1, 2], repeat(2)); | ||
const expected = [0, 1, 2, 0, 1, 2]; | ||
assertEquals(await Array.fromAsync(result), expected); | ||
assertType<IsExact<typeof result, AsyncIterable<number>>>(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { repeat as base } from "@core/iterutil/repeat"; | ||
|
||
/** | ||
* An operator to return a function that repeats the elements of an iterable. | ||
* | ||
* See {@linkcode https://jsr.io/@core/iterutil/doc/repeat/~/repeat repeat} for native repeat. | ||
* | ||
* @example | ||
* ```ts | ||
* import { pipe } from "@core/pipe"; | ||
* import { repeat } from "@core/iterutil/pipe/repeat"; | ||
* | ||
* const iter = pipe( | ||
* [1, 2, 3], | ||
* repeat(2), | ||
* ); | ||
* console.log(Array.from(iter)); // [1, 2, 3, 1, 2, 3] | ||
* ``` | ||
*/ | ||
export function repeat<T>(n: number): (iterable: Iterable<T>) => Iterable<T> { | ||
return (iterable: Iterable<T>) => base(iterable, n); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { assertEquals } from "@std/assert"; | ||
import { assertType, type IsExact } from "@std/testing/types"; | ||
import { pipe } from "@core/pipe"; | ||
import { repeat } from "./repeat.ts"; | ||
|
||
Deno.test("repeat", async (t) => { | ||
await t.step("usage", () => { | ||
const result = pipe([0, 1, 2], repeat(2)); | ||
const expected = [0, 1, 2, 0, 1, 2]; | ||
assertEquals(Array.from(result), expected); | ||
assertType<IsExact<typeof result, Iterable<number>>>(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* Returns a finite iterable that repeats through the given iterable. | ||
* | ||
* Use {@linkcode https://jsr.io/@core/iterutil/doc/cycle/~/cycle cycle} to cycle the iterable. | ||
* Use {@linkcode https://jsr.io/@core/iterutil/doc/async/repeat/~/repeat repeat} to repeat the iterable asynchronously. | ||
* | ||
* @param iterable The iterable to repeat. | ||
* @param n The number of times to repeat the iterable. Must be a safe integer greater than or equal to 0 | ||
* @returns The repeated iterable. | ||
* @throws {RangeError} If `n` is not a safe integer greater than or equal to 0. | ||
* | ||
* @example | ||
* ```ts | ||
* import { repeat } from "@core/iterutil/repeat"; | ||
* | ||
* const iter = repeat([1, 2, 3], 2); | ||
* console.log(Array.from(iter)); // [1, 2, 3, 1, 2, 3] | ||
* ``` | ||
*/ | ||
export function repeat<T>(iterable: Iterable<T>, n: number): Iterable<T> { | ||
if (n < 0 || !Number.isSafeInteger(n)) { | ||
throw new RangeError( | ||
`n must be 0 or positive safe integer, but got ${n}.`, | ||
); | ||
} | ||
if (n === 0) { | ||
return []; | ||
} | ||
return function* () { | ||
const array = Array.from(iterable); | ||
if (array.length === 0) { | ||
return; | ||
} | ||
for (let i = 0; i < n; i++) { | ||
yield* array; | ||
} | ||
}(); | ||
} |
Oops, something went wrong.