関数型プログラミングとOOP [非公開]


93

最近、Haskellなどの関数型言語の使用について多くの話を聞いたことがあります。関数型プログラミングとオブジェクト指向プログラミングの大きな違い、長所と短所は何ですか?


27
ある人は別の人を拒否しません。
mbq

1
@mbq私はそれらが相互に排他的ではないことを理解していますが、2つのアプローチの違いをよりよく理解したいと思っただけです。
GSto

いい質問ですね。私もこれについて疑問に思っていました。
JohnFx

関数型プログラミングとオブジェクト指向プログラミングは互いに直交しています。両方を同じ言語で使用できます。例:Scala、F#、OCamlなど。Jonasが示唆したように、機能的と命令的のどちらを意味したのでしょうか。
missingfaktor

4
本当の答えは-それらの間に「対」はありません。チェックアウトのStackOverflowでこの質問を
missingfaktor

回答:


67

私はそれがより機能的なプログラミング命令型プログラミングであると言うでしょう。

最大の違いは、命令型プログラミングは制御フローに関するものであり、関数型プログラミングはデータフローに関するものです。別の言い方をすれば、関数型プログラミングではのみを使用し、命令型プログラミングではステートメントの両方を使用します。

たとえば、命令型プログラミングでは変数とループは状態を処理するときに一般的ですが、関数型プログラミングでは状態はパラメーターの受け渡しを介して処理されるため、副作用や割り当てを回避できます。

リストの合計を計算するための関数の命令型擬似コード(合計は変数に保持されます):

int sumList(List<int> list) {
    int sum = 0;
    for(int n = 0; n < list.size(); n++) {
        sum = sum + list.get(n);
    }

    return sum;
}

同じ関数の機能的な擬似コード(合計はパラメーターとして渡されます):

fun sumList([], sum) = sum
 |  sumList(v::lst, sum) = sumList(lst, v+sum)

機能概念の入門として、Simon Peyton-Jonesによる関数プログラミングによるTaming Effectsのプレゼンテーションをお勧めします。


12
機能バージョンは末尾再帰であるため、スタックオーバーフローを回避するために最適化されていることに注意してください。(一部の人々は再帰を見て、そのために関数型プログラミングが悪いと思うかもしれません)
代替案

3
命令対機能の最も重要な側面を説明するための+1:制御フローとデータフロー。追加しなければならないことの1つは、機能的パラダイムとオブジェクト指向パラダイムは相互に排他的ではないということです。オブジェクト指向パラダイムを使用してオブジェクト(データ)がどのように相互作用するかをモデル化し、機能パラダイムを使用してそのオブジェクトを変換(操作)することができます。
ライライアン

1
興味深いことに、コントロールとしてのデータとデータとしてのコントロールを混在させてモデリングできます。FPは、矢印と一次関数を使用して制御フローを渡し、データのように操作できます。OOPはさまざまなデザインパターンを使用して、オブジェクトを使用して制御フローを変更します。
CodexArcanum

主な違いは、同じプログラムを書くことではなく、ループを末尾再帰メソッド呼び出しにすることであることに注意する価値があると思います。それよりずっと大きい
サラ

関数の例では、パラメーターパターンマッチングを使用しています。それは関数型プログラミングに限定されるものではありません。同様に関数型プログラムは、すべての反復アルゴリズムを再帰アルゴリズムとして定式化する必要なく、モナドや命令型の構造を使用できます。

16

関数型プログラミングは宣言型モデルに基づいており、そのルーツはラムダ計算に基づいています。C ++やC#などのより命令型の言語から借りることができる多くの素晴らしい概念を提供します。

いくつかの例には、参照透過性、ラムダ関数、ファーストクラス関数、遅延評価と熱心な評価、および不変性が含まれます。

関数型プログラミングを学ぶことが他に何も含まれていない場合は、その概念に役立ちます。それはあなたがプログラミングをする方法を変え、プログラミングについて考えるでしょう。そして、将来、関数型プログラミングはオブジェクト指向プログラミングと同じくらい重要になると思います。

開始するには、Haskellなどの純粋な関数型言語を使用するか、F#のようなハイブリッド言語を使用することを選択できます。

ほとんどの優れた大学は関数型プログラミングをカバーしています。学校に行くなら、そのコースを取ることを強くお勧めします。


関数型プログラミングとオブジェクト指向プログラミングの大きな違い、長所と短所は何ですか?

オブジェクト指向プログラミングは、複雑な問題を階層にモデル化して問題を単純化できるため、優れています。しかし、可変オブジェクトを使用しながらマルチスレッドプログラミングを検討し始めると、非常に困難になります。このような場合、同期オブジェクトを頻繁に使用する必要があり、大規模なアプリケーションを完成させることはほぼ不可能です。

