私は何度も聞いたことがあり、FPとOOは直交している」という考えを理解して検証しようとしています。
まず、2つの概念が直交しているとはどういう意味ですか?
FPは可能な限り不変性と純度を促進しますが、OOは状態と変異のために構築されているようです–命令型プログラミングのわずかに組織化されたバージョンですか?オブジェクトは不変である可能性があることを理解していますが、OOは私にとって状態/変化を暗示しているようです。
彼らは反対のようです。それは彼らの直交性にどのように影響しますか?
Scalaのような言語は、OOとFPの両方を簡単に実行できますが、これは2つのメソッドの直交性に影響しますか?
直交性 は、2つのことが無関係であることを意味します。それはそれが意味する数学から来ています 垂直 。一般的な使用法では、2つの決定が無関係であるか、別の主題を検討するときに1つの主題が無関係であることを意味する場合があります。ここで使用されているように、直交とは、一方の概念が他方を暗示したり除外したりしないことを意味します。
2つの概念 オブジェクト指向プログラミング と 関数型プログラミング は互いに互換性がありません。オブジェクト指向性は、可変性を意味するものではありません。従来の方法でオブジェクト指向プログラムを紹介された多くの人々は、最初にC++、Java、C#、または可変性が一般的で推奨されている同様の言語を最初に使用します(標準ライブラリは人々が使用できるさまざまな可変クラスを提供します)。したがって、多くの人がオブジェクト指向プログラミングを命令型プログラミングおよび可変性と関連付けることは理解できます。これが彼らがそれを学んだ方法だからです。
ただし、オブジェクト指向プログラミングは次のようなトピックをカバーしています。
これはいずれも可変性を意味するものではなく、関数型プログラミングを除外するものでもありません。そうです、それらは異なる概念であるという点で直交です。それらは反対ではありません-どちらか一方、または両方を使用できます(またはどちらも使用できません)。 ScalaやF#のような言語は、両方のパラダイムを1つの言語に結合しようとします。
Scalaは、オブジェクト指向プログラミングと関数型プログラミングの機能を統合するように設計されたマルチパラダイムプログラミング言語です。
F#は、簡潔で表現力豊かで効率的な機能的およびオブジェクト指向言語です。複雑な問題を解決するための単純なコードの記述に役立つ.NET用。
まず、2つの概念が直交しているとはどういう意味ですか?
これは、2つの概念に対照的なアイデアがないか、互いに互換性がないことを意味します。
FPは、可能な限り不変性と純度を促進します。そしてOOは状態と突然変異のために構築されたもののようです(命令型プログラミングのわずかに組織化されたバージョン?)そして私はオブジェクトが不変である可能性があることを理解しています。しかしOO私には状態/変化を暗示しているようです。
彼らは反対のようです。それは彼らの直交性にどのように影響しますか?
Scalaのような言語を使用すると、OOとFPの両方を簡単に実行できます。これは、2つのメソッドの直交性に影響しますか? ?
オブジェクト指向は、カプセル化、オブジェクト構成、データ抽象化、サブタイピングによるポリモーフィズム、および必要に応じて制御された突然変異(OOも同様です。FPは、関数の構成、制御の抽象化、および制約付きポリモーフィズム(別名パラメトリックポリモーフィズム)に関するものです。したがって、2つのアイデアは矛盾していません。どちらも、異なる種類のサービスを提供します。確かに1つの言語で持つことができる力と抽象化メカニズム。実際、これは Scala が構築された理論です!
彼の Scala Experiment Googleでの講演で、MartinOderskyは2つの概念をどのように信じているかを非常によく説明しています-OOとFP-は互いに直交しており、Scalaは、2つのパラダイムをエレガントかつシームレスに統合して、Scalaコミュニティでオブジェクト関数型パラダイムとして広く知られている新しいパラダイムにします。注意が必要です。あなたのために話してください。:-)
まず、2つの概念が直交しているとはどういう意味ですか?
それは彼らがお互いに影響を与えないことを意味します。つまり関数型言語はオブジェクト指向でもあるため、それほど機能的ではありません。
彼らは反対のようです。それは彼らの直交性にどのように影響しますか?
それらが反対である場合(つまり、純粋に関数型言語がオブジェクト指向である可能性がない場合)、それらは定義上直交しません。しかし、私はこれが事実であるとは思わない。
そしてOOは状態と突然変異のために構築されたもののようです(命令型プログラミングのわずかに組織化されたバージョン?)そして私はオブジェクトが不変である可能性があることを理解しています。しかしOO私には状態/変化を暗示しているようです。
これはほとんどの主流のOO言語に当てはまりますが、OO言語が可変状態である必要がある理由はありません。
言語にオブジェクト、メソッド、仮想継承、アドホック多相性がある場合、それはオブジェクト指向言語です-それが可変状態を持っているかどうかも関係ありません。
2つの概念が直交するということは、それらが任意の特定の症状において任意の程度で独立して実現できることを意味します。たとえば、音楽を考えると、曲の調和度とリズム度を分類できます。 「ハーモニック」と「リズミカル」の2つの概念は、ハーモニックとリズミカルなピース、ディスハーモニックと不整脈のピースだけでなく、ハーモニックと不整脈のピースだけでなく、不調和とリズミカルなピースもあるという意味で直交しています。
元の質問に適用すると、これは、Haskellのような純粋に機能的で非オブジェクト指向のプログラミング言語、Eiffelのような純粋にオブジェクト指向の「非機能的」言語だけでなく、Cなどではない言語やScalaなどの両方。
簡単に言えば、Scalaオブジェクト指向であるということは、このデータを操作するメソッドでデータをカプセル化するデータ構造(「クラス」と「特性」)を定義できることを意味し、これらの構造のインスタンスが保証されます。 (「オブジェクト」)は常に定義された状態にあります(オブジェクトのコントラクトはそのクラスに配置されます)。
一方、Scala関数型言語であるということは、可変状態よりも不変を優先し、関数はファーストクラスのオブジェクトであり、他のオブジェクトと同じようにローカル変数、フィールド、またはこれに加えて、Scalaのほとんどすべてのステートメントには値があり、関数型プログラミングスタイルを使用することをお勧めします。
Scalaのオブジェクト指向プログラミングと関数型プログラミングの直交性は、プログラマーとして、目的に合っていると思われるこれら2つの概念の任意の組み合わせを自由に選択できることを意味します。プログラムは次のように記述できます。可変オブジェクトのみを使用し、オブジェクトとして関数をまったく使用しない純粋に必須のスタイルですが、オブジェクト指向機能を使用せずにScalaで純粋に関数型プログラムを作成することもできます。
Scalaでは、実際にはどちらかのスタイルを使用する必要はありません。それはあなたがあなたの問題を解決するために両方の世界の最良のものを選ぶことを可能にします。
すべての分類と同様に、プログラミング言語を関数型、オブジェクト指向、手続き型などに分割することは架空のものです。しかし、分類は必要です。プログラミング言語では、一連の言語機能と、その言語を使用する人々の哲学的アプローチ(後者は前者の影響を受けます)によって分類します。
そのため、「オブジェクト指向」言語は、「関数型」プログラミング言語の機能と哲学をうまく採用できる場合があり、その逆もあります。しかし確かに、すべてのプログラミング言語の機能と哲学に互換性があるわけではありません。
たとえば、OCamlのような関数型言語は、字句スコープとクロージャを介してカプセル化を実現しますが、オブジェクト指向言語は、パブリック/プライベートアクセス修飾子を使用します。これらはそれ自体互換性のないメカニズムではありませんが、冗長であり、F#のような言語(明らかにオブジェクト指向の.NETライブラリと言語スタックと調和して生きようとするほとんどの関数型言語)は、橋渡しをするために長々と努力する必要がありますギャップ。
別の例として、OCamlはオブジェクト指向に構造型システムを使用しますが、ほとんどのオブジェクト指向言語は記名型システムを使用します。これらはかなり互換性がなく、興味深いことに、オブジェクト指向言語の領域内での非互換性を表しています。
オブジェクトのアイデアは、不変の方法で実装できます。例としては、AbadiとCardelliによる本 " A Theory of Objects "があります。これは、これらのアイデアを形式化することを目的としており、オブジェクト指向プログラムについての推論が簡単になるため、オブジェクトに最初に不変のセマンティクスが与えられます。
この場合、従来はオブジェクトをインプレースで変更していたメソッドが、代わりに新しいオブジェクトを返しますが、前のオブジェクトは保持されます。
関数をオブジェクトとして実装し、オブジェクトを関数のコレクションとして実装できるため、2つの概念の間には明らかに何らかの関係があります。
FPは、可能な限り不変性と純度を促進します
あなたは純粋に関数型プログラミングについて話している。
一方、OOは状態と突然変異のために構築されているようです
オブジェクトが変更可能である必要はありません。オブジェクトと突然変異は直交する概念だったと思います。たとえば、OCamlプログラミング言語は、純粋に関数型のオブジェクト更新のための構文を提供します。
Scalaのような言語は、OOとFPの両方を簡単に実行できるようにします
あんまり。末尾呼び出しの最適化がないということは、慣用的な純粋に機能的なコードの大部分がスタックフレームをリークするため、Scalaでスタックオーバーフローすることを意味します。たとえば、 継続受け渡しスタイル (CPS )およびこの論文で説明されているすべての手法 これで終わりです Bruce McAdamによる。JVM自体は末尾呼び出しの最適化ができないため、これを修正する簡単な方法はありません。
純粋な関数型プログラミングとオブジェクト指向プログラミングの直交性に関しては、純粋な関数型プログラミングは小さなプログラム(高階関数など)のみを扱うのに対し、オブジェクト指向プログラミングは大きなプログラムを扱うため、少なくとも直交に近いと言えます。 -プログラムのスケール構造化。これが、関数型プログラミング言語が通常、大規模な構造化のための他のメカニズムを提供する理由です。 Standard MLとOCamlの高次モジュールシステム、Common LISPの場合はCLOS、Haskellの場合は型クラス。
FPとOO)の関係を理解するのに役立ったのは、SICPの本、特にセクション "関数型プログラムのモジュール性とのモジュール性オブジェクト " これらの問題について考えていて、週末に余裕がある場合は、最初の3つの章を読む価値があるかもしれません。
OOPとFPの直交性の素晴らしい 説明 を見つけました。
基本的な考え方は次のとおりです。数式のASTを使用していると想像してください。したがって、さまざまな種類の名詞(定数、加算、乗算)とさまざまな動詞(eval、toString)があります。
たとえば、式は(1 + 2) * 3
。その場合、ASTは次のようになります:
乗算 /\ 加算3 /\ 1 2
動詞を実装するには、すべての種類の名詞にその実装を提供する必要があります。それを表として表すことができます。
+---------------------+-------------------------------------+
| eval | toString |
+---------------+---------------------+-------------------------------------+
| constant | value | value.toString |
+---------------+---------------------+-------------------------------------+
| addition | lhs.eval + rhs.eval | lhs.toString + " + " + rhs.toString |
+---------------+---------------------+-------------------------------------+
| mutiplication | lhs.eval * rhs.eval | lhs.toString + " * " + rhs.toString |
+---------------+---------------------+-------------------------------------+
「直交性」は、[〜#〜] oop [〜#〜]よりも、このテーブルを実装するという事実に由来しますby rows:すべての名詞をクラスとして表します。クラスはすべてのメソッドを実装する必要があります。
一方、[〜#〜] fp [〜#〜]では、このテーブルを実装します by columns—動詞ごとに関数を記述します。この関数は、さまざまなタイプの引数に対して異なる反応を示します(おそらくパターンマッチングを使用)。