Skip to content

Commit

Permalink
feat: change reduce behavior, when empty iterable (#236)
Browse files Browse the repository at this point in the history
  • Loading branch information
ppeeou committed Oct 21, 2023
1 parent 6d42931 commit 469e7df
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 19 deletions.
14 changes: 12 additions & 2 deletions src/every.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ function every<
return pipe(
map(f, iterable),
takeUntil(not),
reduce((a, b) => a && b),
(acc) =>
reduce(
(a: boolean, b: boolean) => a && b,
true,
acc as Iterable<boolean>,
),
(a) => a ?? true,
Boolean,
);
Expand All @@ -68,7 +73,12 @@ function every<
return pipe(
map(f, iterable),
takeUntil(not),
reduce((a, b) => a && b),
(acc) =>
reduce(
(a: boolean, b: boolean) => a && b,
true,
acc as AsyncIterable<boolean>,
),
(a) => a ?? true,
Boolean,
);
Expand Down
12 changes: 10 additions & 2 deletions src/join.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ type ReturnJoinType<T extends Iterable<unknown> | AsyncIterable<unknown>> =
: never;

function sync<A>(sep: string, iterable: Iterable<A>) {
const res = reduce((a: string, b) => `${a}${sep}${b}`, iterable);
const res = reduce(
(a: string, b) => (a == "" ? `${b}` : `${a}${sep}${b}`),
"",
iterable,
);
if (res == null) {
return "";
}
Expand All @@ -19,7 +23,11 @@ function sync<A>(sep: string, iterable: Iterable<A>) {
}

function async<A>(sep: string, iterable: AsyncIterable<A>) {
return reduce((a: string, b) => `${a}${sep}${b}`, iterable).then((res) => {
return reduce(
(a: string, b) => (a == "" ? `${b}` : `${a}${sep}${b}`),
"",
iterable,
).then((res) => {
if (res == null) {
return "";
}
Expand Down
15 changes: 6 additions & 9 deletions src/reduce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ async function async<A, B>(
* {@link https://fxts.dev/docs/map | map}, {@link https://fxts.dev/docs/filter | filter}
*/

function reduce<A extends readonly []>(f: Arrow, iterable: A): undefined;

function reduce<A extends readonly [], B>(f: Arrow, seed: B, iterable: A): B;

function reduce<A>(f: (a: A, b: A) => A, iterable: Iterable<A>): A;
Expand Down Expand Up @@ -113,11 +111,7 @@ function reduce<A extends Iterable<unknown> | AsyncIterable<unknown>, B>(
f: (a: B, b: IterableInfer<A>) => B,
seed?: B | Iterable<IterableInfer<A>> | AsyncIterable<IterableInfer<A>>,
iterable?: Iterable<IterableInfer<A>> | AsyncIterable<IterableInfer<A>>,
):
| B
| undefined
| Promise<B | undefined>
| ((iterable: A) => ReturnValueType<A, B>) {
): B | Promise<B> | ((iterable: A) => ReturnValueType<A, B>) {
if (iterable === undefined) {
if (seed === undefined) {
return (iterable: A) =>
Expand All @@ -128,7 +122,7 @@ function reduce<A extends Iterable<unknown> | AsyncIterable<unknown>, B>(
const iterator = seed[Symbol.iterator]();
const { done, value } = iterator.next();
if (done) {
return undefined;
throw new TypeError("'reduce' of empty iterable with no initial value");
}
return sync(f, value as B, {
[Symbol.iterator]() {
Expand All @@ -141,8 +135,11 @@ function reduce<A extends Iterable<unknown> | AsyncIterable<unknown>, B>(
const iterator = seed[Symbol.asyncIterator]();
return iterator.next().then(({ done, value }) => {
if (done) {
return undefined;
throw new TypeError(
"'reduce' of empty iterable with no initial value",
);
}

return async(f, value as Promise<B>, {
[Symbol.asyncIterator]() {
return iterator;
Expand Down
14 changes: 12 additions & 2 deletions src/some.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ function some<
return pipe(
map(f, iterable),
takeUntil(identity),
reduce((a, b) => a || b),
(acc) =>
reduce(
(a: boolean, b: boolean) => a || b,
false,
acc as Iterable<boolean>,
),
Boolean,
);
}
Expand All @@ -87,7 +92,12 @@ function some<
return pipe(
map(f, iterable),
takeUntil(identity),
reduce((a, b) => a || b),
(acc) =>
reduce(
(a: boolean, b: boolean) => a || b,
false,
acc as AsyncIterable<boolean>,
),
Boolean,
);
}
Expand Down
4 changes: 2 additions & 2 deletions test/reduce.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ describe("reduce", function () {
expect(reduce((a, b) => a + b, "seed", [])).toEqual("seed");
});

it("should return 'undefined' when the given `iterable` is an empty array and initial value is absent", function () {
expect(reduce((a, b) => a + b, [])).toBeUndefined();
it("should be occured error when the given `iterable` is an empty array and initial value is absent", function () {
expect(() => reduce((a) => a, [])).toThrow();
});

it("should work given it is initial value", function () {
Expand Down
4 changes: 2 additions & 2 deletions type-check/reduce.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as Test from "../src/types/Test";

const { checks, check } = Test;

const res1 = reduce((a, b) => a + b, []);
const res1 = reduce((a) => a, []);
const res2 = reduce((a, b) => a + b, "seed", []);
const res3 = reduce((a, b) => a + b, 0, [1, 2, 3]);
const res4 = reduce((a, b) => a + b, [1, 2, 3]);
Expand Down Expand Up @@ -52,7 +52,7 @@ const res16 = pipe(
);

checks([
check<typeof res1, undefined, Test.Pass>(),
check<typeof res1, never, Test.Pass>(),
check<typeof res2, "seed", Test.Pass>(),
check<typeof res3, number, Test.Pass>(),
check<typeof res4, number, Test.Pass>(),
Expand Down

0 comments on commit 469e7df

Please sign in to comment.