それが関数型プログラミングの出番です。不変性のようなものがあるため、関数型プログラミングは本当にマルチスレッドプログラムを単純化します。関数への入力Xが常にYを出力することがわかっている場合、何かを並列化することはほとんど簡単になります。また、変数(または関数型プログラミングの値)は別のスレッドから使​​用中に変更できないことも知っています。


2
明確にするために、Schemeは決して純粋な関数型言語ではありません。
ジョナサンスターリング

5
最後の2番目の段落は完全にbsです。OOはマルチスレッド化において問題を引き起こしませんが、可変性はそうです。命令型プログラミングとオブジェクト指向プログラミングを混同しているようです。そうですか?
missingfaktor

5
@missingfaktor:いいえ、私は概念を混同していません。オブジェクトには通常、アクセサー、修飾子、データメンバー、およびメンバー関数があります。はい、すべてのオブジェクトに修飾子が必要なわけではなく、それらを不変として実装できます。しかし、任意のオブジェクト指向プログラムを見ると、ほとんど確実に修飾子を持ち、まだマルチスレッドで使用されているいくつかのオブジェクトがあります。つまり、OOPパラダイムでは、すべてが不変であることは非常にまれです。
ブライアンR.ボンディ

あなたはこの質問への回答を読んでください:stackoverflow.com/questions/3949618/fp-and-oo-orthogonal/...
missingfaktor

また、ここではフランクSheararの答えを確認してください。programmers.stackexchange.com/questions/12423/...
missingfaktor

8

(この回答は、StackOverflowの非公開の質問へ回答から適応されています。)

関数型プログラミングとオブジェクト指向プログラミングの大きな違いの1つは、それぞれが異なる種類のソフトウェアの進化に優れていることです。

  • オブジェクト指向言語は、事物に対する一連の操作が決まっている場合に適しています。コードが進化するにつれて、主に新しいものを追加します。これは、既存のメソッドを実装する新しいクラスを追加することで実現でき、既存のクラスはそのまま残されます。

  • 物事の固定セットがある場合、関数型言語は適切 であり、コードが進化するにつれて、主に既存のものに新しい操作を追加します。これは、既存のデータ型で計算する新しい関数を追加することで実現でき、既存の関数はそのまま残されます。

進化が間違った方向に進むと、問題が生じます。

  • オブジェクト指向プログラムに新しい操作を追加するには、多くのクラス定義を編集して新しいメソッドを追加する必要があります。

  • 機能プログラムに新しい種類のものを追加するには、多くの機能定義を編集して新しいケースを追加する必要があります。

この問題は長年にわたって知られています。1998年、フィル・ワドラーはそれを「表現の問題」と呼んだ。表現の問題はミックスインなどの言語機能で対処できると考える研究者もいますが、広く受け入れられている解決策はまだ主流に達していない。


ここであなたの答え、知恵の言葉が大好きです。数か月前に会って、ブックマークしなかったので、それを探して30分だけ費やしました。技術ではなく概念を理解することの利点を理解している人のための、OOP対FPの最良の説明です。表現の問題に関する論文も素晴らしいです。あなたの洞察を共有してくれてありがとう、私の意見ではあなたの答えは非常に過小評価されています。
tobiak777

4

本当の対はありません。それらは完全に補完することができます。OOPをサポートするFP言語があります。しかし、コミュニティはモジュール性の扱い方が異なります。

FP言語のユーザーは、数学的法則によってモジュール性を達成する傾向があります。そして、法律の順守を示す証拠を好みます。

命令型OOPでは、ユーザーはオブジェクトの動作をテストケースでキャプチャする傾向があり、オブジェクトが変更された場合に再実行でき、この方法でモジュール性を実現できます。

それはほんの小さな側面ですが、言及する価値があると思います。


2

類推:

求人に応募しました。名前、連絡先情報、仕事の履歴を入力します。終了すると、空のアプリケーションはなくなります。

代わりに、書く前に、セロハンの透明なシートでオーバーレイすることを想像してください。あなたの名前を書きます。セロファンの別のシートを追加します。連絡先情報を書きます。より多くのセロファン。仕事の履歴を書きます。終了しても、空白のアプリケーションはそのままです。また、3枚のセロハンのシートがあり、それぞれが単一の個別の変化の効果をキャプチャしています。

前者(OOP)はその場で物事を変えるという考えを受け入れ、後者(FP)はそれを避けます。どちらも状態管理のパラダイムです。両方とも、異なる戦略を使用して、求職申請を完了する効果をキャプチャできます。OOPは開始インストゥルメントを直接変更し、FP は変更の外観に影響を与えるために来たものをオーバーレイします


美しいアナロジー、THX !! これら2つのアプローチの長所と短所で、この類似性を(可能であれば)拡大してください。
ラーフルアガル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.