Javaで関数型プログラミングは可能ですか?[閉まっている]


42

Amazon.com Bookstoreを閲覧していたときに、「Java開発者向けの関数型プログラミング」という本に出会いました。

私はいくつかの非常に基本的な関数型プログラミングを知っており、Javaで3年間プログラミングしています。

Javaでも関数型プログラミングは可能ですか?


2
スタイルは可能ですが、その冗長性はJavaの構文を考えると耐えられない可能性があります:functionaljava.org
Yuriy Zubarev

7
@nCdy JRubyをチェックする理由 もっと説明してください。
カイロン

1
グルーヴィーを確認してください:-)
Antの

6
これは、Javaという言語とJavaというプラットフォームの違いを引き起こす一種の質問だと思います。
トーマスオーエンズ

2
@ThorbjørnRavnAndersen:「関数型プログラミング」は「怠lazな評価」によって定義されていると思いますか?それは...迎えに奇妙例と思われる
ジョン・バーソロミュー

回答:


70

「関数型プログラミング」と「可能」の意味に依存します。

機能的パラダイムに従って物事を明らかに実装できます。ただし、Java言語には構文糖衣が用意されていないため、せいぜい退屈なものもあれば、非常に難解なものもあります。

同様に、オブジェクト指向コードは、Cのように非OOであると認識された言語で非常にうまく書くことができます。

Javaライブラリ

これを行うのに役立つライブラリがあります。すでにあなたのために脚注を行い、不可解なものを隠しています。

これらにより、FP対応言語に期待されるように、より機能的なアプローチと、おそらくより使い慣れた構文とセマンティクスでJavaコードを書くことができます。理由の範囲内で、それは。

JVM言語

そして明らかに、Javaの上に関数型言語を実装できます。これにより、その言語をFP言語として使用できます。これは、あなたが求めたものよりも少し高いレベルの抽象化ですが、比較的文脈の範囲内です(ただし、ここで少しごまかしているのですが)。

たとえば、チェックアウト:

多かれ少なかれ機能的なJVM言語

それらはまさにあなたが望むものではないかもしれませんが、Javaプラットフォームに移植された他の多くの言語があり、Javaの比較的面白くない(はい、しゃれを意図した)性質から解放し、すでにより多くを提供します柔軟性。JRubyJythonRhinoRubyPythonJavaScript / ECMAScript)のような注目すべき候補も関数型プログラミングの興味深い可能性を提供しますが、本質的には実際に関数型プログラミング言語ではありません。JetBrainsのコトリン、それは関数型言語ではないことを明確に認めつつ、いくつかの関数型構造をサポートしており、一見の価値もあります。

参考文献

次の記事やビデオを読んだり見たりすることもできます。


2
ClojureソースコードはGithub github.com/clojure/clojureで
Chiron

@ 1982年の伝説:あなたのコメントよりも速かった、私はすでに公式のclojure.orgサイトへのリンクを変更しました:)しかし、それをとても早くキャッ​​チしてくれてありがとう!人々が素早く反応するのを見るのは良いことです。
ヘイレム

ABCL(common-lisp.net/project/armedbear)もありますが、成熟/ 成熟の規模のどこに該当するかはわかりません。CommonLispの実装です。
バティーン

@Vatine:おもしろい、聞いたこともない。簡単に見て、追加します。
ヘイレム

1
アラン・ペルリスの「Turning Tarpit」という言葉が大好きです。これは、言語ができることをやろうとすることです(完全にチューリングしているからです)。
-itsbruce

11

あなたが言った本を読んでいます。本当に良いです。

はい、Javaで機能することは可能です。どの程度達成できるかわかりませんが、多くの関数型プログラミングのイディオムを実装できます。

最も重要なことの1つは、「状態を変更しない」という考え方でコーディングしようとすることです。

たとえば、finalキーワードを使用して不変性を実現します。データ構造を使用する場合は、不変のデータ構造をコーディングする必要があります。Google Guavaライブラリはすでにこれを行っています。

並行プログラミングの場合も、Akkaフレームワーク(アクターモデル)に依存できます。

