Skip to content

Commit

Permalink
side-effect-waits
Browse files Browse the repository at this point in the history
  • Loading branch information
uriva committed Nov 13, 2023
1 parent 79262d7 commit e4bd88e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 11 deletions.
31 changes: 30 additions & 1 deletion src/composition.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { complement, compose, identity, pipe } from "./composition.ts";
import {
complement,
compose,
identity,
pipe,
sideEffect,
} from "./composition.ts";

import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
import { multiply } from "./math.ts";
import { not } from "./operator.ts";
import { wrapPromise } from "./promise.ts";
import { AsyncFunction } from "./typing.ts";
import { sleep } from "./time.ts";

Deno.test("pipe with async functions", async () => {
assertEquals(
Expand Down Expand Up @@ -85,3 +92,25 @@ const _1 = <T, Fn extends (x: T) => number>(f: Fn) => {
// // @ts-expect-error first function does not match second
// pipe((x: number) => x, f);
// };

Deno.test("side effect", () => {
assertEquals(sideEffect((x) => console.log(x))(7), 7);
});

Deno.test("side effect order of runs", async () => {
const runOrder: string[] = [];
const f = async (x: number) => {
await sleep(1);
runOrder.push("f");
return x;
};
const g = async (x: number) => {
await sleep(0);
runOrder.push("g");
return x;
};
// Check it keeps type.
const sideEffectF: typeof f = sideEffect(f);
assertEquals(await pipe(sideEffectF, g)(7), 7);
assertEquals(runOrder, ["f", "g"]);
});
22 changes: 17 additions & 5 deletions src/composition.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { reverse } from "./array.ts";
import { AnyAsync, Func, Last, ReturnTypeUnwrapped } from "./typing.ts";
import {
AnyAsync,
AsyncFunction,
Func,
Last,
ReturnTypeUnwrapped,
} from "./typing.ts";

import { not } from "./operator.ts";
import { reduce } from "./reduce.ts";
import { currentLocation } from "./trace.ts";

type UnaryFn<A, R> = (a: A) => R;
// deno-lint-ignore no-explicit-any
type UnaryFnUntyped = (a: any) => any;
type Arg<F extends Func> = Parameters<F>[0];
// deno-lint-ignore no-explicit-any
type Res<F> = F extends UnaryFn<any, infer R> ? R : never;
Expand Down Expand Up @@ -81,10 +89,14 @@ export const complement = <F extends Func>(
// @ts-expect-error compiler cannot dynamically infer
pipe(f, not);

export const sideEffect = <T>(f: (_: T) => void) => (x: T) => {
f(x);
return x;
};
export const sideEffect =
<F extends UnaryFnUntyped>(f: F) =>
(x: Parameters<F>[0]): F extends AsyncFunction ? Promise<Parameters<F>[0]>
: Parameters<F>[0] => {
const result = f(x);
// @ts-expect-error compiler cannot dynamically infer
return (result instanceof Promise) ? result.then(() => x) : x;
};

export const wrapSideEffect = <Args extends unknown[], Result>(
cleanup: (...args: Args) => void | Promise<void>,
Expand Down
5 changes: 0 additions & 5 deletions src/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ export const sideLogBefore = <F extends Func>(f: F): F => {
}) as F;
};

export const sideLogTable = sideEffect(console.table);
// deno-lint-ignore no-explicit-any
export const logWith = <T>(...x: any[]) =>
sideEffect<T>((y) => console.log(...x, y));

const getTimestampMilliseconds = () => new Date().getTime();

export const timeit = <F extends Func>(
Expand Down

0 comments on commit e4bd88e

Please sign in to comment.