-
Notifications
You must be signed in to change notification settings - Fork 633
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
05b6d7e
commit 3d67ed4
Showing
6 changed files
with
495 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// deno-lint-ignore no-explicit-any | ||
type AnyFunction = (...args: any[]) => any; | ||
|
||
type Curried1Function<T, P1> = { | ||
(p1: P1): T; | ||
}; | ||
type Curried2Function<T, P1, P2> = { | ||
(p1: P1): Curried1Function<T, P2>; | ||
(p1: P1, p2: P2): T; | ||
}; | ||
type Curried3Function<T, P1, P2, P3> = { | ||
(p1: P1): Curried2Function<P2, P3, T>; | ||
(p1: P1, p2: P2): Curried1Function<T, P3>; | ||
(p1: P1, p2: P2, p3: P3): T; | ||
}; | ||
type Curried4Function<T, P1, P2, P3, P4> = { | ||
(p1: P1): Curried3Function<P2, P3, P4, T>; | ||
(p1: P1, p2: P2): Curried2Function<T, P3, P2>; | ||
(p1: P1, p2: P2, p3: P3): Curried1Function<T, P4>; | ||
(p1: P1, p2: P2, p3: P3, p4: P4): T; | ||
}; | ||
|
||
/** | ||
* A function that returns a curried version of a given function | ||
* | ||
* @param {(p1: P1, p2: P2, … pn: Pn) => T} fn - The function to be curried. | ||
* @returns - A function which can be provided with only some of the arguments of the given function at each invocation, once all arguments have been provided the given function is called. | ||
* @example Usage | ||
* function add(a: number, b: number, c: number) { | ||
* return a + b + c + d; | ||
* } | ||
* | ||
* const curriedAdd = curry(add); | ||
* console.log(curriedAdd(1)(2)(3)); // 6 | ||
* console.log(curriedAdd(1, 2)(3)); // 6 | ||
* console.log(curriedAdd(1, 2, 3)); // 6 | ||
*/ | ||
|
||
export function curry<T>( | ||
fn: () => T, | ||
): () => T; | ||
export function curry<T, P1>( | ||
fn: (p1: P1) => T, | ||
): (p1: P1) => T; | ||
export function curry<T, P1, P2>( | ||
fn: (p1: P1, p2: P2) => T, | ||
): Curried2Function<T, P1, P2>; | ||
export function curry<T, P1, P2, P3>( | ||
fn: (p1: P1, p2: P2, p3: P3) => T, | ||
): Curried3Function<T, P1, P2, P3>; | ||
export function curry<T, P1, P2, P3, P4>( | ||
fn: (p1: P1, p2: P2, p3: P3, p4: P4) => T, | ||
): Curried4Function<T, P1, P2, P3, P4>; | ||
export function curry(fn: AnyFunction) { | ||
return function curried(...args: any[]): any { | ||
if (args.length >= fn.length) { | ||
return fn(...args); | ||
} else { | ||
return (...moreArgs: any[]) => curried(...args, ...moreArgs); | ||
} | ||
}; | ||
} | ||
|
||
function add(a: number, b: number, c: number, d: number) { | ||
return a + b + c + d; | ||
} | ||
|
||
const curriedAdd = curry(add); | ||
|
||
if (import.meta.main) { | ||
const fnn = curriedAdd(1, 2); | ||
console.log(curriedAdd(1)(2)(3)(4)); | ||
console.log(curriedAdd(1, 2)(3)(4)); | ||
console.log(curriedAdd(1, 2, 3)(4)); | ||
console.log(curriedAdd(1, 2, 3, 4)); | ||
console.log(curriedAdd(1, 2, 3, 4)); | ||
} |
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,9 @@ | ||
{ | ||
"name": "@std/functions", | ||
"version": "0.1.0", | ||
"exports": { | ||
".": "./mod.ts", | ||
"./curry": "./curry.ts", | ||
"./pipe": "./pipe.ts" | ||
} | ||
} |
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,32 @@ | ||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
|
||
/** | ||
* Pure functions for common tasks around collection types like arrays and | ||
* objects. | ||
* | ||
* Inspired by | ||
* {@link https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/ | Kotlin's Collections} | ||
* package and {@link https://lodash.com/ | Lodash}. | ||
* | ||
* ```ts | ||
* import { intersect, sample, pick } from "@std/collections"; | ||
* import { assertEquals, assertArrayIncludes } from "@std/assert"; | ||
* | ||
* const lisaInterests = ["Cooking", "Music", "Hiking"]; | ||
* const kimInterests = ["Music", "Tennis", "Cooking"]; | ||
* | ||
* assertEquals(intersect(lisaInterests, kimInterests), ["Cooking", "Music"]); | ||
* | ||
* assertArrayIncludes(lisaInterests, [sample(lisaInterests)]); | ||
* | ||
* const cat = { name: "Lulu", age: 3, breed: "Ragdoll" }; | ||
* | ||
* assertEquals(pick(cat, ["name", "breed"]), { name: "Lulu", breed: "Ragdoll"}); | ||
* ``` | ||
* | ||
* @module | ||
*/ | ||
|
||
export * from "./curry.ts"; | ||
export * from "./pipe.ts"; |
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,31 @@ | ||
// deno-lint-ignore-file no-explicit-any | ||
type AnyFunc = (...arg: any) => any; | ||
|
||
type LastFnReturnType<F extends Array<AnyFunc>, Else = never> = F extends [ | ||
...any[], | ||
(...arg: any) => infer R, | ||
] ? R | ||
: Else; | ||
|
||
// inspired by https://dev.to/ecyrbe/how-to-use-advanced-typescript-to-define-a-pipe-function-381h | ||
type PipeArgs<F extends AnyFunc[], Acc extends AnyFunc[] = []> = F extends [ | ||
(...args: infer A) => infer B, | ||
] ? [...Acc, (...args: A) => B] | ||
: F extends [(...args: infer A) => any, ...infer Tail] | ||
? Tail extends [(arg: infer B) => any, ...any[]] | ||
? PipeArgs<Tail, [...Acc, (...args: A) => B]> | ||
: Acc | ||
: Acc; | ||
|
||
export function pipe<FirstFn extends AnyFunc, F extends AnyFunc[]>( | ||
firstFn: FirstFn, | ||
...fns: PipeArgs<F> extends F ? F : PipeArgs<F> | ||
): (arg: Parameters<FirstFn>[0]) => LastFnReturnType<F, ReturnType<FirstFn>> { | ||
return (arg: Parameters<FirstFn>[0]) => | ||
(fns as AnyFunc[]).reduce((acc, fn) => fn(acc), firstFn(arg)); | ||
} | ||
|
||
if (import.meta.main) { | ||
const res = pipe(Math.abs, Math.sqrt, Math.floor); | ||
res(-2); // 1 | ||
} |
Oops, something went wrong.