web-dev-qa-db-ja.com

Javaでより機能的なスタイルでコーディングする方法は?

私はJavaを少なくとも5年間使用していますが、言語がどのように機能するかを本当に感謝しています。新しいJVM言語(Scala、Clojureなど)を見ると、より機能的な方法でコーディングする傾向があります。この方法にはいくつかの大きな利点があります。

とにかく、Javaまたは他の純粋なOOPを使用している場合でも、より機能的なスタイルを実現するパターンはありますか?これはJavaで意味がありますか?

15
Nils

関数型プログラミングには、それを定義する2つの主要な特性があります-不変のデータとファーストクラスの関数に重点を置いています。どちらも-ある程度の努力と妥当な範囲内で-Javaで実現可能です。

確かに不変のオブジェクトを持つことができます。オブジェクトの状態をコンストラクターで明示的に設定し、セッターを公開せず、finalキーワードをフィールドに適用します。メソッドでオブジェクトの内部状態を変更する場合は常に、更新された状態の新しいインスタンスを返すようにしてください。このようなアプローチは、F#の関数コードとC#の対応するコードの例を含む本である Real-World Functional Programming で紹介されました。 C#はJavaよりも関数型プログラミングに適していますが、Javaにも同様のアプローチを適用できます。

ファーストクラスの関数になると、物事は少しトリッキーになります。現時点では、Javaには、クロージャのサポートが限定された、匿名のネストされたクラスを使用して関数をエミュレートする、かなり不器用で冗長なメカニズムがあります。関数スタイルで少なくともいくつかのコードを書くだけで十分ですが、適切な関数型言語を使用する場合に比べて、つまらない経験になります。Java使用可能なライブラリ、特に guava があり、関数型プログラミングの概念のいくつかを紹介しています不変のコレクションやいくつかの機能的イディオムのようなJava。これはおそらくエクスペリエンスをあまり厄介なものにしないでしょう-しかし、グアバの 公式ドキュメント でさえ、機能的イディオムは控えめにのみ使用する必要があると述べています。対応する命令バージョンよりも冗長で、明確性が低く、効率が悪い。

Javaの状況は、SE 8のリリースで改善されると報告されています。SE7から延期された適切なクロージャとラムダ式を含めるように設定します。その間、JVMのいくつかの関数型言語の1つを試すことができます。必要に応じて、Javaと相互運用します。

16
scrwtp

他の人がすでにここで述べたことに加えて、関数型プログラミングでは、副作用を生成する/状態を変更するコードを機能的に純粋なコードから分離し、分離を明示的にする動機があります。これは、例えば、 Haskellは、IOおよびState Monadsを使用し、参照を通じてClojureで使用します。

OOPでは、状態と状態の変化がオブジェクトにカプセル化されるため、不変のオブジェクトルートを使用しない限り、これはおそらく少し難しくなります。

役立つかもしれない何かは、操作がコマンドである必要があることを示す Command/Query Separation Pinciple に従うことです副作用を引き起こしますが、何も返しません。または、戻り値を持つqueryである必要があり、副作用はありません。この原則に従うことは、副作用の管理に関する限り、1つをより機能的な考え方に導くのに役立ちます。

編集

これが最初に反対票が投じられた理由はわかりません。 John CarmackによるC++の関数型プログラミングに関する記事 は、私が上で言ったのと同様に始まります(C/Q分離部分を除きます)-これは簡単に適用できますJavaも。

5
paul

Gang of Fourの設計パターンの多くは、オブジェクト指向言語で関数型の概念を実装していると見なされています。

機能的なデザインパターン は、便利な資料です。また、シリーズ " Functional Thinking "。どちらもIBMから。

Functional Design Patterns に関するプレゼンテーション(確認するためにこれを見ていません)は、次のように要約されます。

Aino Vonge Corryは、よく知られている多くのデザインパターンをレビューし、関数型言語にはパターンベースの構成があるため、関数型言語での実装がより簡単であることを示しています。

Java内では、クロージャーをメソッド内のローカルクラスとして実装し、関数型プログラミングレルムにさらに拡張することができます。 Java 8は、ラムダを使用してこの機能を拡張します。

したがって、あなたの質問に答えるために-多くの設計パターンはすでに機能的な概念を実装しています。そして、それらはJavaでは理にかなっています。

他のすべてが失敗した場合、常に Greenspunの10番目のルール を呼び出して、目的の機能パターンを取得できます。

5
user40980

良いスタートはニール・フォードです:機能的思考。

次に、次のようなライブラリを探索する必要があります:Googleグアバ、これは、関数、述語、マップ、およびフィルター操作などの必須の抽象化のためのコレクションです(Googleコレクションを使用した関数型プログラミングの場合、いくつかの優れたブログ投稿があります)。

FP in Javaにいくつかのブログがあります。私はapocalisp.wordpress.comを読みましたが、後悔していませんでした。

モノイドのようなより有用な機能構成体については、functionaljava.orgを探索することもできます。

Haskellを学ぶ、ScalaまたはClojureも良い考えですが、もちろん少し複雑です。

幸運を!

3

Java 8は、開発者がJavaで関数型プログラミングを始めるための穏やかな(またはそれほど穏やかではない)開始となるLambdasを導入します。技術的にはJavaにはすでにいくつかの関数型プログラミング機能がありますが、非常に不格好です(非内部クラス)。

0
Martijn Verburg