|
4 | 4 |
|
5 | 5 | ## 题目
|
6 | 6 |
|
| 7 | +Given a function `fn`, return a **curried** version of that function. |
| 8 | + |
| 9 | +A **curried** function is a function that accepts fewer or an equal number of parameters as the original function and returns either another **curried** function or the same value the original function would have returned. |
| 10 | + |
| 11 | +In practical terms, if you called the original function like `sum(1,2,3)`, you would call the **curried** version like `csum(1)(2)(3)`, `csum(1)(2,3) `, `csum(1,2)(3)`, or `csum(1,2,3)`. All these methods of calling the **curried** function should return the same value as the original. |
| 12 | + |
| 13 | +**Example 1:** |
| 14 | + |
| 15 | +> Input: |
| 16 | +> |
| 17 | +> fn = function sum(a, b, c) { return a + b + c; } |
| 18 | +> |
| 19 | +> inputs = [[1],[2],[3]] |
| 20 | +> |
| 21 | +> Output: 6 |
| 22 | +> |
| 23 | +> Explanation: |
| 24 | +> |
| 25 | +> The code being executed is: |
| 26 | +> |
| 27 | +> const curriedSum = curry(fn); |
| 28 | +> |
| 29 | +> curriedSum(1)(2)(3) === 6; |
| 30 | +> |
| 31 | +> curriedSum(1)(2)(3) should return the same value as sum(1, 2, 3). |
| 32 | +
|
| 33 | +**Example 2:** |
| 34 | + |
| 35 | +> Input: |
| 36 | +> |
| 37 | +> fn = function sum(a, b, c) { return a + b + c; } |
| 38 | +> |
| 39 | +> inputs = [[1,2],[3]] |
| 40 | +> |
| 41 | +> Output: 6 |
| 42 | +> |
| 43 | +> Explanation: |
| 44 | +> |
| 45 | +> curriedSum(1, 2)(3) should return the same value as sum(1, 2, 3). |
| 46 | +
|
| 47 | +**Example 3:** |
| 48 | + |
| 49 | +> Input: |
| 50 | +> |
| 51 | +> fn = function sum(a, b, c) { return a + b + c; } |
| 52 | +> |
| 53 | +> inputs = [[],[],[1,2,3]] |
| 54 | +> |
| 55 | +> Output: 6 |
| 56 | +> |
| 57 | +> Explanation: |
| 58 | +> |
| 59 | +> You should be able to pass the parameters in any way, including all at once or none at all. |
| 60 | +> |
| 61 | +> curriedSum()()(1, 2, 3) should return the same value as sum(1, 2, 3). |
| 62 | +
|
| 63 | +**Example 4:** |
| 64 | + |
| 65 | +> Input: |
| 66 | +> |
| 67 | +> fn = function life() { return 42; } |
| 68 | +> |
| 69 | +> inputs = [[]] |
| 70 | +> |
| 71 | +> Output: 42 |
| 72 | +> |
| 73 | +> Explanation: |
| 74 | +> |
| 75 | +> currying a function that accepts zero parameters should effectively do nothing. |
| 76 | +> |
| 77 | +> curriedLife() === 42 |
| 78 | +
|
| 79 | +**Constraints:** |
| 80 | + |
| 81 | +- `1 <= inputs.length <= 1000` |
| 82 | +- `0 <= inputs[i][j] <= 10^5` |
| 83 | +- `0 <= fn.length <= 1000` |
| 84 | +- `inputs.flat().length == fn.length` |
| 85 | +- function parameters explicitly defined |
| 86 | +- If `fn.length > 0` then the last array in `inputs` is not empty |
| 87 | +- If `fn.length === 0` then `inputs.length === 1` |
| 88 | + |
| 89 | +## 题目大意 |
| 90 | + |
| 91 | +请你编写一个函数,它接收一个其他的函数,并返回该函数的 **柯里化** 后的形式。 |
| 92 | + |
| 93 | +**柯里化** 函数的定义是接受与原函数相同数量或更少数量的参数,并返回另一个 **柯里化** 后的函数或与原函数相同的值。 |
| 94 | + |
| 95 | +实际上,当你调用原函数,如 `sum(1,2,3)` 时,它将调用 **柯里化** 函数的某个形式,如 `csum(1)(2)(3)`, |
| 96 | +`csum(1)(2,3)`, `csum(1,2)(3)`,或 `csum(1,2,3)` 。所有调用 **柯里化** 函数的方法都应该返回与原始函数相同的值。 |
| 97 | + |
| 98 | +**示例 1:** |
| 99 | + |
| 100 | +> **输入:** |
| 101 | +> |
| 102 | +> fn = function sum(a, b, c) { return a + b + c; } |
| 103 | +> |
| 104 | +> inputs = [[1],[2],[3]] |
| 105 | +> |
| 106 | +> **输出:** 6 |
| 107 | +> |
| 108 | +> **解释:** |
| 109 | +> |
| 110 | +> 执行的代码是: |
| 111 | +> |
| 112 | +> const curriedSum = curry(fn); |
| 113 | +> |
| 114 | +> curriedSum(1)(2)(3) === 6; |
| 115 | +> |
| 116 | +> curriedSum(1)(2)(3) 应该返回像原函数 sum(1, 2, 3) 一样的值。 |
| 117 | +
|
| 118 | +**示例 2:** |
| 119 | + |
| 120 | +> **输入:** |
| 121 | +> |
| 122 | +> fn = function sum(a, b, c) { return a + b + c; } |
| 123 | +> |
| 124 | +> inputs = [[1,2],[3]] |
| 125 | +> |
| 126 | +> **输出:** 6 |
| 127 | +> |
| 128 | +> **解释:** |
| 129 | +> |
| 130 | +> curriedSum(1, 2)(3) 应该返回像原函数 sum(1, 2, 3) 一样的值。 |
| 131 | +
|
| 132 | +**示例 3:** |
| 133 | + |
| 134 | +> **输入:** |
| 135 | +> |
| 136 | +> fn = function sum(a, b, c) { return a + b + c; } |
| 137 | +> |
| 138 | +> inputs = [[],[],[1,2,3]] |
| 139 | +> |
| 140 | +> **输出:** 6 |
| 141 | +> |
| 142 | +> **解释:** |
| 143 | +> |
| 144 | +> 你应该能够以任何方式传递参数,包括一次性传递所有参数或完全不传递参数。 |
| 145 | +> |
| 146 | +> curriedSum()()(1, 2, 3) 应该返回像原函数 sum(1, 2, 3) 一样的值。 |
| 147 | +
|
| 148 | +**示例 4:** |
| 149 | + |
| 150 | +> **输入:** |
| 151 | +> |
| 152 | +> fn = function life() { return 42; } |
| 153 | +> |
| 154 | +> inputs = [[]] |
| 155 | +> |
| 156 | +> **输出:** 42 |
| 157 | +> |
| 158 | +> **解释:** |
| 159 | +> |
| 160 | +> 柯里化一个没有接收参数,没做有效操作的函数。 |
| 161 | +> |
| 162 | +> curriedLife() === 42 |
| 163 | +
|
| 164 | +**提示:** |
| 165 | + |
| 166 | +- `1 <= inputs.length <= 1000` |
| 167 | +- `0 <= inputs[i][j] <= 10^5` |
| 168 | +- `0 <= fn.length <= 1000` |
| 169 | +- `inputs.flat().length == fn.length` |
| 170 | +- `函数参数需要被显式定义` |
| 171 | +- 如果 `fn.length > 0` 则最后一个数组 `inputs` 不为空 |
| 172 | +- 如果 `fn.length === 0` 则 `inputs.length === 1` |
| 173 | + |
7 | 174 | ## 解题思路
|
8 | 175 |
|
9 | 176 | [柯里化(Currying)](https://en.wikipedia.org/wiki/Currying)是一种关于函数的高阶技术,它是指将一个函数从可调用的 `f(a, b, c)` 转换为可调用的 `f(a)(b)(c)`。柯里化不会调用函数,只是对函数进行转换。
|
10 | 177 |
|
11 |
| -#### 柯里化的目的是什么? |
12 |
| - |
13 |
| -可以从一个实际中的例子中,了解柯里化的好处。 |
14 |
| - |
15 |
| -例如,有一个用于格式化和输出信息的日志(logging)函数 `log(date, importance, message)`: |
16 |
| - |
17 |
| -```js |
18 |
| -function log(date, importance, message) { |
19 |
| - alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`); |
20 |
| -} |
21 |
| -``` |
22 |
| - |
23 |
| -将它柯里化: |
24 |
| - |
25 |
| -`log = _.curry(log);` |
26 |
| - |
27 |
| -柯里化之后,`log` 仍正常运行: |
28 |
| - |
29 |
| -`log(new Date(), "DEBUG", "some debug"); // log(a, b, c)` |
30 |
| - |
31 |
| -但是也能以柯里化形式运行: |
32 |
| - |
33 |
| -`log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)` |
34 |
| - |
35 |
| -现在,可以轻松地为当前日志创建便捷函数: |
36 |
| - |
37 |
| -```js |
38 |
| -// logNow 会是带有固定第一个参数的日志的部分应用函数 |
39 |
| -let logNow = log(new Date()); |
40 |
| - |
41 |
| -// 使用它 |
42 |
| -logNow('INFO', 'message'); // [HH:mm] INFO message |
43 |
| -``` |
44 |
| - |
45 |
| -现在,`logNow` 是具有固定第一个参数的 `log`,换句话说,就是更简短的“部分应用函数(partially applied function)”或“部分函数(partial)”。 |
46 |
| - |
47 |
| -可以更进一步,为当前的调试日志(debug log)提供便捷函数: |
48 |
| - |
49 |
| -```js |
50 |
| -let debugNow = logNow('DEBUG'); |
51 |
| - |
52 |
| -debugNow('message'); // [HH:mm] DEBUG message |
53 |
| -``` |
54 |
| - |
55 |
| -因此,柯里化让我们能够更容易地获取部分应用函数。就像在日志记录示例中看到的那样,普通函数 `log(date, importance, message)` 在被柯里化之后,当调用它的时候传入一个参数(如 `log(date)`)或两个参数(`log(date, importance)`)时,它会返回部分应用函数。 |
56 |
| - |
57 |
| -#### 实现柯里化函数的思路 |
| 178 | +实现柯里化函数的思路如下: |
58 | 179 |
|
59 | 180 | 1. **函数参数处理**:
|
60 | 181 |
|
|
0 commit comments