関数型プログラミングはコードを複雑にしますか?[閉まっている]


17

過去1年間、私はScalaコードを書いてきました(Javaのバックグラウンドから来ています)。vals、caseクラス、map / filter / lambda関数、暗黙的および型推論を使用して、よりシンプルでクリーンなコードを作成できる方法が本当に気に入りました。主にAkkaベースのアプリケーションに使用しました。

今年は、関数型プログラミングが大好きな新しいチームとScalaプロジェクトに参加しています。それらはScalazを頻繁に使用し、コードはあらゆる場所にapplicatives、context bounds、reader / writer / stateモナドで満たされ、メインメソッドもI / Oモナドに「ラップ」されます。彼らの推論は、これによりコンパイラがコードが正しいことを主張する際に「私たちのために働く」ようにし、各関数に副作用がないことです。

それでも、私の観点からすると、この構文はすべてビジネスロジックの邪魔になります。たとえば、「MyBusinessObject」のタイプは問題ありません。「List [MyBusinessObject]」、「Option [MyBusinessObject]」、「Future [MyBusinessObject]」などのタイプも同様です。それらはすべて明確な意味と目的を持っています。一方、次のようなコード:

def method[M[_]: Applicative] = {
  case (a, b) => (ca[M](a) |@| cb[M](b)) {
    case t @ (ra, rb) =>
      if (ra.result && rb.result) t.right
      else t.left
  }
}

それはプログラムに複雑さを追加しますか、それとも私がこのプログラミング方法に慣れていないのは私だけですか?


6
客観的に答えられる質問は何ですか?
鹿ハンター14

1
1文字または2文字の変数名を持つ大量のコードにつながるようです。APLに少し似ています。それは補足ではありません。
user949300 14

3
昨年Haskellで遊び始めました。それは私がカリー化、ファンクタ、モナドのような概念を理解していなかったとき、一度に非常に複雑に見えない、それは短い、象徴的な機能をたくさん持っているという点で、など。HaskellはScalazに似ている、のような>>=および<$>あなたまでその平均は何も、彼らが何をするかを知っています。しかし、彼らが何を意味するかを学んだ後、彼らは今、私にとって非常に自然かつ迅速に読みました。本当の答えではなく、このようなことに対する私の客観的な経験だけです。私もScalaを使用していますが、Scalazライブラリの経験はありません。
KChaloux 14

3
あなたはイディオムに慣れていないだけです。@ user949300短い変数は、多くの機能コードにとって実際には問題ではありません(Mathスタイルの規則について考えてください!)。トニー・モリスのブログも読んで、意味、型、または詳細な変数名をより適切に伝えるものについて、より深く議論してください。
アンドレス

3
@ user949300:短い変数名がローカルで優先されますが、これは関数型および命令型の世界で同じです(for(i=0; i<7; ++i) { trivialOperation(i); }厄介なtrivialOperationCount変数で書くことはないでしょうか?) OOでアクセサメソッド呼び出しを書き出すだけです。通常、結果はより簡潔です。おそらく少し自明ではありませんが、通常、データ宣言を調べるとすぐに明らかになります。静的型付けは非常に役立ちますが、APLとは異なります。
左辺約14

回答:


37

これは関数型プログラミングとは何の関係もありません -他のプログラミング言語のコンテキストでこの種の状況を見つけることができます-「彼らの」言語の高度なコンストラクトを愛する開発者は、読みやすさと物事をシンプルに保つという常識を無視します。C、C ++、Perl、Java、C#、Basic、およびその他の非機能言語でこのような状況に遭遇しました。コードを複雑にするのは関数型プログラミングではありません-プログラマーはそうします。

誤解しないでください。高度な言語機能を避けることはお勧めしませんが、与えられたコンテキストで適切なバランスを見つけることが重要です。世界中で100,000人を超える開発者が使用する汎用ライブラリを作成する場合、ローカルオフィス専用の個別のレポートジェネレーターを作成する場合とは異なる方法が適用されます。


7
また、コミュニティと多くの関係があります。JavaまたはC#のバックグラウンドを持つ開発者にとって、コードはほとんど理解できません(そして、彼/彼女のコミュニティもそれを理解しません)。しかし、たとえばHaskellを書いて、モナド、アプリカティブ、ファンクターなどを使用しない場合、その言語のコミュニティを困惑させていることになります。コードの「自然さ」は固有のものではなく、そのコミュニティと確立された慣行に関連しています。
アンドレス

1
私たちのほとんどは命令的な背景から来ているので、これは見にくいです。それは時々、自然なことについて間違った仮定をするように導きます。
アンドレスF.

SLT C ++ライブラリを見てください。これは、アマチュアにとって非常に読みやすいように記述できます
ラチェットフリーク14

@ratchetfreak:STLを意味すると思います。これは非常に良い例だと思います(そして実際、私はこれを念頭に置いて回答しました)。テンプレートメタプログラミングを使用すると、STLがより再利用可能になるため、STLプログラマーにとって非常に理にかなっています。そして、そのコードを維持しなければならない人々は、通常、メタプログラミングのテンプレートにも使用されます。標準のビジネスアプリケーション全体でテンプレートメタプログラミングをSTLのように使用すると、コードが複雑になり、管理が難しくなります。もちろん、ビジネスアプリケーションでもTMPで問題ない(まれな)ケースを見つけることができます。
Doc Brown 14

@DocBrownええディスレクシアは間違ったタイミングで起動しましたが、正直なところ、心が半分になった場合(そして今よりもはるかに多くの時間)、多くの関数本体をより読みやすく書き換えることができました。
ラチェットフリーク14

