6

純粋な関数型プログラミングの目標の 1 つは、可変性を排除し、それによって副作用を排除することであることを私は知っています。しかし、現実を直視してみましょう。Java は、関数型プログラミング ライブラリがすべて存在するにもかかわらず、関数型言語ではありません。実際、一部の FP ライブラリはこれを認識し、期待しているようです。たとえば、Functional Java にはEffectクラスがあります。Jedi FP ライブラリには、Commandインターフェイスがあります。これによりIterable、厄介な for ループのボイラープレートを使用せずに、型安全性を備えたコマンド パターンを の要素に適用できます。

Command<PhoneNumber> makeCall = new Command<PhoneNumber> {
    public void execute(PhoneNumber p) { p.call(); }
}
List<PhoneNumber> phoneList = ...
FunctionalPrimitives.forEach( phoneList, makeCall );

問題は、グアバにそのようなものはありますか?

明確化のために回答が受け入れられた後に編集

私は、特定の状況下で、ほとんどの Java FP ライブラリに固有の「垂直問題」に役立つフレームワークを開発しています。したがって、上記のコード例を実際には作成しませんCommand。つまり、宣言の直後にすぐに適用する目的で、垂直方向のノイズの厄介さをすべて備えた の新しいクラス実装を明示的に宣言します。

私は実際のコマンド パターンの行に沿ってより多くのことを考えていました。別の場所で宣言されたいくつかの可能なコマンドがあり、そのうちの 1 つだけがそれを繰り返し適用したいコードに渡されます。さらに、私のフレームワークの目標は、単純に縦の問題を別の場所に移すことなく、関数型インターフェイス オブジェクト (関数、述語、コマンド、その他の単純なラムダ) を作成することをより慣用的にすることです。これはGuavaの範囲内ではないことに長い間気づきました。しかし、コマンドのようなインターフェイスは他の FP ライブラリで利用できるため、アナログが Guava に存在するかどうかを知りたかっただけです。

私のフレームワークを使用したより完全なコード例は、次のようになります。

class Stuff {
    private final Stuff CALLS_TO = callsTo(Stuff.class); // a proxy
    public static final Command<Stuff> CMD1 = commandFor(CALLS_TO.someMethod1());
    public static final Command<Stuff> CMD2 = commandFor(CALLS_TO.someMethod2());

    // methods exist for use elsewhere, but are conveniently also wrapped as commands
    public void someMethod1() {...}
    public void someMethod2() {...}
}

class Activity {
    public void handleIt(List<Stuff> stuffs, Command<Stuff> doCmd) {
        doSomeThings();
        ...
        forEach(stuffs, doCmd);
        ...
        doOtherThings();
    }
}
4

1 に答える 1

10

いいえ!

Guava プロジェクトのリーダーである Kevin Bourrillion は、Guava の機能について次のように述べています。

「構文が最悪です。同時に、これは現在も、これまでも、これからも常に、適切な言語の変更が行われるまでの応急処置にすぎません。その時点で、最終的に最適な構文を実際に決定し、関数型プログラミングを開始できます。実際に Java での生活を改善したことは一度だけです。したがって、関数/述語にどれだけの労力を費やすかはわかりません。王冠の宝石だと思っているからではなく、そうしなければならないという理由でライブラリにあるのです。」</p>

Java 8 が登場したら、おそらく戦略を大幅に変更する予定ですが、それはまだしばらく先の話です。

Commandまた、あなたが説明したインターフェースが最適なソリューションであると思われるユースケースはあまり見つかりませんでした. たとえば、上記のコードは次のように記述した方がはるかに優れていると思います。

for(PhoneNumber phone : phoneList) {
  phone.call();
}

昔ながらの方法。のメリットを確信できる可能性がありCommandますが、「for-each」のユースケースは、ほとんどの場合、昔ながらの方法で行う方がよいと思います。

于 2012-03-02T00:04:49.587 に答える