Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: change reduce behavior, when empty iterable #236

Merged
merged 1 commit into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading