2009-07-14 5 views
9

Ich schreibe eine Erlang-Funktion, die jede gerade Zahl bis zu einem bestimmten Parameter druckt.Gibt es in Erlang eine Möglichkeit, eine leere Funktion zu erstellen?

Bisher habe ich die Funktion mit Wache wie folgt geschrieben:

printEven(I,N) when I < N -> 
    if 
    I rem 2 == 0 -> io:format("~p~n",[I]), printEven(I+1,N); 
    I rem 2 == 1 -> printEven(I+1,N) 
    end; 
printEven(I,N) -> 
    io:format("Done"). 

ich wirklich den letzten Fall möge nur haben, automatisch verlassen und nicht alles in der Funktion zu drucken. Ich habe versucht, es nur zu entfernen, aber dann tritt ein Fehler auf, seit wann die Rekursion beendet ist, wird ein Fehler ausgelöst.

Wie kann ich das tun? Gibt es in Erlang so etwas wie ein 'pass' oder 'yield' Keyword?

+0

Umm, dieser Code kann nicht kompilieren - die erste Klausel müsste mit einem Semikolon enden, nicht mit einem Punkt. Laufen Sie es in der Shell? Wenn Sie dann sind, wird es immer drucken, was es zurückgibt, und es gibt immer etwas zurück. Wenn Sie es nicht in der Shell ausführen, dann lassen Sie einfach das io: format ... –

Antwort

11

OK, definieren zunächst die Funktion:

printEven(I,N) when I >= N -> ok; 
printEven(I,N)    -> 
    if 
    I rem 2 == 0 -> io:format("~p~n",[I]), printEven(I+1,N); 
    I rem 2 == 1 -> printEven(I+1,N) 
    end. 

Erlang eine funktionale Programmiersprache ist und (per Definition) Funktionen 'haben' einen Wert, so dass Sie 'etwas' zurück gehen zu bekommen. Per Konvention ist das Atom, das Sie bei der Fertigstellung einer Funktion, die Sie für Nebenwirkungen verwenden, zurückbekommen, ok ', das ist das Beste, das Sie hier verwenden können.

Sie können den Rückgabewert "stillschweigend verwerfen", wenn Sie möchten. Sie tun das, wenn Sie die Funktion durch Muster auf die Variable Anpassung aufrufen ‚do not care‘ (der Unterstrich ist):

_ = printEven(3,9), 

oder durch die Funktion ohne Mustererkennung Aufruf:

printEven(3,9), 

Sie sind jedoch viel besser, immer Rückgabewerte durch Musterabgleich zu überprüfen, wenn Sie eine Funktion aufrufen:

ok = printEven(3,9), 

Dies ist eine wirklich gute Gewohnheit zu bekommen, weil Sie eine Menge lib verwenden rary Funktionen, die Fehlercodes zurück, wie Sie von ihren Spezifikationen sehen:

@spec funky(X) -> [ok | {error, bad_op} | {error, wig_out}] 

Wenn flippige Effekte hat Seite wollen Sie wissen, es jetzt indem sie sie mit einem Muster übereinstimmen Aufruf fehlgeschlagen ist, so dass es hier zum Absturz und jetzt, wenn flippig ausfällt:

ok = funky(99), 

wenn Sie es '_' übereinstimmen oder den Rückgabewert ignorieren wird es 268 Zeilen später abstürzen, wenn Ihr mojo flippige erwartet seine thang getan zu haben, und dann ist es viel schwerer zu finden.

Dies ist glückliche Pfad-Programmierung, die das Erledigt in Erlang ist. "Lass es krachen" ist das Motto. Wenn Sie Erlang neu sind, werden Sie das sehr beunruhigend finden - wie nackt herumlaufen. Mach dir keine Sorgen, es ist eine gute Sache. Es führt zu viel Code 'nicht geschrieben'.

