问题描述
我看到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,我只是想尝试理解不在标准库中包含它的原理。
据我所知,只有两种功能,具有破坏性和建设性。
虽然建设性的功能,顾名思义,构造某种东西,破坏性的东西会破坏某些东西,但不是你现在想象的方式。例如,函数
函数<整数,整数> f =(x,y) - > x + y
是一个建设性的。
因为你需要构建一些东西。在示例
中,您构造了元组(x,y)。构造函数有问题,
无法处理无限参数。但最糟糕的是,你b $ b不能只是让论证开放。您不能只是说好吧,让x:= 1并尝试每次尝试
。每次使用
x:= 1
时,你必须构造整个元组。所以,如果你想看看 y:= 1,y:= 2,y:= 3
的函数返回什么,你
必须写 f(1,1),f(1,2),f(1,3)
。
在Java 8中,应该使用方法引用来处理(大多数情况下)构造函数,因为使用构造型lambda函数没有多大优势。它们有点像静态方法。
你可以使用它们,但它们没有真正的状态。
另一种类型是破坏性的,它需要一些东西并根据需要将其拆除。
例如,破坏性函数
函数<整数,函数<整数,整数> ;> g = x - > (y - > x + y)
与函数相同f
这是建设性的。破坏性函数的好处是,你
现在可以处理无限参数,这对于流来说特别方便,你可以让参数保持打开状态。
所以如果你想再看看结果如果 x:= 1
和 y:= 1,y:= 2,y:= 3
,你可以说 h = g(1)
和
h(1 )
是 y:= 1
的结果, h(2)
y:= 2
和 h(3)
y:= 3
。
所以这里你有一个固定状态!这是非常有活力的,而且大部分时间我们都想要一个lambda。
如果你可以放入一个功能,那么像Factory这样的模式就容易多了为你工作。
破坏性的很容易相互结合。如果类型合适,您可以根据自己的喜好组合它们。使用它,您可以轻松定义使(使用不可变值)测试更容易的态射!
你也可以用建设性的方式做到这一点,但破坏性的组合看起来更好,更像是一个列表或装饰,而建设性的看起来很像一棵树。像使用建设性功能回溯
这样的事情并不好。你可以保存破坏性的部分功能(动态编程),而在回溯中只使用旧的破坏性功能。这使得代码更小,更易读。使用建设性功能,您或多或少地记住所有参数,这可能很多。
那么为什么需要 BiFunction
应该比没有<$ c $的原因更有问题c> TriFunction ?
首先,很多时候你只有一些值(少于3个)并且只需要一个结果因此根本不需要正常的破坏性功能,建设性的功能会很好。还有像monad这样的东西,
真的需要一个建设性的功能。但除此之外,根本没有很多充分理由说明为什么会有 BiFunction
。这并不意味着它应该被删除!我为我的Monads而战直到我死!
因此,如果你有很多参数,你不能把它们组合成一个逻辑容器类,如果你需要
函数是建设性的,使用方法参考。否则尝试使用新获得的破坏性函数的能力,你可能会发现自己用很少的代码行做很多事情。
I see java.util.function.BiFunction, so I can do this:
BiFunction<Integer, Integer, Integer> f = (x, y) -> { return 0; };
What if that is not good enough and I need TriFunction? It doesn't exist!
TriFunction<Integer, Integer, Integer, Integer> f = (x, y, z) -> { return 0; };
I guess I should add that I know I can define my own TriFunction, I'm just trying to understand the rationale behind not including it in the standard library.
As far as I know, there are only two kinds of functions, destructive and constructive.
While constructive function, as the name implies, constructs something, a destructive one destroys something, but not in the way you may think now.
For example, the function
Function<Integer,Integer> f = (x,y) -> x + y
is a constructive one.As you need to construct something. In the exampleyou constructed the tuple (x,y). Constructive functions have the problem,of being not able to handle infinite arguments. But the worst thing is, youcan't just leave an argument open. You can't just say "well, let x := 1" and try outevery y you may like to try. You have to construct every time the whole tuple withx := 1
. So if you like to see what the functions return for y := 1, y := 2, y := 3
youhave to write f(1,1) , f(1,2) , f(1,3)
.
In Java 8, constructive functions should be handled (most of the time) by using method references because there's not much advantage of using a constructive lambda function. They are a bit like static methods.You can use them, but they have no real state.
The other type is the destructive one, it takes something and dismantles it as far as needed.For example, the destructive function
Function<Integer, Function<Integer, Integer>> g = x -> (y -> x + y)
does the same as the function f
which was constructive. The benefits of a destructive function are, youcan handle now infinite arguments, which is especially convenient for streams, and you can just leave arguments open.So if you again want to see what would the result be like if x := 1
and y := 1 , y := 2 , y := 3
, you can say h = g(1)
andh(1)
is the result for y := 1
, h(2)
for y := 2
and h(3)
for y := 3
.
So here you have a fixed state! That's quite dynamic and that's most of the time that what we want from a lambda.
Patterns like Factory are a lot easier if you can just put in a function which does the work for you.
Destructive ones are easily combined with each other. If the type is right you can just compose them as you like. Using that, you can easily define morphisms which make (with immutable values) testing a lot easier!
You can do that too with a constructive one, but destructive composition looks nicer and more like a list or a decorator, and the constructive one looks a lot like a tree. And things like backtrackingwith constructive functions are just not nice. You can just save the partial functions of a destructive one (dynamic programming), and on "backtrack" just use the old destructive function. That makes code a lot smaller and better readable. With constructive functions you have more or less to remember all arguments, which can be a lot.
So why is there a need for BiFunction
should be more of question than why there is no TriFunction
?
First of all, a lot of time you just have a few values (less than 3) and need just a result, so a normal destructive function would not be needed at all, a constructive one would do fine. And there are things like monads whichreally needs a constructive function. But aside from that, there are not really a lot of good reasons why there is a BiFunction
at all. Which doesn't mean it should be removed! I fight for my Monads until I die!
So if you have a lot of arguments, which you can't combine into a logical container class, and if you need thefunction to be constructive, use a method reference. Otherwise try to use the new gained ability of destructive functions, you may find yourself doing a lot of things with a lot less code lines.
这篇关于Java 8:java.util.function中的TriFunction(和kin)在哪里?或者替代方案是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!