72

関数型プログラミングを使用したくないのはいつですか? 何があまり得意ではないのですか?

私は、「広く使用されていない」や「適切なデバッガーが利用できない」などではなく、パラダイム全体の欠点を探しています。これらの答えは今のところ正しいかもしれませんが、FP は新しい概念 (避けられない問題) であり、固有の性質ではありません。

関連している:

4

8 に答える 8

45

関数型プログラミングの多くの欠点を考えるのは難しいです。繰り返しになりますが、私は関数型プログラミングに関する国際会議の元議長であるため、私が偏見を持っていると想定しても問題ありません。

主な欠点は、孤立と参入障壁に関係していると思います。優れた関数型プログラムを書くことを学ぶことは、異なる考え方を学ぶことを意味し、それをうまく行うにはかなりの時間と労力を費やす必要があります。先生なしで学ぶのは難しい。これらのプロパティは、いくつかの欠点につながります。

  • 初心者が書いた関数型プログラムは、不必要に遅くなる可能性が高く、たとえば、C の初心者が書いた C プログラムよりも遅くなる可能性が高くなります。不必要に遅くなります。(これらすべての光沢のある機能...)

    一般に、専門家は高速な関数型プログラムを書くのに何の問題もありません。実際、8 コアおよび 16 コアのプロセッサで最高のパフォーマンスを発揮する並列プログラムの一部は、Haskellで記述されています。

  • 関数型プログラミングを始める人は、約束された生産性の向上を実現する前にあきらめる可能性が高く、たとえば Python や Visual Basic を始める人よりも高くなります。書籍や開発ツールの形でのサポートはそれほど多くありません。

  • 話せる人が少ない。Stackoverflow が良い例です。このサイトに定期的にアクセスする Haskell プログラマーは比較的少数です (ただし、Haskell プログラマーは、Stackoverflow よりもはるかに古く、確立された独自の活発なフォーラムを持っています)。

    関数型プログラミングの概念は、Smalltalk、Ruby、C++ などの言語の背後にあるオブジェクト指向の概念よりも教えるのも学ぶのも難しいため、隣人と簡単に話すことができないのも事実です。また、オブジェクト指向コミュニティは何年も費やして、自分たちの機能について適切な説明を作成してきましたが、関数型プログラミング コミュニティは、自分たちの機能が明らかに優れており、説明に特別な比喩や語彙を必要としないと考えているようです。(彼らは間違っています。私はまだ最初の素晴らしい本Functional Design Patternsを待っています。)

  • 遅延関数型プログラミングのよく知られた欠点(Haskell または Clean には適用されますが、ML、Scheme、Clojure には適用されません) は、遅延関数型プログラムを評価するための時間とスペースのコストを予測するのが非常に難しいことです。それ。この問題はパラダイムの根本的なものであり、なくなることはありません。事後的な時間と空間の振る舞いを発見するための優れたツールがありますが、それらを効果的に使用するには、すでに専門家である必要があります。

于 2009-11-24T17:09:12.423 に答える
29

関数型プログラミングの大きな欠点の 1 つは、理論的なレベルでは、ほとんどの命令型言語と同様にハードウェアにも適合しないことです。(これは、コンピューターに実行してもらいたい方法ではなく、実行したいことを表現できるという明らかな強みの 1 つの裏返しです。)

たとえば、関数型プログラミングでは再帰が多用されます。数学の「スタック」は無制限であるため、これは純粋なラムダ計算では問題ありません。もちろん、実際のハードウェアでは、スタックは非常に有限です。大規模なデータセットを単純に再帰すると、プログラムがブームになる可能性があります。ほとんどの関数型言語は、これが起こらないように末尾再帰を最適化しますが、アルゴリズムを末尾再帰にすると、かなり見栄えの悪いコード体操を強いられる可能性があります (たとえば、末尾再帰マップ関数は後方リストを作成するか、差分を構築する必要があります)。そのため、非末尾再帰バージョンと比較して、正しい順序で通常のマップされたリストに戻るために余分な作業を行う必要があります)。

(差分リストの提案をしてくれた Jared Updike に感謝します。)

于 2009-11-24T01:13:33.083 に答える
23

あなたの言語があなたのプログラムを通して状態/例外の動作を調整するための良いメカニズムを提供していない場合 (例えば、モナド バインドの構文シュガー)、状態/例外を含むすべてのタスクは雑用になります。(これらの砂糖を使用しても、FP で状態/例外を処理するのが難しいと感じる人もいるかもしれません。)

関数型イディオムは多くの場合、制御の反転や遅延を頻繁に行います。これは、(デバッガーを使用した) デバッグに悪影響を与えることがよくあります。(これは、FP が不変性/参照透過性のためにエラーを起こしにくいことによって多少相殺されます。つまり、デバッグの頻度が少なくて済みます。)

于 2009-11-24T00:14:51.610 に答える
13

Philip Wadler はこれに関する論文を書き (Why No One Uses Functional Programming Languages と呼ばれる)、人々が FP 言語を使用するのを妨げる実際的な落とし穴に対処しました。

更新: ACM にアクセスできる人は古いリンクにアクセスできません:

于 2009-11-24T01:23:58.163 に答える
8

速度や採用の問題、およびより基本的な問題への対処は別として、関数型プログラミングでは、既存のデータ型に新しい関数を追加するのは非常に簡単ですが、新しいデータ型を追加するのは「難しい」と言うのを聞いたことがあります。検討:

(SMLnjで書かれています。また、多少不自然な例をお許しください。)

datatype Animal = Dog | Cat;

fun happyNoise(Dog) = "pant pant"
  | happyNoise(Cat) = "purrrr";

fun excitedNoise(Dog) = "bark!"
  | excitedNoise(Cat) = "meow!";

