Skip to content

Commit

Permalink
feat(partial): add partial tail function
Browse files Browse the repository at this point in the history
  • Loading branch information
TomokiMiyauci committed Jun 5, 2023
1 parent 46ed432 commit 96b1d7b
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 3 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,21 @@ const unary = partialRight(fn, false, 0);
const nullary = partialRight(fn, false, 0, "");
```

### partialTail

Create tail partial applied function.

Tail is any argument other than the first argument.

```ts
import { partialTail } from "https://deno.land/x/curry@$VERSION/mod.ts";

declare const fn: (a: string, b: number, c: boolean) => void;

const binary = partialTail(fn, 0);
const unary = partialTail(fn, 0, false);
```

## API

See [deno doc](https://deno.land/x/curry/mod.ts) for all APIs.
Expand Down
2 changes: 1 addition & 1 deletion mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
// This module is browser compatible.

export { curry } from "./curry.ts";
export { partial, partialRight } from "./partial.ts";
export { partial, partialRight, partialTail } from "./partial.ts";
32 changes: 31 additions & 1 deletion partial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,37 @@ export function partialRight<AX, R>(
...args: AX[]
): (...args: readonly AX[]) => R {
args = args.reverse();
return function (...rest): R {
return function partial(...rest): R {
return fn.apply(null, rest.concat(args));
};
}

/** Create tail partial applied function.
*
* Tail is any argument other than the first argument.
*
* @example
* ```ts
* import { partialTail } from "https://deno.land/x/curry@$VERSION/mod.ts";
*
* declare const fn: (a: string, b: number, c: boolean) => void;
*
* const binary = partialTail(fn, 0);
* const unary = partialTail(fn, 0, false);
* ```
*/
export function partialTail<
H,
T extends readonly unknown[],
U extends readonly unknown[],
R,
>(
fn: (...args: readonly [H, ...T, ...U]) => R,
...tail: T
): (head: H, ...rest: U) => R {
function partial(head: H, ...rest: U): R {
return fn(head, ...tail, ...rest);
}

return partial;
}
84 changes: 83 additions & 1 deletion partial_test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license.

import { partial, partialRight } from "./partial.ts";
import { partial, partialRight, partialTail } from "./partial.ts";
import {
assertEquals,
assertSpyCallArgs,
Expand Down Expand Up @@ -238,3 +238,85 @@ describe("partialRight", () => {
});
});
});

describe("partialTail", () => {
describe("unary", () => {
interface Context {
fn: Fn2Spy<Arity1>;
}
beforeEach<Context>(function () {
this.fn = spy((arg1: string): string => arg1);
});

const arg = "";

it<Context>("should pass 0 argument", function () {
const fn = partialTail(this.fn);

assertEquals(fn(arg), arg);
assertSpyCallArgs(this.fn, 0, [arg]);
});
});

describe("binary", () => {
interface Context {
fn: Fn2Spy<Arity2>;
}
beforeEach<Context>(function () {
this.fn = spy((arg1: string, arg2: number): string => arg1 + arg2);
});

const arg = "";
const arg2 = 0;

it<Context>("should pass 0 argument", function () {
const fn = partialTail(this.fn);

assertEquals(fn(arg, arg2), arg + arg2);
assertSpyCallArgs(this.fn, 0, [arg, arg2]);
});

it<Context>("should pass 1 argument", function () {
const fn = partialTail(this.fn, arg2);

assertEquals(fn(arg), arg + arg2);
assertSpyCallArgs(this.fn, 0, [arg, arg2]);
});
});

describe("ternary", () => {
interface Context {
fn: Fn2Spy<Arity3>;
}
beforeEach<Context>(function () {
this.fn = spy((arg1: string, arg2: number, arg3: boolean): string =>
arg1 + arg2 + arg3
);
});

const arg = "";
const arg2 = 0;
const arg3 = false;

it<Context>("should pass 0 argument", function () {
const fn = partialTail(this.fn);

assertEquals(fn(arg, arg2, arg3), arg + arg2 + arg3);
assertSpyCallArgs(this.fn, 0, [arg, arg2, arg3]);
});

it<Context>("should pass 1 argument", function () {
const fn = partialTail(this.fn, arg2);

assertEquals(fn(arg, arg3), arg + arg2 + arg3);
assertSpyCallArgs(this.fn, 0, [arg, arg2, arg3]);
});

it<Context>("should pass 2 argument", function () {
const fn = partialTail(this.fn, arg2, arg3);

assertEquals(fn(arg), arg + arg2 + arg3);
assertSpyCallArgs(this.fn, 0, [arg, arg2, arg3]);
});
});
});

0 comments on commit 96b1d7b

Please sign in to comment.