Wann Call-by-Name und Call-by-Value?

8

Ich verstehe das Grundkonzept von Call-by-Name und Call-by-Value, und ich habe auch einige Beispiele betrachtet. Ich bin mir jedoch nicht sicher, wann ich Call-by-Name verwenden soll. Was wäre ein realistisches Szenario, in dem Call-by-Name einen signifikanten Vorteil oder eine Leistungssteigerung gegenüber dem anderen Call-Typ hätte? Was sollte der richtige Denkansatz sein, um einen Anruftyp beim Entwerfen einer Methode auszuwählen?

    
naugustine 26.09.2013, 18:04
quelle

4 Antworten

16

Es gibt viele Orte, an denen Call-by-Name Leistung oder sogar Korrektheit gewinnen könnte.

Einfaches Leistungsbeispiel: Protokollierung. Stellen Sie sich eine solche Schnittstelle vor:

%Vor%

Und dann so benutzt:

%Vor%

Wenn die info -Methode nichts bewirkt (weil zum Beispiel die Protokollierungsstufe für einen höheren Wert konfiguriert wurde), wird computeTimeSpent niemals aufgerufen, wodurch Zeit gespart wird. Dies passiert häufig bei Loggern, bei denen häufig eine String-Manipulation beobachtet wird, die relativ zu den zu protokollierenden Aufgaben teuer sein kann.

Korrektheitsbeispiel: logische Operatoren.

Sie haben wahrscheinlich Code wie folgt gesehen:

%Vor%

Angenommen, Sie haben && methode wie folgt deklariert:

%Vor%

Wenn ref dann null ist, erhalten Sie einen Fehler, weil isSomething für eine null Referenz aufgerufen wird, bevor sie an && übergeben wird. Aus diesem Grund lautet die tatsächliche Deklaration:

%Vor%

Man könnte sich also fragen, wann Call-by-Value zu verwenden ist. In der Programmiersprache Haskell funktioniert alles ähnlich wie Call-by-Name funktioniert (ähnlich, aber nicht gleich).

Es gibt gute Gründe, Call-by-Name nicht zu verwenden: es ist langsamer, es erzeugt mehr Klassen (das Programm braucht länger zum Laden), es verbraucht mehr Speicher und es ist anders genug, dass viele sich schwer darüber Gedanken machen können es.

    
Daniel C. Sobral 26.09.2013, 18:37
quelle
6

Call by name bedeutet, dass der Wert zum Zeitpunkt des Zugriffs ausgewertet wird, während bei call by value der Wert zuerst ausgewertet und dann an die Methode übergeben wird.

Um den Unterschied zu sehen, betrachten Sie dieses Beispiel (vollständig nicht-funktionale Programmierung mit nur Nebenwirkungen;)). Angenommen, Sie möchten eine Funktion erstellen, die misst, wie viel Zeit eine Operation benötigt. Sie können es mit Call-by-Name tun:

%Vor%

Sie erhalten das Ergebnis (YMMV):

%Vor%

Wenn Sie jedoch nur die Signatur von measure in measure(action: Unit) so ändern, dass sie den Wert "pass-by-value" verwendet, lautet das Ergebnis:

%Vor%

Wie Sie sehen, wird action ausgewertet, bevor measure gerade startet, und auch die verstrichene Zeit liegt nahe bei 0, da die Aktion bereits ausgeführt wurde, bevor die Methode aufgerufen wurde.

Hier ermöglicht Pass-by-Value, das erwartete Verhalten der Methode zu erreichen. In einigen Fällen hat dies keinen Einfluss auf die Korrektheit, hat aber Einfluss auf die Performance, zum Beispiel bei der Protokollierung von Frameworks, bei denen ein komplexer Ausdruck möglicherweise gar nicht ausgewertet werden muss, wenn das Ergebnis nicht verwendet wird.

    
Michał Kosmulski 26.09.2013 19:19
quelle
4

Die einfachste Art, es zu erklären, ist

  

call-by-value-Funktionen berechnen den Wert des übergebenen Ausdrucks   vor dem Aufruf der Funktion wird also auf den gleichen Wert zugegriffen   Zeit. Call-by-Name-Funktionen berechnen jedoch den übergebenen Wert neu   Ausdruckswert bei jedem Zugriff.

Ich habe immer gedacht, dass diese Terminologie unnötig verwirrend ist. Eine Funktion kann mehrere Parameter haben, die sich in ihrem Call-by-Value-Status und ihrem Call-by-Name-Status unterscheiden. Es ist also nicht so, dass eine Funktion Call-by-Name oder Call-by-Value ist, sondern dass jeder seiner Parameter Pass-by-Name oder Pass-by-Value sein kann. Außerdem hat "call-by-name" nichts mit Namen zu tun. = & gt; Int ist ein anderer Typ als Int; es ist "Funktion von keinen Argumenten, die ein Int erzeugen" vs nur Int. Sobald Sie erstklassige Funktionen haben, müssen Sie nicht die Namen von Anrufen nach Namen erfinden, um dies zu beschreiben.

    
Xenalin 26.09.2013 18:10
quelle
0

Wenn ein Parameter namens call-by-name mehr als einmal in einer Funktion verwendet wird, wird der Parameter mehrmals ausgewertet.

Da der übergebene Parameter ein reiner Funktionsaufruf pro funktionaler Programmierung sein sollte, erzeugt jede Auswertung innerhalb der aufgerufenen Funktion immer das gleiche Ergebnis. Call-by-Name wäre daher verschwenderischer als der herkömmliche Call-by-Value.

    
T Cheng 29.01.2017 22:57
quelle

Tags und Links