簡體   English   中英

組合函數如何處理多個參數?

[英]How does compose function work with multiple parameters?

這是我需要改進的“撰寫”功能:

const compose = (fns) => (...args) => fns.reduceRight((args, fn) => [fn(...args)], args)[0];

這是一個的實際實現:

 const compose = (fns) => (...args) => fns.reduceRight((args, fn) => [fn(...args)], args)[0]; const fn = compose([ (x) => x - 8, (x) => x ** 2, (x, y) => (y > 0 ? x + 3 : x - 3), ]); console.log(fn("3", 1)); // 1081 console.log(fn("3", -1)); // -8

這是我的導師提出的改進。

const compose = (fns) => (arg, ...restArgs) => fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);

如果我們在第一次迭代時傳遞像 func(x, [y]) 這樣的參數列表,我仍然不明白我們如何使函數與 [y] 的解壓縮數組一起工作?

我們來分析一下改進后的compose做了什么

compose = (fns) =>
          (arg, ...restArgs) =>
          fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);

當您使用許多函數輸入compose時,您會返回……一個函數。 在你的情況下,你給它一個名字, fn

這個fn函數是什么樣的? 通過簡單的替換,您可以將其視為這樣:

(arg, ...restArgs) => fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);

其中fns === [(x) => x - 8, (x) => x ** 2, (x, y) => (y > 0 ? x + 3 : x - 3)]

所以你可以給這個函數fn提供一些參數,這些參數將與(arg, ...restArgs)進行“模式匹配”; 在您的示例中,當您調用fn("3", 1)arg"3"restArgs[1] (因此...restArgs在逗號后擴展為1 ,因此您會看到fn("3", 1)減少到

fns.reduceRight((acc, func) => func(acc, 1), "3");

由此你看到

  1. 最右邊的函數(x, y) => (y > 0 ? x + 3 : x - 3)使用兩個參數"3"acc的初始值)和1調用,
  2. 結果將作為第一個參數傳遞給中間函數,並調用以下func
  3. 等等,

但關鍵是func的第二個參數,即1 ,只被最右邊的函數使用,而它被傳遞給其他兩個函數但被忽略

結論

函數組合是介於一元函數之間的東西。 將它與具有高於 1 元數的函數一起使用會導致混淆。

例如考慮這兩個函數

square = (x) => x**2;   // unary
plus = (x,y) => x + y;  // binary

你能編曲嗎? 好吧,你可以將它們組合成這樣的函數

sum_and_square = (x,y) => square(plus(x,y));

您在問題底部的compose功能會很順利:

sum_and_square = compose([square, plus]);

但是如果你的兩個函數是這些呢?

apply_twice = (f) => ((x) => f(f(x))); // still unary, technically
plus = (x,y) => x + y;                 // still binary

您的compose將不起作用。

即使,如果函數plus被柯里化,例如,如果它被定義為

plus = (x) => (y) => x + y

那么人們可以考慮將它們組合在一個函數中,其作用如下:

f = (x,y) => apply_twice(plus(x))(y)

這將可預見地產生result(3,4) === 10

您可以將其設為f = compose([apply_twice, plus])

美容改善

此外,我建議進行“裝飾性”更改:使compose接受...fns而不是fns

compose = (...fns)/* I've only added the three dots on this line */ =>
          (arg, ...restArgs) =>
          fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);

並且您將能夠在沒有 groupint 的情況下調用它以將要組合在數組中的函數,例如,您將編寫compose(apply_twice, plus)而不是compose([apply_twice, plus])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM