6

通常の 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

4

5 に答える 5

13

これは、以前の既存の表記法と一致することです。

有理数に拡張された数学的整数除算関数:

(\): I x I -> Q

上記の関数型プログラミング バージョン (Haskell、Ocaml など)

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

or

division :: Integer -> Integer -> Rational

3つすべてが「除算関数は2つの整数を取り、有理数を返す」と言います。機能的なパラダイムでは、リターンを最初に言うのは逆です。C は、「2 つの整数を取る除算関数で有理数を返す」と言うように教えてくれました (例: 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 Function と同じように見えます。

于 2013-11-01T13:14:05.180 に答える
6

私の推測では、ラムダの典型的なユースケースであるメソッドチェーンの方が直感的であると思います。

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

したがって、ここでのメソッド シーケンスは左から右に読み取り、ラムダは左から右に読み取ります。では、型パラメータを左から右にしないのはなぜですか?

これをもう少しエスカレートします - その理由は、英語が左から右に読むためかもしれません。:-)

アップデート

これが数学の現代アラビア語表記法で起こっていることを知って、私は非常に驚きました:

ラテン複素数

ラテン複素数

アラビア複素数

アラビア複素数

この例では、すべての文字のアラビア語表記がラテン語を反映しています。これは、角度記号とi (画像単位) 文字で追跡できます。どちらの場合も、ドットがあります。リンクされた wiki 記事には、逆向きの矢印の例もありますlim(Java 8 ラムダの矢印の方向と比較して)。これは、アラビア語のJavaが開発された場合、少し異なって見えることを意味する可能性があります. :-)

免責事項: 私は数学のバックグラウンドを持っていますが、この質問に答えていたときにアラビア語の表記法がわかりませんでした.

于 2013-11-01T13:17:36.840 に答える
4

通常の手続き型および OO プログラミングでは、関数/メソッドは通常、パラメーターのリストを取り、何らかの結果を返します。

int max(int num1, int num2)

関数シグネチャをコールバックベース (並列または非同期処理など) として書き換える場合、最後のパラメーターとしてリターン コールバックを追加してシグネチャを変換するのが長年の慣行でした。

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

このパターンの現在の例は、GWT RPC 処理にあります。

このスタイルは、関数をパラメーターとして関数に渡すことによって関数が連鎖される、いわゆる継続渡しスタイルを持つ言語の Lisp スタイルに由来します。Lisp では引数は左から右に評価されるため、値を消費する関数はリストの最後にある必要があります。この配置は、継続性のために命令型言語で採用されています。これは、パラメーター リストの最後に追加のオプション パラメーター (ブール値フラグなど) を追加することが伝統的であったためです。

于 2013-11-01T13:05:17.547 に答える
4

Java での関数型スタイルでのプログラミングをより便利にするという明確な意図があります。さて、数学では、関数は一般的に次のように書かれます

f: A -> B

(つまり、As から Bs への関数)。これは、関数型言語、Scala、および既存の Java の関数型ライブラリでの表記にも対応しています。

言い換えれば、それはまさに正しいことです。

機能的インターフェースはメソッドではなく、メソッドは機能的インターフェースではないことに注意してください。したがって、前者の構文が後者とどのような関係があるかは明確ではありません。

于 2013-11-01T13:08:18.657 に答える
0

私の意見Functionでは、グアバと同じように見える. 順序を逆にすると、多くの混乱が生じると思います。

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

于 2013-11-01T13:01:00.867 に答える