feat(flowRight): implement flowRight (#603)

This commit is contained in:
D-Sketon 2024-09-28 21:56:26 +08:00 committed by GitHub
parent 7eed956ee0
commit 75ed97afa0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 338 additions and 0 deletions

View File

@ -0,0 +1,21 @@
import { bench, describe } from 'vitest';
import { flowRight as flowRightToolkit } from 'es-toolkit';
import { flowRight as flowRightLodash } from 'lodash';
const flowRight = flowRightToolkit;
const flowRightLo = flowRightLodash;
describe('flowRight', () => {
const add = (x: number, y: number) => x + y;
const square = (n: number) => n * n;
bench('es-toolkit/flowRight', () => {
const combined = flowRight(add, square);
combined(1, 2);
});
bench('lodash/flowRight', () => {
const combined = flowRightLo(add, square);
combined(1, 2);
});
});

View File

@ -0,0 +1,50 @@
# flowRight
Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
This method is like [flow](./flow.md), except that it creates a function that invokes the given functions from right to left.
## Signature
```typescript
function flowRight<R>(f: () => R): () => R;
function flowRight<A extends any[], R>(f1: (...args: A) => R): (...args: A) => R;
function flowRight<A extends any[], R1, R2>(f2: (a: R1) => R2, f1: (...args: A) => R1): (...args: A) => R2;
function flowRight<A extends any[], R1, R2, R3>(
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R3;
function flowRight<A extends any[], R1, R2, R3, R4>(
f4: (a: R3) => R4,
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R4;
function flowRight<A extends any[], R1, R2, R3, R4, R5>(
f5: (a: R4) => R5,
f4: (a: R3) => R4,
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R5;
function flowRight(...funcs: Array<(...args: any[]) => any>): (...args: any[]) => any;
```
### Parameters
- `funcs` (`Array<(...args: any[]) => any>`): The functions to invoke.
### Returns
(`(...args: any[]) => any`): The new composite function.
## Examples
```typescript
const add = (x: number, y: number) => x + y;
const square = (n: number) => n * n;
const combined = flowRight(square, add);
console.log(combined(1, 2)); // => 9
```

View File

@ -0,0 +1,50 @@
# flowRight
创建一个函数,该函数返回调用给定函数的结果,并将创建函数的 `this` 绑定传递给这些函数,每次调用时将上一次调用的返回值作为参数传递给下一次调用。
此方法类似于 [flow](./flow.md),但它创建的函数从右到左调用给定的函数。
## 签名
```typescript
function flowRight<R>(f: () => R): () => R;
function flowRight<A extends any[], R>(f1: (...args: A) => R): (...args: A) => R;
function flowRight<A extends any[], R1, R2>(f2: (a: R1) => R2, f1: (...args: A) => R1): (...args: A) => R2;
function flowRight<A extends any[], R1, R2, R3>(
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R3;
function flowRight<A extends any[], R1, R2, R3, R4>(
f4: (a: R3) => R4,
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R4;
function flowRight<A extends any[], R1, R2, R3, R4, R5>(
f5: (a: R4) => R5,
f4: (a: R3) => R4,
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R5;
function flowRight(...funcs: Array<(...args: any[]) => any>): (...args: any[]) => any;
```
### 参数
- `funcs` (`Array<(...args: any[]) => any>`): 需要调用的函数。
### 返回值
(`(...args: any[]) => any`): 新的组合函数。
## 示例
```typescript
const add = (x: number, y: number) => x + y;
const square = (n: number) => n * n;
const combined = flowRight(square, add);
console.log(combined(1, 2)); // => 9
```

View File

@ -0,0 +1,53 @@
import { describe, it, expect } from 'vitest';
import { flowRight } from './flowRight';
import { curry } from '../compat/function/curry';
import { head } from '../array';
import { ary } from './ary';
import { uniq } from '../array';
const add = function (x: number, y: number) {
return x + y;
};
const square = function (n: number) {
return n * n;
};
describe('flowRight', () => {
it(`\`flowRight\` should supply each function with the return value of the previous`, () => {
const fixed = function (n: number) {
return n.toFixed(1);
};
const combined = flowRight(fixed, square, add);
expect(combined(1, 2)).toBe('9.0');
});
it(`\`flowRight\` should return a new function`, () => {
const noop = () => {};
const combined = flowRight(noop);
expect(combined).not.toBe(noop);
});
it(`\`flowRight\` should work with a curried function and \`_.head\``, () => {
const curried = curry((i: any) => i);
const combined = flowRight(curried, head);
expect(combined([1])).toBe(1);
});
it(`\`flowRight\` should work with curried functions with placeholders`, () => {
// TODO change to es-toolkit/compat - map
const map = (array: any[], func: (...args: any[]) => any) => {
return array.map(func);
};
const curried = curry(ary(map, 2), 2);
const getProp = curried(curried.placeholder, (value: { a: any }) => value.a);
const objects = [{ a: 1 }, { a: 2 }, { a: 1 }];
const combined = flowRight(uniq, getProp);
expect(combined(objects)).toEqual([1, 2]);
});
});

163
src/function/flowRight.ts Normal file
View File

@ -0,0 +1,163 @@
import { flow } from './flow.ts';
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {() => R} f The function to invoke.
* @returns {() => R} Returns the new composite function.
*
* @example
* function noArgFunc() {
* return 42;
* }
* const combined = flowRight(noArgFunc);
* console.log(combined()); // 42
*/
export function flowRight<R>(f: () => R): () => R;
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {(...args: A) => R} f1 The function to invoke.
* @returns {(...args: A) => R} Returns the new composite function.
*
* @example
* function oneArgFunc(a: number) {
* return a * 2;
* }
* const combined = flowRight(oneArgFunc);
* console.log(combined(5)); // 10
*/
export function flowRight<A extends any[], R>(f1: (...args: A) => R): (...args: A) => R;
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {(a: R1) => R2} f2 The function to invoke.
* @param {(...args: A) => R1} f1 The function to invoke.
* @returns {(...args: A) => R2} Returns the new composite function.
*
* @example
* const add = (x: number, y: number) => x + y;
* const square = (n: number) => n * n;
*
* const combined = flowRight(square, add);
* console.log(combined(1, 2)); // 9
*/
export function flowRight<A extends any[], R1, R2>(f2: (a: R1) => R2, f1: (...args: A) => R1): (...args: A) => R2;
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {(a: R2) => R3} f3 The function to invoke.
* @param {(a: R1) => R2} f2 The function to invoke.
* @param {(...args: A) => R1} f1 The function to invoke.
* @returns {(...args: A) => R3} Returns the new composite function.
*
* @example
* const add = (x: number, y: number) => x + y;
* const square = (n: number) => n * n;
* const double = (n: number) => n * 2;
*
* const combined = flowRight(double, square, add);
* console.log(combined(1, 2)); // 18
*/
export function flowRight<A extends any[], R1, R2, R3>(
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R3;
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {(a: R3) => R4} f4 The function to invoke.
* @param {(a: R2) => R3} f3 The function to invoke.
* @param {(a: R1) => R2} f2 The function to invoke.
* @param {(...args: A) => R1} f1 The function to invoke.
* @returns {(...args: A) => R4} Returns the new composite function.
*
* @example
* const add = (x: number, y: number) => x + y;
* const square = (n: number) => n * n;
* const double = (n: number) => n * 2;
* const toStr = (n: number) => n.toString();
*
* const combined = flowRight(toStr, double, square, add);
* console.log(combined(1, 2)); // '18'
*/
export function flowRight<A extends any[], R1, R2, R3, R4>(
f4: (a: R3) => R4,
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R4;
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {(a: R4) => R5} f5 The function to invoke.
* @param {(a: R3) => R4} f4 The function to invoke.
* @param {(a: R2) => R3} f3 The function to invoke.
* @param {(a: R1) => R2} f2 The function to invoke.
* @param {(...args: A) => R1} f1 The function to invoke.
* @returns {(...args: A) => R5} Returns the new composite function.
*
* @example
* const add = (x: number, y: number) => x + y;
* const square = (n: number) => n * n;
* const double = (n: number) => n * 2;
* const toStr = (n: number) => n.toString();
* const split = (s: string) => s.split('');
*
* const combined = flowRight(split, toStr, double, square, add);
* console.log(combined(1, 2)); // ['1', '8']
*/
export function flowRight<A extends any[], R1, R2, R3, R4, R5>(
f5: (a: R4) => R5,
f4: (a: R3) => R4,
f3: (a: R2) => R3,
f2: (a: R1) => R2,
f1: (...args: A) => R1
): (...args: A) => R5;
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {(...args: any[]) => any} funcs The functions to invoke.
* @returns {(...args: any[]) => any} Returns the new composite function.
*
* @example
* const add = (x: number, y: number) => x + y;
* const square = (n: number) => n * n;
*
* const combined = flowRight(square, add);
* console.log(combined(1, 2)); // 9
*/
export function flowRight(...funcs: Array<(...args: any[]) => any>): (...args: any[]) => any;
/**
* Creates a function that returns the result of invoking the given functions with the `this` binding of the created function, where each successive invocation is supplied the return value of the previous.
*
* This method is like `flow` except that it creates a function that invokes the given functions from right to left.
*
* @param {(...args: any[]) => any} funcs The functions to invoke.
* @returns {(...args: any[]) => any} Returns the new composite function.
*
* @example
* const add = (x: number, y: number) => x + y;
* const square = (n: number) => n * n;
*
* const combined = flowRight(square, add);
* console.log(combined(1, 2)); // 9
*/
export function flowRight(...funcs: Array<(...args: any[]) => any>): (...args: any[]) => any {
return flow(...funcs.reverse());
}

View File

@ -14,3 +14,4 @@ export { rest } from './rest.ts';
export { curry } from './curry.ts';
export { spread } from './spread.ts';
export { flow } from './flow.ts';
export { flowRight } from './flowRight.ts';