JVMバイトコードは、(少なくともまだ)テールコールの最適化、関数型プログラミング言語にとって非常に重要な機能をサポートしていないことに言及する価値があります。


「JVMバイトコードは(少なくともまだ)テールコールの最適化、関数型プログラミング言語にとって非常に重要な機能をサポートしていないことに言及する価値があります。」ScalaにはTCOがあります。
ジョルジオ

@Giorgio:Scalaはコンパイル時にTCOを実行します。
scrwtp

@scrwtp:そのためにパフォーマンスが低下しますか?または、コンパイル時TCOの欠点は何ですか?
ジョルジオ

@Giorgio:私が意図したのは、Chironが最初に述べたように、javaバイトコードはネイティブにサポートしていません。関数型言語はそれを回避し、末尾再帰呼び出しをループにコンパイルしますが、これはJVMではなく言語->バイトコードコンパイラの機能です。
scrwtp

@scrwtp:Chironの答えは、「JVMバイトコードは、(少なくともまだ)テールコールの最適化、関数型プログラミング言語にとって非常に重要な機能をサポートしていないことに言及する価値があります。」JVMでの関数型言語の実装のように聞こえますが罰せられますが、テールコールの最適化はコンパイルされたコードでシミュレートできるため、これは真実ではありません。だから私はChironの声明に同意するが、それは少し誤解を招くと思う。
ジョルジオ

6

はい、チューリング完全な言語/実行環境の組み合わせで可能なのと同じように、間違いなく可能です。自分が何をしているのかを知っていれば、非常にうまく機能させることさえできます。

しかし、それがどれほど賢明なのかはわかりません。特に、それは特にイディオムではないことに注意してください(つまり、非常に奇妙に見えるでしょう、いくつかの型にはまらないことをし、通常のJavaに慣れている人を混乱させる必要があります)

新しい関数を定義するなど、奇妙なコードになります。

Function twoStrings=new Function() {
  public Object apply(Object param1) {
    // do something to param1 and return a result
  }
}

関数型プログラミングを行うには、通常次のものが必要です。

  • ファーストクラス関数 -「関数」を表し、1つ以上のパラメーターに関数を適用する「適用」メソッドを持つ抽象クラスまたはインターフェースを定義することにより、Javaで簡単に作成できます。
  • クロージャー -最終フィールドに格納されたクローズド値を使用して、上記の関数オブジェクトのインスタンスを作成します。これには匿名の内部クラスを使用できます。
  • 標準的な高階関数のライブラリ -これはややこしいですが、数時間で簡単な関数型言語をブートストラップするために独自のライブラリを作成できます。より洗練されたものが必要な場合は、人々がJavaで構築した他の機能ライブラリをチェックできます。

エクササイズとしても、面白い趣味プロジェクトとしても可能です。しかし、JVMの利点を維持しつつJavaライブラリにアクセスしながら真剣に機能的なプログラミングを行いたい場合は、Clojureが最良の選択肢だと思います。

ps Clojureのコアは実際にはJavaで書かれているため、実際にはJavaで関数型プログラミングを実行する非常に興味深い事例です。Clojureのソースコードは、興味のある方のためにGitHubにあります。


興味深いことに、IntelliJ IDEAの最新バージョンは、これらの匿名のOneSiesをエディターで表示するためのよりコンパクトなフォームに折りたたむことに気付きました。冗長な残骸を隠すというかなりの仕事をします。もちろん、このすべては無関係になりますジャワ8.来る
ベン・ハーディ

4

Javaである程度機能することは可能です。そうするのは大変な痛みです。の代わりに

myList.each { doSomething(it); }

次のようなものがあります:

myList.each(new Function() { public void do(Object arg) { something(); }})

クロージャーと関数をファーストクラスオブジェクトとして使用して、真の関数型プログラミングが必要な場合は、別の言語を選択してください。Scala、Clojure、GroovyはすべてJVM上で実行され、レガシーJavaクラスと対話できます。。


