私はcall-by-nameとcall-by-valueという基本的な概念を理解しており、いくつかの例を見てきました。しかし、私はcall-by-nameをいつ使うべきかについてはっきりしていません。コール・バイ・ネームが他のコール・タイプに比べて大きな利点やパフォーマンスを得る現実的なシナリオは何でしょうか?方法を設計する際にコールタイプを選択するには、正しい考え方のアプローチが必要ですか?それが説明される可能性がありますコール・バイ・ネームとコール・バイ・バリューを使用するタイミングは?
答えて
名前による呼び出しが多かったため、パフォーマンスや正確さが増す可能性があります。
単純なパフォーマンス例:ロギング。
trait Logger {
def info(msg: => String)
def warn(msg: => String)
def error(msg: => String)
}
そして、このように使用:このようなインタフェースを想像してみて
logger.info("Time spent on X: " + computeTimeSpent)
(たとえば、ログレベルがより高いために構成された、ので)info
メソッドは何もしていない場合、computeTimeSpent
が呼び出されることはなく、時間を節約できます。これはロギングでは頻繁に起こります。ロギングでは、ロギングされるタスクに比べて高価な文字列操作が頻繁に発生します。
正解例:論理演算子。
おそらく、このようなコードを見てきました:ref
がnull
あるたびisSomething
がするので、あなたがエラーを取得します、そして
trait Boolean {
def &&(other: Boolean): Boolean
}
:
if (ref != null && ref.isSomething)
は、あなたがこのような&&
メソッドを宣言したと言いますnull
参照で呼び出された後、&&
に渡されます。このため、実際の宣言は次のようになります。
実際には、値による呼び出しを使用するのは不思議です。実際、Haskellプログラミング言語では、すべてがcall-by-nameがどのように動作するか(似ていますが同じではありません)と同様に動作します。
call-by-nameを使用しない理由としては、速度が遅く、クラスが多く作成され(読み込みに時間がかかります)、メモリが多く消費されます。それについて。
上記の説明にはわずかな修正があります。この例では、ログレベルが情報レベルより高く設定されていても、インフォメーションロガー内で呼び出された関数が呼び出されます。ロガーメッセージのみが印刷されません。 – Sangeeta
@Sangeetaいいえ、関数は呼び出されません。それは全体のポイントです。 –
簡単な方法は、
コールバイ値関数は、渡された式の値 関数を呼び出す前に、これと同じ値がアクセスされたすべての 時間を計算です。ただし、call-by-name関数は、渡された 式の値がアクセスされるたびにその値を再計算します。
私はいつもこの用語が不必要に混乱していると思っています。関数は、名前によるコールと値によるコールの状態が異なる複数のパラメータを持つことができます。したがって、関数が名前によるコールまたは値による呼び出しではなく、それぞれのパラメータが名前渡しまたは値渡しである可能性があります。さらに、「名前による呼び出し」は名前とは関係ありません。 => IntはIntとは異なる型です。それは "Intを生成する引数のない関数"です。ファーストクラスの関数を取得したら、これを記述するために名前による呼び出しの用語を使用する必要はありません。
名前で呼び出すと値にアクセスするときに評価され、値で呼び出すと値が最初に評価されてからメソッドに渡されることを意味します。
この違いを見るには、この例(副作用のみの完全な非機能プログラミング)を参照してください)。いくつかの操作にかかる時間を測定する関数を作成したいとします。あなたがそれを行うことができますによる呼び出し名:
Starting to measure time
Will now sleep a little
Operation took 1000167919 ns
しかし、あなたはmeasure
measure(action: Unit)
への署名だけを変更した場合ので、それはpass-使用しています:あなたは結果(メーリングリスト)を取得します
def measure(action: => Unit) = {
println("Starting to measure time")
val startTime = System.nanoTime
action
val endTime = System.nanoTime
println("Operation took "+(endTime-startTime)+" ns")
}
measure {
println("Will now sleep a little")
Thread.sleep(1000)
}
値による、結果は次のようになります。
Will now sleep a little
Starting to measure time
Operation took 1760 ns
あなたが見ることができるように、action
は、経過時間が近いさえも開始しmeasure
前に評価されますメソッドが呼び出される前に既に実行されていたアクションのため、0に設定します。
ここで、値渡しにより、メソッドの予想される動作を実現できます。場合によっては、正確性に影響を与えませんが、たとえば結果が使用されない場合に複雑な式を評価する必要がないロギングフレームワークなど、パフォーマンスに影響を与えます。
名前でcall-by-nameパラメータを複数回使用すると、パラメータは複数回評価されます。
渡されるパラメータは、関数型プログラミングによる純粋な関数呼び出しである必要があるため、呼び出される関数内の各評価は常に同じ結果を生成します。したがって、名前によるコールは、従来のコールバイ値よりも無駄になります。
- 1. Javaのメモリ、パス・バイ・バリュー、参照渡し
- 2. は、パッチライン・バイ・ライン
- 3. キーピング価格・バイ・日統計
- 4. Linqトップ、グループ・バイ・オーダーBy
- 5. VS2005とVS2008のサイド・バイ・マニフェストの問題
- 6. 従来の(標準)チェックアウト(ステップ・バイ・ステップ・ページ)
- 7. コピーの省略、一時バウンド・バイ・REFオブジェクト
- 8. ライン・バイ・ラインファイル処理、forループ対
- 9. テレフォニマネージャを使用してBRで着信コールと発信コールを録音する
- 10. ケーキのPHPのビデオを見るオーダー・バイ・レーティング
- 11. undef_methodを使用するタイミングとremove_methodを使用するタイミングは?
- 12. 現在のマスターカードレートの取得方法(バイ/売り通貨)?
- 13. try-lock mutexコールとCASコールの比較
- 14. コールは
- 15. オーダー・バイを使用しない場合、オブジェクトへのLinqはデフォルト順序で結合されますか?
- 16. JavaScriptとAJAXコール
- 17. JavascriptとAjaxコール
- 18. コールとVBScript
- 19. ユニコード・バイ・デフォルトのDelphi XEアプリケーションのメッセージダイアログでASCIIアート記号を使用する方法
- 20. コール()
- 21. コール
- 22. コール
- 23. コール
- 24. コール
- 25. コール()
- 26. コール
- 27. コール)
- 28. コール::
- 29. タスクを使用するタイミングとスレッドを使用するタイミング
- 30. assert()を使用するタイミングとtry catchを使用するタイミング
例がありますか? – dax