2017-10-22 1 views
3
fun({0, M}) -> {M+1, M-2}; 
fun({N, M}) -> 
{A, B} = fun({N-1, M+1}), 
      {B, A+1}. 

Ich bin mir also nicht sicher, was das A und B wäre und wie der nächste rekursive Aufruf wäre. sagen wir 2,2Wie funktioniert der rekursive Aufruf in dieser Erlang-Funktion?

so wäre es

f(2,2) -> {A,B} = fun({1,3}), {B,A+1} 
f(1,3) -> {A,B} = fun({0,4}), {B,A+1} 
f(0,4) -> {5,2} 

sein, aber wo kommt A und B gehen und tun sie in jedem rekursiven Aufruf ändern?

+0

Jeder Anruf ein neuer Kontext ist - Die Ausnahme ist, wenn Sie einen externen Zustand absichtlich schließen. Ziehen Sie eine etwas allgemeinere Erklärung für einige rekursive Idiome in Betracht: [Erklärung der Listen: Faltfunktion] (https://stackoverflow.com/questions/26854586/explanation-of-listsfalt-function/26855055#26855055) – zxq9

Antwort

2

Sie müssen nur wieder nach oben:

f({1, 3}) -> {A, B} = {5, 2}, {B, A+1} -> {2, 6} 
f({2, 2}) -> {A, B} = {2, 6}, {B, A+1} -> {6, 3} 

(beachten Sie, dass fun ist ein Schlüsselwort in Erlang und dass f(N,M) ist nicht das gleiche wie f({N,M}))

und tun sie in jeder Änderung rekursiver Aufruf

Ja, wie Sie sehen können.

3

Als sehr grundlegende Erklärung von „wo ist meine Variable“, die Countdown-Funktion in diesem Beispiel Modul betrachten:

Wenn wir den Basisfall getroffen, die 0 ist, wir dann halt. Der Rückgabewert der Funktion insgesamt ist das Atom ok (denn das ist der Rückgabewert eines erfolgreichen Aufrufs an io:format/2).

Wenn der Eingang größer ist als 0 ist, dass wir auf der zweiten Klausel dann übereinstimmen, das heißt, wir weisen Sie N die einzige Eingabeargument für diese bestimmte Iteration. Als nächstes machen wir unseren Output Call. Dann weisen wir Next dem Wert N - 1 zu. Dann rufen wir dieselbe Funktion erneut auf (eine Schleife ausführen), indem wir den Wert Next im Rumpf des aktuellen Aufrufs als Eingabeargument verwenden. Die nächste Iteration Alle Variablen sind völlig neu, da dies ein neuer Ausführungskontext ist. Die alten N und Next sind nicht mehr vorhanden. Tatsächlich gibt es kein Ereignis auf einem Stapel irgendwo, weil Erlang "tail call optimization" verwendet, um rekursive Tail-Aufrufe in constant space zu pflegen, genauso wie die meisten anderen Sprachen eine explizite for oder while oder do while oder [Formular einfügen].

Wie Alexy darauf hinweist, seien Sie vorsichtig mit dem Token fun - es ist ein Schlüsselwort in Erlang, kein Name einer legalen Funktion. Es ist der Nicht-Name einer anonymous function (auch bekannt als lambda). Mit anderen Worten: Wenn Sie keine Bezeichnung angeben, lautet der Name jeder anonymen Funktion einfach fun.

fun ist auch das Schlüsselwort, das verwendet wird, um eine Funktion nach Label (als Wert selbst) zu referenzieren, anstatt sie aufzurufen. Zum Beispiel ruft countdown(10) die obige Funktion mit einem Argument von 10 auf. Referenzieren Die Funktion als fun countdown/1 gibt die Funktion selbst als Wert zurück.Das ist, nebenbei, warum die Funktion Export-Deklaration an der Spitze des Moduls als -module([countdown/1]) geschrieben wird, denn das ist der explizite Name dieser Funktion. Bedenken Sie:

1> c(example). 
{ok,example} 
2> example:countdown(2). 
Counting down in: 2 
Counting down in: 1 
Blastoff! 
ok 
3> Countdown = fun example:countdown/1. 
#Fun<example.countdown.1> 
4> Countdown(2). 
Counting down in: 2 
Counting down in: 1 
Blastoff! 
ok 

Während ich zu diesem Thema bin ...

Erlang hat nur sehr wenige Keywords im Vergleich zu den meisten Sprachen (und sehr wenig Syntax, tatsächlich). Hier ist the list of reserved words:

nach und andalso Band beginnen bnot bor bsl bsr BXOR Fall fangen cond div Spaß Ende, wenn wir nicht von oder orelse rem Versuch erhalten, wenn xor

Verwandte Themen