7

私はあなたが彼らのコードのやり方に慣れていないことは少なくとも絵の一部だと言うでしょう。私はあなたと同じような状況にあります(C#からF#に来て、Haskellのバックグラウンドを持つ人々と一緒に仕事をしています)、それは面白い経験ですが、壁に頭をぶつけて、もつれを解く瞬間があります特に複雑な点のない関数合成は、そこで何が起こっているのかを把握するためです。それは文化的なものです。

この特定のコードがプログラムに複雑さを追加するかどうかについて-私は知りません。コードの一般的な部分自体が複雑になる可能性があることに同意しました。ただし、これはユーティリティであり、ビジネスロジックの一部ではありません。コードベースをより複雑にするのか単純にするのかを知りたい場合は、そのコードなしでどのように見えるかを想像する必要があります。多くの場合、それら自体が複雑であるような一般的な構成体の場合ですが、単一の画面に収まる複雑さです。同時に、コードベース全体をかなり簡単にします。これは特にモナドの場合です。

また、@ Doc Brownが示唆するように、「芸術のための芸術」の場合もあります。除外することもできません。


5

一般に、関数型プログラミング可変状態を排除することで複雑さを軽減し、コードのセクションがどのように機能するかを理解しようとするときに考慮しなければならないケースの数を減らすと主張します。

ただし、関数型プログラミングにより高度な抽象化が可能になり、高度に抽象化されたコードは非常に便利ですが、定義によって通常は理解を導くために使用するコンテキストとは離婚しているため、理解することも困難です。ビジネスオブジェクトについての「それらはすべて明確な意味と目的を持っています」というコメントは間違いなく真実ですが、そのロジックは既に理解しているニーズとコンテキストに非常に特有であるという事実を反映しています。Monadのような構造の存在により、ほとんど労力をかけずに非常に便利なものを作成できますが、WebにはMonadとは何かを説明しようとするページが散らばっています。それはあなたのための抽象化です。

また、Scalazは長い間FPを食べて呼吸していた人々によって書かれました。彼らはHaskellで利用可能な機能をScalaに持ち込みたかったのです。そうすることで、彼らは教育的であろうとはしなかった。Scalazは、著者にとっては明確で分かりやすいように見えますが、初心者には馴染みのない語彙とスタイルを使用しています。Haskellのバックグラウンドを考えると、私たちの残りの人にとって困惑している方法は、著者にとって非常に明白であるように思われたため、コメントすら正当ではありませんでした。

さらに、関数型プログラミング言語として、Scalaにはいくつかの欠点があり(一部にはJVMに欠点があるため)、Scalazの作者にforcedいコードを書くことを強制する場合がありました。たとえば、一般的なテールコールの除去がないため、一部のコードでトランポリンの使用が強制され、「種類のシステム」がないために型シグネチャが複雑になる可能性があります。

そして最後に、Scalazはそれ自体を大いに活用しています。それはその力のしるしと考えることもできますが、初心者にとってはソースをパズルにすることができます-あなたが見ているコードのランダムな部分は、あなたにとって異質のものを利用する可能性があります。

頑張れ。そして、これは役立つかもしれません。


-4

それはプログラムに複雑さを追加しますか、それともあなたがこのプログラミング方法に慣れていないというだけですか?

なぜこれらの可能性は同じではないと思いますか?

よく書かれたコードは、特定のプログラミング言語に精通していない人でも読むことができます。一部の言語(BASIC、Pascalなど)は、プログラミング言語を見たこともない小学生でも読んで理解することができます。

他の言語の経験とScalaの経験がある人(そして少なくとも1週間はScalazと仕事をしていて、トリッキーなことを説明する同僚がいる人)がまだ混乱している場合; それはそれが複雑さを追加したという証拠です。


11
これは単に本当ではありません:"Well written code can be read by people who aren't familiar with the specific programming language."
アンドレスF.

@アンドレス:それは本当です...ポイントに。適切に記述されたコードは、ビジネスロジックを実装の詳細から分離し、ビジネスロジックが読み取り可能である必要があります。これは、実行しているほとんどの処理が、名前の良いヘルパー関数を直接呼び出すためです。もちろん、これらのヘルパーは、あらゆる種類の言語機能を使用する場合があり、理解するには言語とライブラリの豊富な経験が必要です。
ベンフォークト

4
以下は慣用的なAPLであると信じていますx[⍋x←6?40]。それは何だと思いますか?私は確かに...知らなかったであろう
bdesham

3
@Brendan同じパラダイム内でのみ(そしてそれでも、時にはそうではない)。たとえば、Prolog、Java、およびAPLは非常に異なるため、最初の言語をどれだけよく知っていても、そのうちの1つだけを知っている(他の言語は知らない)場合、他の2つを読むことはできないと主張します。(真剣に、bdeshamの例では、APLを知らない場合、どのように悪魔は「クリスマスツリー」を解釈することになっていますか?)
Izkata 14

1
ブレンダン、よく書かれたあなたの定義は非標準です。よく書かれているのは、常に言語とそのコミュニティに関連しています。言語Xのプログラムは、バグがなく、効率的で明確である場合、適切に記述されています...特定の対象者にとって!ちなみに、これは一般的に書き言葉に当てはまります。常にあなたの聴衆を知っています。(たとえば)科学論文に適しているのは、おそらくあなたのお母さんへのメールには適していません。
アンドレスF. 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.