実行を遅らせることは、ほとんどの場合、メリットです。しかし、それが問題であり、(Nhibernate での) 「フェッチ」に頼って熱心にフェッチする場合があります。
怠惰な評価があなたを苦しめる可能性がある実際の状況を知っていますか?
実行を遅らせることは、ほとんどの場合、メリットです。しかし、それが問題であり、(Nhibernate での) 「フェッチ」に頼って熱心にフェッチする場合があります。
怠惰な評価があなたを苦しめる可能性がある実際の状況を知っていますか?
各リダクションステップの遅延評価により線形空間の複雑さが生じるため、遅延評価を使用して定数空間で入力データのリダクション (折り畳みなど) を実行することはできません。代わりに、各リダクション ステップの結果を強制的に評価して、スペースの使用量を一定に保つ必要があります。
たとえば、Haskell でファイルをハッシュします。あなたは善意で、入力ファイルをチャンクごとに怠惰に読んで、各チャンクをダイジェストに追加するかもしれませんが、背後では、Haskell が実際には、ダイジェストに追加するすべてのチャンクに対してサンクを作成し、ファイル全体をメモリ内に残しています。結果のダイジェストが実際に評価されるまで、これらのサンク。痛い!
ここで最後のコメントを参照してください: Haskell 遅延 I/O とクロージング ファイル
遅延評価は、パフォーマンスが重要で、値を常に評価する必要がある状況では役に立ちません。このような場合、遅延評価のオーバーヘッドが浪費されるため、値を評価して終了する方がよいでしょう。
遅延評価は、評価に副作用がある場合には役に立ちません。それが唯一の理由であり、純粋に関数型の言語だけがそれを持っているのです。式が特定の順序で発生しなければならない副作用を持つ可能性がある場合、それを持つことはできません。
それとは別に、遅延評価はパフォーマンスを向上させるだけであり、それが主な目標です。そしてそれが、一部の言語が副作用を禁止する理由です。その妥協点の遅延評価を得るために、もう 1 つの良い効果は、制御構造を通常の関数にすることができることです。
奇妙な問題を引き起こす怠惰の一例(今日、Haskellで私に起こりました):
import System.IO
main = do
content <- readFile "foo.txt"
writeFile "foo.txt" content
これにより、コンパイルおよび実行時に次のエラーがスローされます。
foo.txt: openFile: resource busy (file is locked)
ファイル foo.txt を開き、コンテンツを読み取り、もう一度閉じます。次に、書き込み用に開き、コンテンツを書き込み、再度閉じます。
実際に何をしたか: 「ああ、いくつかのコンテンツです。後で実際に必要になったときに読むことになるでしょう。」次に、書き込み用に「foo.txt」を開きます。コンテンツの作成を開始... OK、コンテンツが必要です。読み取り用に foo.txt を開きます - バム!
修正するのは簡単ですが、どこを見ればよいかわからないと見つけるのは困難です。
遅延評価は、値を保存したくない場合には役に立ちません。使用してください。しかし、これは遅延評価器の実装に依存します。一部のシステム (Haskell など) は、値が再び使用されるかどうかを判断できます。漏れを引き起こすことができないものもあれば、漏れを引き起こす可能性があるものもあります。
リソースの遅延読み込みでは、読み込みごとにリクエスターとソースの間を行ったり来たりする必要があります。NHibernate の場合、これはアプリケーションからデータベース (多くの場合、別のサーバー上にあります) への移行を意味します。
多くの場合、各トリップに関連するオーバーヘッドがあります (確かに NHibernate やその他の DB クエリにはオーバーヘッドがあります)。
データのすべてまたはかなりの部分が必要になることがわかっている場合は、一度に取得してオーバーヘッドを 1 回だけ発生させる方がよいでしょう。
典型的な例は、オブジェクトのリストをプルバックしてコンボ ボックスに入力する必要がある場合です (多くの場合、これらは構成オブジェクトです)。リスト メンバーをコンボ ボックスに追加するたびに、遅延読み込みがデータベースに戻っていました。リスト全体をコンボ ボックスに入れているため、各オブジェクトを遅延フェッチするために余分なオーバーヘッドが発生します。
また、プログラムのユーザー エクスペリエンスの問題になる可能性もあります。アプリのロード中に画面にバナーが表示されると 5 秒待つのは喜ばしいことですが、テキスト ボックスに何かを入力しているときに 0.25 秒待たなければならないことは嫌がります。すべてのデータを積極的にロードするのにかかる時間がそれほど長くない場合は、ワークフローのどこかの時点で人々が遅延を受け入れることを検討できます (アプリのロード、ウィンドウのポップアップ、ボタンの押下など)。