2012-01-10 8 views
6

ほとんどのプログラミング言語では、関数に渡された引数は、の前に評価されます。より前に評価されます。つまり、それらは忠実に評価されます。ほとんどのプログラミング言語は、関数に渡される引数の評価を熱く使用するのはなぜですか?

私にとって、関数がそれらを使用すると、遅延した引数だけを評価するほうがはるかに意味があるようです。なぜなら、それは決して必要ではないものを評価する理由です。

object if(bool condition, object valueIfTrue, object valueIfFalse) { 
    if(condition) return valueIfTrue; 
    return valueIfFalse; 
} 

で:

また、あなたはブール値がfalseの場合に返すブール値を受け入れるif機能、およびブール値がtrueの場合に返されるオブジェクト、および他のオブジェクトを実装するとし言語が引数を熱心に評価すると、両方のオブジェクトが常に評価されますが、関数は常に最高でもわずかなオーバーヘッドが発生し、最悪の場合は無限ループが発生します。

しかし、ほとんどのプログラミング言語は関数の引数を熱心に評価しているので、通常そういう理由があるはずです。ここで熱心な評価の大きなメリットがありますか?見落としているのですか?それは、言語をそのように実装するのが簡単だったからです。それは単に伝統ですか、それとも何ですか?

+0

これらの非遅延言語でコードをコンパイル/解釈するのは簡単だからです。 –

答えて

5

重要であり、どちらも私が先行評価のために見てきたカップルの理由から、あります

  1. が先行評価は副作用がすぐにと常に起こることを意味します。遅延評価を使用する場合は、以前に行ったことの副作用に依存することはできません。
  2. レイジー評価では、一定量のメモリが肥大化します。一般的に計算の結果を格納するのに必要なメモリは、計算を記述するthunkを格納するよりもはるかに少なくなります。これは、あまりにも多くのメモリ(すなわち時間とメモリのトレードオフ)を使用することにつながり、さらに重要なことに、プログラム/アルゴリズムのメモリ特性を理解するのがより困難になります。

遅延評価は強力なツールになりますが、コストがかからないわけではありません。純粋に機能的な言語は、(一般的に)副作用がないので問題#1を避ける傾向がありますが、時には問題#2に依然として噛まれています。遅延評価を可能にする言語(LISPマクロはこれの一種ですが、遅延評価と同じではありませんが)は、両方の世界を最大限に活かすことができますが、プログラマー側の努力が犠牲になります。

3

オプション1 - レジスタにすべてarguementsをロードし、通話機能

オプション2 - それは必要だ場合は、次の引数を取得し、クリアすることが必要だかどうかを評価するために、CPUのパイプラインを待つ評価し、最初の引数をロードする....必要なパラメタをレジスタにロードし、余分なロジックで機能を実行して、使用中のレジスタをマークします。

アンすでにあなたは(わずかに分岐予測によって保存)を実行されるコードパスを参照するのを待つ間、とにかくパフォーマンスホールドアップを引き起こすことが起こっている「場合は、」

3

遅延評価が動作するためにはが必要です式が評価されたかどうかを追跡するための余分なコードとデータ場合によっては、熱心な評価よりもコストがかかります。表現が遅延評価の恩恵を受けることができるかどうかを判断するには、プログラムがどのように動作するかについての非常に高度な知識が必要です。コンパイラおよび/またはインタプリタは確かにこの種の知識を持たないでしょう。

また、関数または式に副作用がある場合、遅延評価ストラテジーにより、プログラムが直観に反してデバッグが困難になることがあります。これはもちろん、設計上の副作用がない関数型プログラミング言語では問題にはなりません。実際には、すべてではないにしてもほとんどの関数型プログラミング言語にとって、遅延評価がデフォルトの戦略です。

言われているように、別の場所で両方の戦略を使用できないようなものはありません。非自明なプログラムでハイブリッドアプローチを使用すると、私は驚くことはありません。

2

優れた回答を除いて、遅延評価には別の実用的な問題があります。最後のものが "使用"されたときに怠惰に評価される一連の式があると、パフォーマンスのボトルネックを特定するのが非常に難しくなる可能性があります。

+0

例を挙げることができますか?あなたが話しているコードの種類を視覚化しようとしています。 –

+0

まあ、評価されたときに別の変数 'y'の値を取得し、このようなチェーンが戻ってくる関数に引数' x'があるとします。遅くてボトルネックとなる評価があるかもしれませんが、 'x'を評価するときにそれらを見ることができます。誤解を招く恐れがあり、起源を追跡することが困難な場合があります。 –

0

白亜系の時代に戻ると、これを行った多くの言語がありました。例えば、SNOBOL。 ALGOL 68には、このようなことをした「名前による呼び出し」機能がありました。そしてC(とその多くの派生物)は非常に特定の状況でそれを行い、ブール式を「短絡」と表現しています。一般に、それは電源を有効にするよりも、ほとんど常に混乱とバグの原因です。

+0

私は名前によるAlgolの呼び出しが怠惰な評価ではないと思っています。値の代わりに参照を渡していたと思います。 –

+0

ALGOLの名前による呼び出しは、テキスト置換のほうが多く、明示的に参照ではないため、遅延評価とみなされます。今私はそれについて考えているが、それはALGOL 68ではなく、それを導入したALGOL 60かもしれません。 –

+1

Ahh ... 1960年代、 "[白亜紀](http://stackoverflow.com/questions/1463321/was -algol-ever-used-for-mainstream-programming)」と呼ばれていました。 Algol68には名前による呼び出しはありませんが、68は参照による呼び出しがあります。さらに、遅延評価は、 "proceduring"、c.f.を使用して、コーダーによってプログラムで実装できます。 [手順による短絡評価](http://stackoverflow.com/questions/9462051/short-circuit-evaluation-using-procedures) – NevilleDNZ

関連する問題