(Sie sollen auch in der Gewohnheit, die Klausel des Setzens, die die Rekursion als Top-Klausel endet, wie hier gezeigt - es macht den Code zu lesen sooo viel einfacher, wenn Sie eine Multi-Klausel Funktion.)

+0

Eigentlich ist dieser Code nicht hübsch genug, der zweite Satz sollte geschrieben werden als: printEven (I, N) -> _ = wenn ich rem 2 == 0 -> io: format ("~ p ~ n", [ICH]); I rem 2 == 1 -> ok% drucken nichts Ende, printEven (I + 1, N); Bedenken Sie, dass die If-Klausel einen Wert zurückgibt - Sie würden es wahrscheinlich in diesem Fall nicht übereinstimmen, aber ich steckte in das Spiel, um Sie daran zu erinnern, dass es tut :) –

+0

Nur können Sie Dinge schöner machen, indem Sie vermeiden zu schreiben Der rekursive Funktionsaufruf zweimal, Sie können die Dinge hübscher machen, indem Sie vermeiden, zweimal "I rem 2" mit einer case-Anweisung zu schreiben. Siehe meine Antwort. – 7stud

1

Ich glaube, das Schlüsselwort "ok"

4

nur ein Atom zurück.

printEven (I, N) -> fertig.

sollte es tun.

+0

Ich möchte nicht ein Atom zu drucken, nur die Zahlen im Text. – samoz

+0

ein Atom wird nicht gedruckt. es wird nur die Schleife stoppen. –

+0

Ich sollte klarstellen, sollten Sie beachten, dass der Rückgabewert von printEven nie verwendet wird, so dass Sie alles zurückgeben können, die einen rekursiven Aufruf nicht enthält. –

2

Sie könnten den Test auch für die Schutzklausel kombinieren. Ich bevorzuge auch den Done Atom Trick - es zeigt in Ihrem Code, dass es die Funktionsklausel ist, die die "Rekursion" stoppt.

printEven(I, N) when I<N, I rem 2 == 0 -> 
    io:format("~p is even~n", [I]), 
    printEven(I+1, N); 
printEven(I,N) when I<N -> 
    printEven(I+1, N); 
printEven(I,N) -> 
    done. 
+0

Gibt es eine Möglichkeit, still zu gehen? Ohne ein Atom? – samoz

+2

Nein - alle Funktionen geben einen Wert zurück. Sie testen nicht den Wert der Funktion, also bin ich mir nicht sicher, warum es für Sie wichtig ist? –

0
printEven(Start, Stop) when Start =< Stop -> 
    case Start rem 2 of 
     0 -> io:format("~p~n", [Start]); %returns ok 
     _ -> do_nothing 
    end, 
    printEven(Start+1, Stop); 
printEven(Start, Stop) when Start > Stop -> 
    ok. 

der Wert der Fall Aussage ist entweder ok oder do_nothing, aber der Fall Aussage ist nicht der letzte Ausdruck, so dass es Wert ist der Rückgabewert für die erste Klausel der Funktion nicht sein, und weil der Wert Ist der Case-Ausdruck nicht an eine Variable gebunden, wird der Wert einfach verworfen.

Der letzte Ausdruck in der ersten Klausel Funktion ist tatsächlich printEven(Start+1, Stop), und dass Funktionsaufruf wird Rückkehr ok Ende, sobald der Rekursion das Ende der Sequenz erreicht und führt printEven(Start, Stop) when Start > Stop -> ok;

printEven(1, 3) => ? 
        | 
        V 
      printEven(2, 3) => ? 
           | --side effect: output 2 
           V 
         printEven(3, 3) => ? 
              | 
              V 
             printEven(4, 3) => ok 

Füllung in den Rückgabewert für jede Funktion Aufruf der Kette gibt:

printEven(1, 3) => ok 
        ^
        | 
       printEven(2, 3) => ok 
           ^
           | 
         printEven(3, 3) => ok 
              ^
              | 
             printEven(4, 3) => ok 
-1

Dies würde es tun:

printEven(I,N) -> ok. 
Verwandte Themen