関数型言語を学ぶことは、より良いOOPプログラマーになりますか?[閉まっている]


28

Java / C#/ C ++プログラマーとして、関数型言語について多くの話を聞いていますが、関数型言語を学ぶ必要はありません。関数型言語で導入されたより高いレベルの思考が、より優れたOOP /手続き型言語のプログラマーになると聞いたことがあります。

誰でもこれを確認できますか?どのような点でプログラミングスキルが向上しますか?

それほど洗練されていない言語でスキルを向上させることを目標に学習する言語の適切な選択は何ですか?


3
C#でコーディングしている場合は、すでに知っています。LINQは非常に機能的なものです。
SKロジック

OOPは実際のオブジェクトのモデリングに適していると思います。
Tulainsコルドバ

1
@ user61852ほとんどのオブジェクト指向デザインパターンは、「実際の」オブジェクトについては何もモデル化しませんが、実際には非常に抽象的な概念です。
アンドレスF.

Java / C#(+ C ++)プログラマ以上のものであること。40枚の中からブレードXを選択する理由を概説するそれほど大きくないパンフレットを備えた巨大なスイスアーミーナイフと、とにかく鋭くてカーブしているので、好きなものの近くで切り取ることができるブレードとの間には違いがありますあなたがそれをあなたがそれを適用できることができるように、多くの考えなしで多種多様な状況に切断力です。(もちろん、ハンドルの栓抜き付き)
エリックReppen

回答:


32

私は基本的にFrustratedWithFormsDesignの答えに同意しますが、新しいパラダイムの学習がスキルの向上にどのように役立つかについても質問しました。私の経験からいくつかの例を挙げることができます。

関数型プログラミングを学ぶので、私はどの概念を扱うのがより自然に「オブジェクト」(一般に突然変異が意味する)と考えられ、どの概念が不変の「値」と考えられるかについてもっと意識しています(重要な違いがあると思います、OOが理にかなっている場合とFPが理にかなっている場合に触れますが、それは私の意見です)。

私のコードには副作用が含まれていることに気付き、それらの場所を分離するように注意し、より多くの関数を「純粋な」関数にします。これにより、OOコードのテスト容易性が大幅に向上します。

データ表現のサイクルについてもっと意識しています。(たとえば、リンクリストをHaskellの二重リンクリストに変換する関数を書くことができないと思うので、その言語ではサイクルにかなり多く気づきます。)サイクルを避けると同期の量が減りますデータ構造を内部的に一貫させるために実行する必要があり、これらの構造をスレッド間で共有する負担を軽減します。

私は再帰に頼る可能性が高くなります(スキームの再帰ループ構造は美しさのものです)。ダイクストラは、構造化プログラミングに関する注意事項でこれの重要性について触れました -再帰アルゴリズムは数学的な帰納法に非常に直接対応しており、ループが正しいことを知的に証明する唯一の手段であることを示唆します。(コードが正しいことを証明しなければならないということはお勧めしませんが、自分でコードを作成しやすくするほど、コードが正しい可能性が高くなります。)

高階関数を使用する可能性が高くなります。John Hughesの論文、Why Functional Programming Matters。関数型プログラミング手法を採用することで得られる構成可能性を強調し、高次関数が主要な役割を果たす。

また、Jettiの回答で触れたように、多くのFPアイデアが新しいOO言語に組み込まれていることがわかります。RubyとPythonはどちらも多くの高階関数を提供し、LINQはC ++にモナド内包表記のサポートをもたらす試みとして説明されていると聞きました。


@Aidan:C ++ 0xのwrtラムダ、とにかく新しいC ++コンパイラは既にそれらを組み込んでいます。
マチューM.

1
「可変状態を保持するもの」としての「オブジェクト」は非常に一般的ですが、バリューオブジェクトパターンは長年にわたって存在しています。
フランクシェラー

@Matthieu、ありがとう、それを反映するためにテキストを更新しました。
エイダンカリー

@フランク:ポインタをありがとう。私はこれを答えに含めませんでしたが、Values to Objectsにする主な異論は、オブジェクトの所有者であるb / wオブジェクトインターフェイスとオブジェクト(オブジェクトの関係がより多くなる)の区別に関するものです。オブジェクト自体よりもプライマリ)。 1 + 2は数学的にはと同等ですが2 + 1、の1.+(2)実装とは異なり2.+(1)ます。オブジェクトインターフェイスを使用するよりも操作を使用する方が自然に理解できるSWの問題がいくつかあります。
エイダンカリー

1
@Aidan William Cookの「データ抽象化の理解について、再訪」を読みましたか?オブジェクトとADTの違いを掘り下げます。これはあなたが示唆していることです。
フランクシェラー

32

優れたOOPプログラマーになるとは限りませんが、新しい考え方が紹介され、OOPの観点だけでなく、一般的な問題解決が向上する可能性があります。


3
オブジェクトが実際に高階関数であることを考えると、FPを学習することが私のOOPに直接役立つことがわかりました。あなたが言うように、それはより一般的に適用可能/有用です。
フランクシェラー

12

関数型言語-私にとってLisp-を学ぶことは、並列アプリケーションを構築するときに本当に役立ちます。機能的メソッド(状態ベース、副作用なし)は同期がはるかに簡単で、入力のみに依存するため、スレッドセーフにするのが簡単です。つまり、コードの特定の領域で監視する必要があるデータは、渡すパラメータだけです。これにより、デバッグも容易になります。


