Was ist „pass-by-name“ und wie es genau funktioniert?
-
10-07-2019 - |
Frage
Ich habe wikipedia überprüfen und gegoogelt, aber ich kann immer noch nicht meine Meinung umschlingen, wie Pass-by-name arbeitet in Algol 60.
Lösung
fand ich eine gute Erklärung unter Pass-By-Name Parameter Passing . Im Wesentlichen ist der Körper einer Funktion zum Aufrufzeitpunkt interpretiert nach textlich den aktuellen Parametern in den Funktionskörper ersetzt wird. In diesem Sinne ist die Bewertungsmethode des von C Präprozessormakros ähnlich.
Durch die aktuellen Parameter in den Funktionskörper ersetzt, kann die Funktion Körper sowohl Lese- als auch die angegebenen Parameter schreiben. In diesem Sinne ist das Auswerteverfahren ähnlich Pass-by-reference. Der Unterschied besteht darin, dass, da mit Pass-by-namen die Parameter ist ausgewertet in der Funktion, ein Parameter wie a[i]
auf dem aktuellen Wert von i
innerhalb der Funktion abhängt, anstatt bei a[i]
auf den Wert bezieht bevor die Funktion aufgerufen wurde.
Die Seite, die ich oben verlinkt hat einige weitere Beispiele, wo Pass-by-Name ist sowohl nützlich und gefährlich. Die Techniken, ermöglicht durch den Pass-by-Namen heute durch andere, sicherere Techniken wie Pass-by-reference und Lambda-Funktionen weitgehend ersetzt werden.
Andere Tipps
Ich nehme an, Sie meinen Call-by-Name in Algol 60.
Call-by-Name ist ähnlich wie bei Call-by-reference, dass Sie den Wert der übergebenen Parameter ändern können. Es unterscheidet sich von Call-by-reference, dass der Parameter ist nicht ausgewertet, bevor die Prozedur aufgerufen wird, sondern stattdessen faul ausgewertet. Das heißt, es wird ausgewertet, wenn und nur wenn der Parameter tatsächlich verwendet wird.
Angenommen, wir ein Verfahren f(x, y)
haben und wir geben es i
und i/2
wo i
anfänglich gleich 10
. Wenn f
Sätze x
42
und wertet dann y
wird der Wert 21
(während bei Aufruf durch Referenz oder rufen Sie von Wert wäre es immer noch 5
sehen) sehen. Dies ist, weil der Ausdruck i/2
wird nicht ausgewertet, bis y
ausgewertet wird.
In vielerlei Hinsicht erscheint dies wie ein normaler Text-Substitution der Parameter zu verhalten (mit Umbenennung Namenskonflikte zu vermeiden). In der Praxis wird dies jedoch in der Ausdrücken für die bestandenen (im Wesentlichen Schließungen) mit „Thunk“ implementiert.
Der Wikipedia-Artikel über Jensen Geräte einige interessante Beispiele zeigt Aufruf der Verwendung von Namen . Hier ist einer von ihnen:
real procedure Sum(k, l, u, ak) value l, u; integer k, l, u; real ak; comment k and ak are passed by name; begin real s; s := 0; for k := l step 1 until u do s := s + ak; Sum := s end;
In dem Verfahren wird die Indexvariable
k
und Summen Begriffak
sind namentlich übergeben. Call-by-Name ermöglicht das Verfahren den Wert zu ändern der Indexvariablen während der Ausführung der for-Schleife. Call-by-Name auch bewirkt, dass dasak
Argument bei jeder Iteration neu bewertet werden die Schleife. Typischerweiseak
hängt von der Änderung (Neben bewirkt wird)k
.Zum Beispiel Code, um die Summe der ersten 100 Bedingungen eines realen zu berechnen Array
V[]
wäre:Sum(i, 1, 100, V[i]).
Für die in der Zukunft:
Konzepte in Programmiersprachen von John C. Mitchell war auch hilfreich.
Pass-by-Namen . Vielleicht ist die seltsamste Merkmal von Algol 60, im Nachhinein ist die Verwendung von Pass-by-Namen. Im Pass-by-name, das Ergebnis eines Prozeduraufruf ist das gleiche, als ob die formale Parameter wurden in substituieren der Körper des Verfahrens. Diese Regel für das Ergebnis eines Verfahrens definierte aufrufen, indem Sie den Vorgang kopieren und Substitution für die formalen Parameter wird die Algol 60 Kopierregel genannt. Obwohl die Kopie funktioniert Regel gut für rein funktionalen Programme, wie durch Reduktion der β lambda illustriert Zahnstein, die Interaktion mit Seiten Auswirkungen auf den formalen Parameter sind ein bisschen komisch. Hier ist ein Beispiel Programm eine Technik zeigt, bezeichnet als Jensen Gerät: ein Passieren Expression und eine Variable enthält , dass das Verfahren zu einem Verfahren so kann einen Parameter verwenden, die sich ändern Lage auf die sich die anderen:
begin integer i; integer procedure sum(i, j); integer i, j; comment parameters passed by name; begin integer sm; sm := 0; for i := 1 step 1 until 100 do sm := sm + j; sum := sm end; print(sum(i, i*10 )) end
In diesem Programm wird das Verfahren Summe (i, j) addiert die Werte von j, wie ich oben geht von 1 bis 100. Wenn Sie das sehen Code, werden Sie feststellen, dass die Verfahren macht keinen Sinn, es sei denn, Änderungen i einige Veränderungen verursachen in der Wert von j; sonst wird das Verfahren nur berechnet 100 * j. Im Aufruf sum (i, i 10 *) hier gezeigt ist, die for-Schleife in dem Körper der Prozedur Summe aufaddiert der Wert von i * 10 als i von 1 geht an 100.
Eigentlich Call-by-Name, ist nicht nur eine historische Kuriosität. Sie können Sie Call-by-Name in Windows Batch-Dateien (und andere Skriptsprachen Myriaden). Zu wissen, wie es funktioniert und wie es effektiv zu nutzen, in der Programmierung kann saubere Lösungen für Probleme öffnen. Ich weiß, es ist nur Zeichenketten durch für eine spätere Expansion vorbei, aber es kann manipuliert werden, um ähnliche Effekte wie Call-by-Namen haben.
call :assign x 1
exit /b
:assign
setlocal enabledelayedexpansion
(endlocal
:: Argument 1 is the name of the variable
set %1=%2
)
exit /b
hat ein Beleuchtungsflatlander Beispiel dafür, wie es funktioniert in Scala hier . Angenommen, Sie implementieren wollten , während :
def mywhile(condition: => Boolean)(body: => Unit): Unit = if (condition) { body mywhile(condition)(body) }
Wir können das nennen wie folgt:
var i = 0 mywhile (i < 10) { println(i) i += 1 }
Scala ist nicht Algol 60, aber vielleicht wirft es ein Licht.
Sie können „name“ in der symbolischen Form einer Variable übergeben, die sie beide gleichzeitig aktualisiert und abgerufen werden können. Als Beispiel kann sagen, dass Sie eine Variable x verdreifachen wollen, das vom Typ int ist:
start double(x);
real x;
begin
x : = x * 3
end;
Algol wurde für mathematische Algorithmen entwickelt. Ich mag die Summenfunktion als Beispiel für Anruf mit Namen.
Leider mein Algol ist ein bisschen rostig die Syntax ist wahrscheinlich nicht richtig.
.FUNCTION SUM(var,from,to,function)
.BEGIN
.REAL sum =0;
.FOR var = from .TO to .DO sum = function;
return sum;
.END
Sie können als Summe verwenden wie
Y = sum(x,1,4,sum(y,3,8,x+y));
In dem oberhalb dem inneren sum (y, 3,8, x + y) würde eine unbenannte Funktion erzeugen, um den äußeren sum Anruf zu übergeben. Die Variablen x und y sind nicht von Wert übergeben, sondern nach dem Namen. Im Fall von Variablen mit Namen nennen, ist äquivalent mit Adreßverweis in C aufrufen Es wird ein wenig verwirrend, wenn Rekursion beteiligt ist.
leiht Algol Maschinen. Sie hatten 48-Bit-Wortspeicher mit 3 Merkerbits. Der Flag-Bits implementiert, um die cal namentlich von Algol. es war so eine Stapelmaschine, wenn die Funktion auf den Stapel geladen wurde der Ruf nach Namen fag verursachen würde es heißen. Der Compiler würde unbenannte Funktionen erzeugen, wenn Ausdrücke als Argumente verwendet wurden. Eine Variable wäre ein einfacher indirekter Bezug. Ein Fehler auftreten würde, auf eine Funktion zu schreiben.
Ich weiß, ich bin spät, um den Club beitreten und dies ist nicht unbedingt eine Antwort, aber ich wollte nur etwas hinzufügen, die ein wenig klären helfen könnten. Ich habe immer gedacht, die Algol Pass-by-Namen als einen ähnlichen Prozess wie bei der C ++ Präprozessordirektiven (Makros, speziell) ersetzt den Namen einer Funktion / Variable mit dem eigentlichen Stück Code während der Kompilierung. Die Pass-by-Name ersetzt im Wesentlichen den Namen des formalen Parameters mit dem aktuellen Parameter und führt. Ich habe noch nie in Algol geschrieben, aber ich höre, dass Pass-by-name das gleiche Ergebnis wie C ++ 's Pass-by-reference hat.