関数型プログラミングは、匿名クラスの代わりにブロックを使用することではありません。Java 8にはブロックがあるため、投稿されたコードはよりエレガントに見えますが、関数型プログラミングにはなりません。
シロン

@レジェンド:私はそれを理解していますが、明らかにそれをうまく説明していませんでした。
ケビンクライン

これは見落とし/見落としです。どの言語でも、実際にSOMEWHERE関数を定義する必要があります。その部分をスキップすることはできません。したがって、Javaはほぼ簡潔であり、必要なことはFunctionオブジェクトを匿名にすることだけです。これを行うことができます:Function f = new Function(){public void do(){}}; .... then ...その関数を呼び出します...... myMethodToCallAFunction(Function f){f.do()} ...これで終わりです。それに対処する。
アレクサンダーミルズ14年

3

答えは「はい」という印象的なものですが、私の意見では、多くの関数型言語で最も重要な機能の1つは優れた型システムです。これをJavaで自分で管理することはできません。

機能的なプログラムを作成し、JVMを使い続けたい場合は、通常の容疑者ScalaとClojureの中からFregeを調べることをお勧めします。Fregeには、Haskellに非常に近い構文と型システムがありますが、プログラムはJavaコードに直接変換され、他のJavaコードと対話できます。


2

まあ、あらゆる種類のものが可能です。Cでオブジェクト指向プログラミングを行うことは可能です。あまり良い考えではありません。

JavaはFP用に設計されていないため、純粋にFPスタイルですべてを実行しようとすると、問題が発生します。あなたはそれを使う代わりに、その言語と戦うことになります。また、言語だけでなく、すばらしい無料のJavaライブラリもすべてあります。そのため、純粋なFPを使用しないでください。FPの背後にあるアイデアのいくつかをJavaコードに統合しますが、すべてのアイデアにそれを行うことはできないことを理解してください。


0

OpenJDKチームは、最新のOpenJDK 8バイナリをダウンロードし、新しいラムダ式とCollections API(特に)で導入された新しい機能的なイディオムを試してみることをお勧めします。明確な機能スタイルでプログラミングできます。「Javaでの関数型プログラミング?」を参照してくださいGuava、FunctionalJava、LambdaJなどのJava8以前のライブラリとJDK8コレクションを比較します。


-3

可能と思われるかもしれませんが、純粋な関数型プログラミングではありません。命令型プログラミングになる可能性があります。

彼がヘイレムによって言及された可能性のある関数型プログラミングによって意味する理由を尋ねることはありません。ここにあります:

「関数型プログラミング」と「可能」の意味に依存します。

関数型プログラミングには多くの説明があるかもしれませんが、異なる定義や意味を持つことはできません。
OOPと同様に、「OOPとはどういう意味ですか?」
間違いなく多くの説明がありますが、それはただ1つの目的、OOPの目的に関係します。
同じことが関数型プログラミングにも当てはまります

機能的な意味を言うとき、プログラムは機能で構成されます。
関数の役割は、評価された引数/パラメーターを返すことです(引数は変数であり、パラメーターは関数宣言の一部である変数であり、関数を呼び出すときの式です)。

また、同じ引数が渡されると、関数は常に同じ結果を返します。そのようにして、バグを回避したり、将来のバグをデバッグしたりするのが簡単になります。関数型プログラミングにより、グローバル変数の変更などの副作用を回避できます。

JavaScriptの例:

function increment(lis){
    return lis.map(
        function (x){
            return x+2;
        }
    );
}

var myList = [4, 7, 2, 3];
console.log(increment(myList));
console.log(myList);

関数incrementは、オブジェクト内の各要素に1つの値を追加し、結果を返します。myListの値は変更されませんでしたが、関数を呼び出すと、そのオブジェクトの要素に追加された値が表示されました。

私の応答として、Javaで可能である関数プログラミング?、Javaで真の関数型プログラミングを行うことは不可能だと思います。javaは、命令型プログラミングを拡張し、保守性を向上させるOOPとして設計されているためです。オブジェクト、変数などの状態が変化したとき、それはすでに命令型プログラミングです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.