为什么 - 在Java 1.8中 - 使用函数<v,r>而不是函数<r,v>?</r,v> </v,r>

时间:2013-11-01 12:52:19

标签: java generics functional-programming java-8

订单看起来很奇怪,因为在常规Java中,始终首先指定返回类型。如:

public static double sum(Iterable<Number> nums) { ... }

为什么然后在Function和BiFunction类中做出选择以反过来指定它们?如:

interface Function<T,R>
interface BiFunction<T,U,R>

我不是在这里征求关于哪个更好的意见,但具体来说是:

a)在优先考虑一个订单而不是另一个订单时,是否有任何技术或其他(非风格)的好处?或者它是一个随意的选择?

b)是否有人知道任何文件说明或权威来源的任何陈述理由,为什么选择了另一个?

除此之外:如果延伸到更高的城市,这个命令似乎更奇怪。例如,一个假设的QuadFunction:

interface QuadFunction<A,B,C,D,R> { ... }

(在撰写本文时,图书馆中的最高版本是2 - 即BiFunction。)

请参阅:http://download.java.net/jdk8/docs/api/java/util/function/package-summary.html

5 个答案:

答案 0 :(得分:13)

与先前现有的符号一致。

数学整数除法函数扩展为有理数:

(\): I x I -> Q

上面的函数式编程版本(如Haskell,Ocaml)

division :: Integer -> (Integer -> Rational)

or

division :: Integer -> Integer -> Rational

所有三个人都说“分割函数需要两个整数并返回一个有理数”。在功能范例中,它首先要说明你的回报。 C告诉我们“我们在除法函数中返回一个有理数,它取两个整数”(ex float division(int a,int b){})。

在Java中,你的返回类型位于方法的左边,因为Java想要看起来像C. C的设计者认为“int main(int argv,char * argv [])”看起来比“main(int argv)好” ,char * argv [])int“。在编写代码时,至少对我而言,在知道它需要什么之前,我经常会知道什么方法会返回。 (编辑1:我们写了像String s = removeSpaces(textLine)这样的行,所以左边的返回符合左边的变量)

在C#中,func看起来与Java 8函数相同。

答案 1 :(得分:6)

我的猜测是方法链更直观,这可能是lambdas的一个典型用例,即

IntStream.range(1, 10).map(Ints::random).filter(x -> x % 2 == 0)

所以,这里的方法序列从左到右读,lambdas从左到右。那么为什么不让类型参数从左到右?

进一步升级 - 原因可能是英语从左到右阅读。 : - )

<强>更新

我很惊讶地发现这是maths modern arabic notation发生的事情:

拉丁文复数

latin complex numbers

阿拉伯语复数

arabic complex numbers

在这个例子中,每个字母中的阿拉伯符号都反映了拉丁语。可以通过角度符号和 i (imagenary unit)char来跟踪它 - 在两种情况下它都有一个点。在链接的wiki文章中,还有一个反向lim箭头的示例(与Java 8 lamda的箭头方向相比)。这可能意味着阿拉伯语Java,如果它被开发出来,会看起来有点不同。 : - )

免责声明:我有数学背景,但在回答这个问题时我不知道阿拉伯语符号。

答案 2 :(得分:4)

在普通的程序和OO编程中,函数/方法通常采用参数列表并返回一些结果:

int max(int num1, int num2)

当将函数签名重写为基于回调的(例如并行或异步处理)时,通过将返回回调作为最后一个参数附加来转换签名是一种长期的做法:

void maxAsync(int num1, int num2, Callback<int> callback) // pseudo-Java

此模式的当前示例可在GWT RPC processing中找到。

这种风格起源于所谓的continuation-passing style的Lisp语言风格,其中函数通过将函数传递给函数作为参数来链接。因为在Lisp中,参数是从左到右计算的,所以消耗值的函数需要位于列表的末尾。这种安排已经被命令式语言用于连续性,并且因为在参数列表的末尾添加额外的可选参数(布尔标志等)是传统的。

答案 3 :(得分:4)

明确的意图是使用Java编写功能样式更方便。现在,在数学中,函数通常写成

f: A -> B

(即,从As到Bs的函数)。这也与函数语言,Scala和已有的Java函数库中的符号相对应。

换句话说:这是正确的事情。

请注意,功能接口不是方法,方法不是功能接口,因此不清楚前者的语法与后者有什么关系。

答案 4 :(得分:0)

我的意见:看起来和番石榴中的Function一样。反过来接受命令会引起很多困惑。

http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Function.html