web-dev-qa-db-ja.com

命令型言語での関数型プログラミング戦略

私はしばらくの間、関数型プログラミングのいくつかの戦略が多くの計算(つまり、データ構造の不変性)に適していることを確信しました。ただし、命令型言語の人気により、機能的に実装されるプロジェクトに常に取り組むことはほとんどありません。多くの言語(Matlab、Python、Julia)は関数型パラダイムの使用をサポートしていますが、多くの場合(Matlabの匿名関数を見ると)取り組まれていると感じています。そうは言っても、OOP /命令型コードでも使用できる関数型のメソッドと戦略は何ですか?可変状態とグローバル変数を持つ言語でも副作用を許可しない確実な関数コードをどのように書くことができますか?

6
jmarple

変更可能な状態は、変更不可能なオブジェクトを使用して簡単に回避できます。同様に、グローバル変数は通常、開発者(または実装が不十分なフレームワーク)の選択です。

そうは言っても、非関数型言語で追加の関数型パラダイムを使用することもできます。コードの表現力がすべてです。 Python=のリスト内包表記によってコードが簡単になることがわかった場合は、それを実行してください。特定の場合に読みやすく、メソッドチェーンを通じて不変の構造を使用している場合は、すばらしいです。

しかし、忘れないでください 元のLOCの3倍を記述し、微妙なバグを導入するリスクがあるとしても、機能的なものよりも命令型のバリアントを見つけやすい人もいます 。さらに重要なことに、一部のプログラマーは基本的な概念を理解していません。多くのC#プログラマーは遅延評価に苦労しており、IEnumerable<T>は、データベースから一連の要素を返します。最初に要素の数を数え、次にそれらをループします。データベースへのクエリは1つではなく2つあります。主流の非関数型言語ではほとんど使用されていないモナドやその他の概念についても話していません。

また、関数型言語を使用しなくても心配はいりません。 非関数型言語は、過去数年間、関数型言語からインスピレーションを得ている傾向があります。C#はその良い例です。 PythonとJavaScriptは、関数型の側面をますます導入する傾向がある他の2つの主流言語です。本質的に、遅延評価とラムダ式をサポートする言語はすべて、関数型スタイルのコードの良い候補です。

13

可変状態とグローバル変数を持つ言語でも副作用を許可しない確実な関数コードをどのように書くことができますか?

簡単な答えは、グローバル変数や可変変数を使用しないことです。あるいは、変数を変更できるからといって必ずしもそうする必要はありません。

このようなクラスを考えてみましょう:

class ImmutableClass
{
    private int myImmutableField;

    public ImmutableClass(int fieldValue)
    {
        this.myImmutableField = fieldValue;
    }

    public int FieldValue { get { return this.myImmutableVariable; } }
}    

そのクラスは不変であり、スレッドセーフですらあります。フィールドは技術的に変更可能ですが、作成後に状態を変更する方法はありません。

2
Scott Whitlock

純粋な関数と不変の変数/オブジェクトを優先します。

それとは別に、使用している言語の制限と規則を覚えておいてください。忘れないでください:

  • 読みやすさ。あなたの同僚はあなたの慣用的でないコードを理解するのが難しくなるでしょう

  • 末尾呼び出しの最適化の欠如

  • 怠惰の欠如

  • 有用な最適化の欠如(例:ストリームフュージョン)

  • 便利な構文がない(例:匿名関数の)など...

私の経験では、あちこちにいくつかのmapsとfiltersを除いて、関数の抽象化を過度にプッシュしてもうまくいきませんでした。関数型プログラミングは非常に強力ですが、すべてのコンテキストで「絶対的な真の方法」であるとは限りません。

1
lortabac