函数分解Vs Currying Vs部分应用



Currying、部分应用和函数分解是相同的概念吗?它们之间有什么区别吗?

我在读这些,我发现这些都是一样的。我不明白他们之间是否有什么区别。既然可以一次性将所有参数传递给单个方法,为什么要在java中编写这样的代码

Function<Integer,Function<Integer,Function<Integer, Integer> > > 
triadder = u -> w -> v -> u + w + v; 
// Calling the curried functions 
// Calling Curried Function for Adding u, v & w 
System.out.println("Add 2, 3, 4 :"
+ triadder 
.apply(2) 
.apply(3) 
.apply(4));

Java不太适合这种方法。其他语言使它更容易。在Java中,面向对象是最好的选择,只有在真正需要的特定情况下,函数编程的思想才会为它锦上添花。

"部分应用"是一个比currying更通用的概念。这意味着给出一个函数,该函数在其闭包中保存一些数据——调用者提供另一个参数。

这可以比作一个Java对象,它"捕获"一个字段,然后提供一个使用该字段和另一个参数的方法。

更具体地说,"Currying"将多参数函数重新构造为一个参数的函数。这是通过捕获除一个参数外的所有参数来完成的,将其他参数留给以后的调用。

"函数分解"是将复杂过程分解为简单函数的分析,相当于面向对象设计的函数编程。

除了@JoshuaFox的答案外,关于为什么不一次性传递所有参数的另一个问题的一个答案是,它经常使代码重复,并可能在不真正需要的地方添加大量样板。

我有一个用F#编写的小型网络应用程序,可以在几个不同的平台上运行。我有一个配置文件,为每个特定平台提供值。在运行时,我从配置文件中获得这些值,并具有如下函数:

let private supptFunc (p1: string) (p2: string) (p3: string) : string = ...
...
// Partially apply parameters from config file to create a simpler
// function in the rest of the code
let externaFn1 = supptFunc (<get v1 from config file>) (<get v2 from config file>)

这使得externalFn1成为一个接受字符串并返回字符串的函数。因此,在我的代码的其余部分中,我只使用从请求中获得的单个参数(p3(调用externaFn1

通过这种方式,我根据完成工作所需的参数来实现supptFunc,并且从不担心它们来自哪里。我不必在代码中读取配置文件,也不必将值存储在列表或映射中。他们总是被传进来。

但我不必在可能需要函数的地方提供这些值。我只是创建了一个有用的函数,将其公开给我的代码的其余部分,该函数为当前平台"烘焙"了这些值。代码库的所有其余部分只使用公开的函数,只使用它们所拥有和需要的参数。

因此,现在我可以将supportFunc测试为一个函数,总是获取它所需的所有参数,并可以在测试时提供我想要的任何参数,以检查它在我选择的任何情况下的行为。但我并不要求所有来电者都提供supportFunc所需的一切,因为他们不一定有责任掌握所有这些信息。

这不是部分应用程序的唯一用例,但F#自动咖喱函数的事实使它成为保持代码更干净、更简单的简单方法。

最新更新