web-dev-qa-db-ja.com

再帰は、プログラミング時に「あまりにも賢い」ことのインスタンスですか?

私はいくつかの本を読んだ経験から学んだことですが、コードを最適化できないほどに最適化したり、チームで作業したり、作業しているときでも、非常に高速で非常に複雑な問題の解決策を思いついたりすることは望ましくありません。あなた自身で、しばらくしてあなたの賢い解決策を理解する必要があります。

私の質問は、再帰は同じように扱われるべきですか?平均的なプログラマーは再帰を簡単に理解できるので、再帰を免責して使用すべきですか、それとも平均的なプログラマーは再帰をあまり理解しておらず、チーム全体の生産性のために再帰から離れるべきですか?

「再帰を理解していないプログラマーは一粒の塩の価値がないので心配しないでください」という簡単な答えがあることは知っていますが、皆さんが実際に体験したい経験があるかどうか疑問に思っていました私が述べたばかりの意見よりも問題を明らかにするであろう共有。

8
Macy Abbey

平均的なプログラマーは再帰を簡単に理解するので、再帰を免責して使用すべきですか、それとも平均的なプログラマーは再帰をあまり理解しておらず、チーム全体の生産性のために再帰を避けるべきですか?

平均的なプログラマーは再帰を完全に理解していると思います。実際、プログラマーがコンピューターサイエンスまたはソフトウェアエンジニアリングの学位を取得している場合は、ほとんど保証されています。確かに、世の中には平均以下のプログラマーが何人かいますが、チームに彼らを望まないでしょう。

この場合、平均的なプログラマーと優れたプログラマーの違いは、再帰を使用するwhenとそうでない場合を知っています。そして、それは解決される問題とそれを解決するために使用される言語に依存します。

  • 関数型プログラミング言語を使用している場合、再帰はさまざまな問題に対する自然で効率的なソリューションです。 (テール再帰最適化ルール!)

  • OOまたは単純な手続き型言語を使用している場合、再帰は効率が悪くなる可能性があり、スタックオーバーフローが原因で問題が発生する可能性があります。そのため、場合によっては、再帰的なソリューションではなく反復的なソリューションを選択します。ただし、 、他の場合では、再帰的ソリューションは非常にシンプルでエレガントなので、(おそらくより効率的な)反復ソリューションは「賢すぎる」ソリューションになります(たとえば、問題がツリー/グラフのバックトラッキング、構築、またはウォーキングを必要とする場合、など、再帰は多くの場合より簡単です。)

22
Stephen C

一部の問題は自然に再帰的です。これらの場合の反復ソリューションを考え出すことは、実際には再帰的なソリューションよりも不格好で複雑な場合があります。良い例は、階層ツリー構造をトラバースする必要があるアルゴリズムです。これは、プログラミングでは珍しいことではありません。

TL; DRバージョン:いいえ。

42
Bobby Tables

再帰は、ほとんどの関数型プログラミング言語の基本原則です。関数型言語の反復(ループ)は、通常、再帰によって行われます。

関数型言語は、より多くのプロセッサコアをエレガントに処理する必要があるため、最近、多少ルネッサンスになっています。関数型言語は、可変構造のロックに伴う複雑さを伴わずに、プログラムをより適切に推論する方法を提供することにより、この種の並行性を実現するのに役立ちます。

11
Robert Harvey

ツリー構造のウォーク(たとえば、特定のBツリーノードの検索ではなくディレクトリ構造全体のウォーク)などのいくつかの問題は、再帰の使用に最適です。非再帰的同等物は、多くの場合、独自のスタックの管理をさらに複雑にします。

このような場合、再帰が最善かつ最も簡単なソリューションであり、理解が最も簡単です。

11
Lawrence Dol

適切な場合は再帰を使用すると言いますが、明示的な再帰を回避する方法を常に模索しています。

たとえば、ツリー構造を手動でトラバースする必要がある場合は、はい、再帰を使用する必要があります。誰かが再帰的なツリートラバーサルを理解できないほど愚かである場合、彼らは反復バージョンの先頭も末尾も作成しません。

しかし、より適切なオプションは、「ツリー内のすべてに対してこの操作を実行する」ということがわかるまで、再帰を抽象化するイテレータを使用することです。

7
Anon.

再帰は、コードのクリーン度の観点から最も単純なメカニズムです。速度が非常に重要な場合は、問題のパラメータの2D配列を使用できます。ドータープロセスの生成は、別のアイテムを配列に追加するだけです。私はかつて、アセンブラの三重対角ソルバーを実行しましたが、それは当時は大変なことでした。インスタンスごとに必要なコンテキストはレベルごとに8ワードであり、各サブ問題は前の問題の3分の1でした。この「ライブラリ」は、他のすべての実装の問題を打ち負かしたため、人気がありました。しかし、それはプログラミングではかなりまれな状況なので、このソリューションを利用できるからといって、「時期尚早の最適化」に屈する必要はありません。明らかに、いくつかのことについては、再帰101の例のような「階乗の計算」のように、それはひどい過剰です。しかし、ほとんどのアプリにとって、これはソースコードの複雑さを排除するための本当にエレガントな方法です。

アプリに使用するシンプルなスペルチェッカー(マイナーなスペルミスの修正に関するヒントを提供したい)があります。そこでは、2つの文字列間の「距離」を計算し、削除と追加を許可しています。これにより、ツリー構造が大きくなる可能性があり、近い一致のみを対象とするため、ブランチがトリミングされます。再帰を使用すると、おそらく20行のコードになります(FortranとCの両方のバージョンがあります)。それ以外の場合は厄介だと思います。そのツリーについて考えるよりも、プログラミング/デバッグ検証の方がはるかに簡単でした!

3
Omega Centauri

理解していますが、明示的に使用したことはありません。自分自身をプログラマーと呼ぶ人は、スタックとヒープが何であるかを知る必要があるのと同じくらい、それが何であるかを知っているか学ぶべきだと思います。ねえ、誰もが気まぐれな再帰を介して三目並べで最小/最大がどのように機能するかを知る必要があります。

0
johnny