以下をすぐに追加できます。

fun angryNoise(Dog) = "grrrrrr"
  | angryNoise(Cat) = "hisssss";

ただし、Animal に新しいタイプを追加する場合は、各関数を実行してサポートを追加する必要があります。

datatype Animal = Dog | Cat | Chicken;

fun happyNoise(Dog) = "pant pant"
  | happyNoise(Cat) = "purrrr"
  | happyNoise(Chicken) = "cluck cluck";

fun excitedNoise(Dog) = "bark!"
  | excitedNoise(Cat) = "meow!"
  | excitedNoise(Chicken) = "cock-a-doodle-doo!";

fun angryNoise(Dog) = "grrrrrr"
  | angryNoise(Cat) = "hisssss"
  | angryNoise(Chicken) = "squaaaawk!";

ただし、オブジェクト指向言語の場合は正反対であることに注意してください。抽象クラスに新しいサブクラスを追加するのは非常に簡単ですが、すべてのサブクラスが実装する抽象クラス/インターフェースに新しい抽象メソッドを追加したい場合は面倒です。

于 2009-11-24T00:39:19.773 に答える
3

私が話している間、私は今Haskellを学んでいるので、逸話で話題になりたかっただけです。関数をアクションから分離するというアイデアが私にアピールし、純粋関数を非純粋関数から分離するために暗黙の並列化の背後にいくつかの本当にセクシーな理論があるので、私はHaskellを学んでいます。

私は3日間、関数のフォールドクラスを学習しています。Foldには非常に単純なアプリケーションがあるようです。リストを取得し、それを単一の値に減らします。Haskellはfoldl、を実装しfoldrています。2つの関数の実装は大きく異なります。foldlと呼ばれる、の代替実装がありfoldl'ます。これに加えて、呼び出される構文がわずかに異なり、初期値が異なるバージョンがありfoldr1ますfoldl1。そのうちの対応する実装がありfoldl1'ますfoldl1。このすべてが吹くのを気にしないかのように、fold[lr].*引数としてrequireし、リダクションで内部的に使用すると、2つの別個の署名があり、1つのバリアントのみが無限リスト(r)で機能し、そのうちの1つだけが定数メモリで実行されます(私が理解しているように(L)は、それだけが必要なのでredex)。なぜfoldr無限のリストで機能できるのかを理解するには、少なくとも言語の怠惰な振る舞いを適切に理解し、すべての関数が2番目の引数の評価を強制するわけではないという細かい詳細が必要です。これらの関数のオンライングラフは、大学でそれらを見たことがない人にとっては地獄のように混乱しています。ありませんperldoc同等。Haskellプレリュードの機能のいずれかが何をするのかについての単一の説明を見つけることができません。プレリュードは、コアが付属するプリロードされたディストリビューションの一種です。私の最高のリソースは、本当に私が会ったことのない男(Cale)であり、彼自身の時間に莫大な費用をかけて私を助けてくれます。

ああ、foldはリストを非リスト型のスカラーに減らす必要はありません。リストの恒等関数を書くことができますfoldr (:) [] [1,2,3,4](リストに蓄積できるハイライト)。

/meは読書に戻ります。

于 2009-11-24T05:13:34.457 に答える
2

ここに私が遭遇したいくつかの問題があります:

  1. ほとんどの人は、関数型プログラミングを理解するのが難しいと感じています。これは、おそらくあなたが機能的なコードを書くのが難しくなり、他の誰かがそれを理解するのがほぼ確実に難しくなることを意味します.
  2. 関数型プログラミング言語は通常、c などの言語よりも低速です。これは時間の経過とともに問題が少なくなっています (コンピューターが高速になり、コンパイラーがよりスマートになっているため)。
  3. 命令型の対応物ほど広く普及していないため、一般的なプログラミングの問題のライブラリや例を見つけるのが難しい場合があります。(たとえば、ほとんどの場合、Python 用のものを見つける方が簡単ですが、Haskell 用のものがあります)
  4. 特にデバッグ用のツールが不足しています。Visual Studio for C# や eclipse for Java を開くほど簡単ではありません。
于 2009-11-24T00:25:56.737 に答える
0

関数型プログラミングの特定の実装の詳細から離れて見ると、2 つの重要な問題が見えます。

  1. 命令的な問題ではなく、実世界の問題の機能モデルを選択することが実用的であることは比較的まれに思えます。問題領域が必須である場合、その特性を備えた言語を使用することは自然で合理的な選択です (一般に、微妙なバグの数を減らす一環として、仕様と実装の間の距離を最小限に抑えることが推奨されるため)。はい、これは十分に賢いコーダーによって克服できますが、タスクにロックスターコーダーが必要な場合、それはあまりにも難しいからです.

  2. 私がよく理解していなかった何らかの理由で、関数型プログラミング言語 (またはおそらくその実装やコミュニティ?) は、すべてを自分の言語で行いたいと考える可能性がはるかに高くなります。他の言語で書かれたライブラリを使用することはほとんどありません。他の誰かが複雑な操作の特に優れた実装を持っている場合は、自分で作成するよりもそれを使用する方がはるかに理にかなっています。これは、外部コードの処理 (特に効率的な処理) をかなり困難にする複雑なランタイムの使用の結果の一部であると思われます。この点で私が間違っていることを証明したいと思います。

これらは両方とも、関数型プログラミングが一般的なコーダーよりもプログラミング研究者によってはるかに強く使用されていることが原因である、プラグマティズムの一般的な欠如に帰着すると思います。優れたツールは専門家に素晴らしいことをさせることができますが、優れたツールとは、専門家が通常できることを一般人ができるようにするものです。

于 2010-11-29T01:06:53.487 に答える