また、ライブラリをスレッド化するのにも役立ちます。ライブラリはタスクとして純粋な関数を期待する傾向があります。また、間接的に役立つこともあります。オブジェクトコードを参照し、関数によって使用される一連のオブジェクトに暗黙的なロックを持つ "所有パラメーター"があるような "機能スタイル"でOOコードを記述する場所があります。 。期待を文書化する(およびそれらを単体テストする)限り、これにより、ロックの問題が少ない、より良いマルチスレッドコードが得られます。そして、いくつかの明示的なロック。

Prologが関数型言語と呼ばれることは聞いたことがありません。私が十分に目を凝らすと、Prolog(の一部)がFPでどのように役立つかを漠然と見ることができます。
フランクシェラー

1
プロローグは関数型言語ではありません。これは論理言語です。あなたがProlog-をしたい場合のようにだけでなく、心のように関数型プログラミングを統合されている論理型言語、あなたは、ガンダーつかむことができる水銀を。警告:Prologを既に知っている場合でも、脳を少し傷つけます。
ちょうど私の正しい意見

@ちょうど私の正しい意見:はい、あなたは正しいと思います。関数型言語についてもっと学ぶ必要があると思います!
マイケルK

1
@moz:ええ、Javaにラムダがあればいいのに。匿名Threadオブジェクトは...不器用です。
マイケルK

9

プログラミングの他のパラダイムを学習すると、一般的なプログラミングスキルが向上します。プログラミングは、アカデミックな研究グレードのものではない場合(そしてその場合でも、多くの場合)、基本的に問題解決です。一言で考える。さまざまなパラダイムは、問題とその解決策についてのさまざまな考え方です。したがって、「関数型言語を学習する」とだけ考えないでください。「問題とその解決策について考えるための別の方法を学ぶ」と考えてください。そうすれば、実際に言語を使用したことがない場合でも、言語を学習する利点がわかります。

あなたの特定の質問に対処するために、私は昔(C ++の標準が登場する前の頃)C ++プログラマでした。メソッドなどによって操作される状態を保持するオブジェクトを使用して、すべての通常のものに従いました。その後、Haskellに出くわし、それの多くを学びました。(私は誰もがHaskellを本当に学んだとは思いません。)同僚の1人(私のグループに割り当てられたテスター)が私のコードがテストしやすくなったという手っ取り早いコメントをするまで、演習は少し無駄に思えました。

起こったことは、オブジェクトをますます不変にし始めたことでした。複雑な可変状態のクラスは、変更を加えて自身を複製したクラスに置き換えられ始め、新しいオブジェクトを返しました。共有オブジェクトは、コピーオンライトセマンティクスを持つオブジェクトに置き換えられ始めました(したがって、メモリオーバーヘッドなしで多くのオブジェクトクローンの錯覚を与えます)。絶対に必要でない限り、関数には副作用はありませんでした。「関数」の純粋な数学的定義はますます標準になりました。関数型プログラミングの分野をどんどん探求していくうちに、これはすべて私のコードで自然に起こり始めました-意識的な考えは関係していませんでした。

今では、2年ごとに少なくとも1つの新しいプログラミングパラダイム(AOPのようなマイナー拡張パラダイムであっても)と各パラダイム内の少なくとも2つの新しい言語(できるだけ純粋な、もう1つのハイブリッド/実用的な)を学ぶことを目標にしています)。それぞれが、あらゆる言語のすべてのプログラミングに適用する新しい知的ツールを私に与えてくれたので、それらを学ぶのに費やした時間は、私の意見では、少しでも無駄になりませんでした。


3

前にも言ったことがありますが、機能言語を学ぶことで間違いなく私のC#が改善されました。ラムダを理解するのに役立ちました(そして、ラムダを愛するのに役立ちました)。また、非同期操作で作業するとき、関数型プログラミング(F#)をどれだけ好むかを実感しました!


3

マシンコードは副作用のリストにすぎません-プロセッサによって直接実行されるコマンド。Cの副作用は異なり、レジスタと物理ハードウェアを処理するのではなく、抽象化のセットを処理し、コンパイラにすべての汚い仕事をさせます。Cでは、ループとif thenステートメントで副作用を構造化することもできます。C ++は、OOPおよび必要な機能を言語に追加することにより、Cを改良します。JavaとC#はガベージコレクションを追加し、Pythonは動的型付けを追加します。

これらのすべての機能-動的型付け、ガベージコレクションなど、これらの言語のプログラムは、依然として完全に副作用に基づいています。Scheme、Clojure、Haskell、MLなどの関数型プログラミング言語はまったく異なるものであり、これらの言語は、機械コードよりも数学に近いものです。副作用を使用する代わりに、関数の周りに値を渡します。

それほど洗練されていない言語でスキルを向上させることを目標に学習する言語の適切な選択は何ですか?

Schemeをお勧めします。これは最小限であり、MITの古い入門プログラミングクラスで使用されていました。他の関数型プログラミング言語は習得がはるかに困難です。ClojureはJavaのすべての複雑さをもたらし、MLは複雑な静的型システムをもたらします。Haskellは学術言語と呼ばれることもあります-初心者には理想的ではありません。一方、Schemeは簡単に習得して理解できます。

どのような点でプログラミングスキルが向上しますか?

ほとんどすべての高水準プログラミング言語には、関数と再帰(関数型プログラミングの基礎となる概念)があります。そのため、FPの知識はほぼどこでも役立つはずですが、機能的にプログラムしたい場合は、他の人の言語設計を好みに合わせて変更するのではなく、自然で効率的な言語を使用する必要があります関数型プログラミングを行うには関数型プログラミング言語を使用する必要があります。

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