我看到了 java.util.function.BiFunction,所以我可以这样做:
BiFunction<Integer, Integer, Integer> f = (x, y) -> { return 0; };
如果这还不够好,我需要 TriFunction 怎么办?它不存在!
TriFunction<Integer, Integer, Integer, Integer> f = (x, y, z) -> { return 0; };
我想我应该补充一点,我知道我可以定义自己的 TriFunction,我只是想了解不将其包含在标准库中的基本原理。
原文由 Richard Finegan 发布,翻译遵循 CC BY-SA 4.0 许可协议
据我所知,只有两种功能,破坏性和建设性。
顾名思义,建设性功能会构造某些东西,而破坏性功能会破坏某些东西,但不是您现在所想的那样。
例如,函数
是 建设性 的。因为你需要构建一些东西。在示例中,您构造了元组 (x,y) 。构造函数存在无法处理无限参数的问题。但最糟糕的是,你不能就此置之不理。你不能只说“好吧,让 x := 1”然后尝试每一个你可能想尝试的 y。每次都必须使用
x := 1
构造整个元组。因此,如果您想查看函数为y := 1, y := 2, y := 3
返回的内容,您必须编写f(1,1) , f(1,2) , f(1,3)
。在 Java 8 中,构造函数应该(大部分时间)通过使用方法引用来处理,因为使用构造函数 lambda 函数没有太多优势。它们有点像静态方法。您可以使用它们,但它们没有真实状态。
另一种是破坏性的,它会拿走一些东西并根据需要将其拆除。例如, 破坏性 功能
与建设性的功能
f
相同。破坏性函数的好处是,你现在可以处理无限参数,这对流来说特别方便,而且你可以让参数保持打开状态。 So if you again want to see what would the result be like ifx := 1
andy := 1 , y := 2 , y := 3
, you can sayh = g(1)
andh(1)
is the result fory := 1
,h(2)
fory := 2
andh(3)
fory := 3
.所以这里你有一个固定的状态!这是非常动态的,而且大多数时候我们希望从 lambda 中得到什么。
如果您可以放入一个为您完成工作的函数,那么像 Factory 这样的模式会容易得多。
破坏性的很容易相互结合。如果类型正确,您可以随意组合它们。使用它,您可以轻松定义态射,这使得(具有不可变值)测试变得更加容易!
你也可以用建设性的来做到这一点,但破坏性的组合看起来更好,更像一个列表或装饰器,而建设性的看起来很像一棵树。像构造函数回溯这样的事情并不好。您可以只保存破坏性函数(动态编程)的部分函数,然后在“回溯”上只使用旧的破坏性函数。这使得代码更小,可读性更好。使用构造函数,您或多或少可以记住所有参数,这可能很多。
那么为什么需要
BiFunction
比为什么没有TriFunction
更值得怀疑?首先,很多时候你只有几个值(小于 3)并且只需要一个结果,所以根本不需要一个普通的破坏性函数,一个建设性的函数就可以了。还有像 monad 这样的东西确实需要一个建设性的功能。但除此之外,根本没有太多充分的理由说明为什么会有
BiFunction
。这并不意味着它应该被删除!我为我的 Monads 战斗直到我死!所以如果你有很多参数,你不能将它们组合到一个逻辑容器类中,并且如果你需要函数是构造性的,请使用方法引用。否则尝试使用新获得的破坏性函数的能力,您可能会发现自己用更少的代码行做很多事情。