gpt4 book ai didi

javascript - 我需要帮助了解其余和传播运算符

转载 作者:行者123 更新时间:2023-11-29 16:42:28 28 4
gpt4 key购买 nike

这是代码:

const Pipe = (...fns) => fns.reduce((f,g) => (...args) => g(f(...args)));

所以通过 (...fns) fns 参数变成了一个数组,对吗?在这部分:
 (f,g) => (...args)

args 是从哪里来的?是否有默认的 args 参数?我无法阅读这部分:
(...args) => g(f(...args))

我只是无法用这种嵌套来包裹我的头,而 reduce 在这里所做的事情是如此令人困惑。

最佳答案

您的第一个问题是您正在处理 pipe 的错误实现– 第二个问题是新 JavaScript 中有多种扩展语法,并且(对于初学者)并不总是很清楚在哪里使用哪一种语法

休息参数

一个 rest 参数将提供的参数收集到一个数组中的函数。这取代了旧的 arguments JavaScript 过去的对象

const f = (...xs) =>
xs

console.log(f()) // []
console.log(f(1)) // [1]
console.log(f(1,2)) // [1,2]



传播论据

传播参数允许您将数组(或任何可迭代的)作为参数传播给函数调用。这替换了(几乎所有) Function.prototype.apply 的实例。

const g = (a,b,c) =>
a + b + c

const args = [1,2,3]

console.log(g(...args)) // 6



为什么pipe不好

这不是一个完整的功能 – pipe s 域是 [Function] (函数数组),但如果使用空函数数组,此实现将产生错误( TypeError: Reduce of empty array with no initial value)

这可能不会立即显现出来,但它可能以多种方式出现。最值得注意的是,当要应用的函数列表是在程序的其他地方创建的数组并最终为空时, Pipe灾难性地失败
const foo = Pipe()
foo(1)
// TypeError: Reduce of empty array with no initial value

const funcs = []
Pipe(...funcs) (1)
// TypeError: Reduce of empty array with no initial value

Pipe.apply(null, funcs) (1)
// TypeError: Reduce of empty array with no initial value

Pipe.call(null) (1)
// TypeError: Reduce of empty array with no initial value

重新实现 pipe

这是无数的实现之一,但它应该更容易理解。我们有一种使用 rest 参数和一种使用 spread 参数。最重要的是, pipe 总是 返回一个函数

const pipe = (f,...fs) => x =>
f === undefined ? x : pipe(...fs) (f(x))

const foo = pipe(
x => x + 1,
x => x * 2,
x => x * x,
console.log
)

foo(0) // 4
foo(1) // 16
foo(2) // 36

// empty pipe is ok
const bar = pipe()
console.log(bar(2)) // 2



“但我听说递归很糟糕”

好的,所以如果你要传递数千个函数,你可能会遇到堆栈溢出。在这种情况下,您可以使用堆栈安全的 Array.prototype.reduce (或 reduceRight )就像您原来的帖子一样。

这次不是在 pipe 内做所有事情。 ,我将把问题分解成更小的部分。每个部分都有不同的用途, pipe现在只关心零件如何组合在一起。

const comp = (f,g) => x =>
f(g(x))

const identity = x =>
x

const pipe = (...fs) =>
fs.reduceRight(comp, identity)

const foo = pipe(
x => x + 1,
x => x * 2,
x => x * x,
console.log
)

foo(0) // 4
foo(1) // 16
foo(2) // 36

// empty pipe is ok
const bar = pipe()
console.log(bar(2)) // 2



“我真的只是想了解我帖子中的代码”

好的,让我们逐步了解您的 pipe功能,看看发生了什么。因为 reduce将多次调用 reduce 函数,我将为 args 使用唯一的重命名每一次
// given
const Pipe = (...fns) => fns.reduce((f,g) => (...args) => g(f(...args)));

// evaluate
Pipe(a,b,c,d)

// environment:
fns = [a,b,c,d]

// reduce iteration 1 (renamed `args` to `x`)
(...x) => b(a(...x))

// reduce iteration 2 (renamed `args` to `y`)
(...y) => c((...x) => b(a(...x))(...y))

// reduce iteration 3 (renamed `args` to `z`)
(...z) => d((...y) => c((...x) => b(a(...x))(...y))(...z))

那么当应用该功能时会发生什么?让我们看看当我们应用 Pipe(a,b,c,d) 的结果时有一些论据 Q
// return value of Pipe(a,b,c,d) applied to `Q`
(...z) => d((...y) => c((...x) => b(a(...x))(...y))(...z)) (Q)

// substitute ...z for [Q]
d((...y) => c((...x) => b(a(...x))(...y))(...[Q]))

// spread [Q]
d((...y) => c((...x) => b(a(...x))(...y))(Q))

// substitute ...y for [Q]
d(c((...x) => b(a(...x))(...[Q]))

// spread [Q]
d(c((...x) => b(a(...x))(Q))

// substitute ...x for [Q]
d(c(b(a(...[Q])))

// spread [Q]
d(c(b(a(Q)))

所以,正如我们所料
// run
Pipe(a,b,c,d)(Q)

// evalutes to
d(c(b(a(Q))))

补充阅读

我写了很多关于函数组合的文章。我鼓励你探索其中一些相关的问题/我已经写了很多关于函数组合的文章。我鼓励您探索其中一些相关的问题/答案

如果有的话,您可能会看到 compose 的不同实现。 (或 pipeflow 等)在每个答案中。也许其中之一会与您的更高良心交谈!
  • How to understand curry and function composition using Lodash flow?
  • lodash curry does not work on function returned by flow; lodash FP enough for FP?
  • functional composition of a boolean 'not' function (not a boolean value)
  • How to compose functions of varying arity using Lodash flow?
  • How to reconcile Javascript with currying and function composition
  • 关于javascript - 我需要帮助了解其余和传播运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44275396/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com