2016-12-08 4 views
0
increment([]) -> []; 
increment([H|T]) -> [H+1|increment(T)]. 

decrement([]) -> []; 
decrement([H|T]) -> [H-1|decrement(T)]. 

Also ich habe diesen Code, aber ich weiß nicht, wie sie richtig funktionieren wie in Java.Was sind die Schritte bei der Inkrementierung von Erlang?

+0

Ziemlich viel wie es in Ihrer ähnliche Frage bereits beschrieben: http://stackoverflow.com/questions/41008186/how-does-a-loop-simulation-works Sie fragen sich, wie sie sich unterscheiden? –

+0

Ja, ich bin wirklich verwirrt T^T –

Antwort

2

Java und Erlang sind verschiedene Bestien. Ich empfehle nicht, beim Lernen von Erlang zu versuchen, Vergleiche mit Java anzustellen, besonders wenn Java die einzige Sprache ist, die Sie bisher kennen. Der Code, den Sie gepostet haben, ist ein gutes Beispiel für das Paradigma, das als "funktionale Programmierung" bekannt ist. Ich würde vorschlagen, etwas zu diesem Thema zu lesen, um zu verstehen, was vor sich geht. Um zu versuchen, dies so weit wie Erlang geht zu brechen, müssen Sie verstehen, dass eine Erlang-Funktion völlig anders ist als eine Java-Methode.

In Java besteht Ihre Methodensignatur aus dem Methodennamen und den Typen seiner Argumente. Der Rückgabetyp kann ebenfalls signifikant sein. Eine Java-Methode increment wie die Funktion, die Sie geschrieben haben, könnte wie List<Integer> increment(List<Integer> input) geschrieben werden. Der Körper der Java-Methode wäre wahrscheinlich ein Element zu einem Zeitpunkt durch die Liste durchlaufen und jedes Element auf mich selbst gesetzt plus eins:

List<Integer> increment(List<Integer> input) { 
    for (int i = 0; i < input.size; i++) { 
     input.set(i, input.get(i) + 1); 
    } 
} 

Erlang gemeinsam fast nichts mit diesem. Die "Signatur" einer Erlang-Funktion ist zunächst der Name und die Funktion der Funktion. Arity bedeutet, wie viele Argumente die Funktion akzeptiert. Also Ihre Inkrement-Funktion ist bekannt als increment/1, und das ist ihre einzigartige Signatur. Die Art und Weise, wie Sie die Argumentliste innerhalb der Klammern nach dem Funktionsnamen schreiben, hat weniger mit Argumenttypen zu tun als mit dem Muster der Daten, die an sie übergeben werden. Eine Funktion wie increment([]) -> ... kann nur erfolgreich aufgerufen werden, indem Sie die leere Liste [] übergeben. Ebenso kann die Funktion increment([Item]) -> ... nur erfolgreich aufgerufen werden, indem eine Liste mit einem Element darin übergeben wird und increment([Item1, Item2]) -> ... eine Liste mit zwei Elementen übergeben werden muss. Dieses Konzept des Abgleichs von Daten mit Mustern wird sehr treffend als "Mustervergleich" bezeichnet und Sie finden es in vielen funktionalen Sprachen. In Erlang-Funktionen wird gewählt, welcher Kopf der Funktion ausgeführt werden soll. Dies ähnelt in etwa der Java-Methode, bei der Sie viele Methoden mit demselben Namen, aber unterschiedlichen Argumenttypen verwenden können. Ein Muster in einem Erlang-Funktionskopf kann jedoch Variablen an verschiedene Teile der Argumente binden, die mit dem Muster übereinstimmen.

In Ihrem Codebeispiel hat die Funktion increment/1 zwei Köpfe. Der erste Kopf wird nur ausgeführt, wenn Sie der Funktion eine leere Liste übergeben. Der zweite Kopf wird nur ausgeführt, wenn Sie eine nicht leere Liste an die Funktion übergeben. Wenn das passiert, sind zwei Variablen, H und T, gebunden. H ist an das erste Element der Liste gebunden, und T ist an den Rest der Liste gebunden, was alles außer dem ersten Element bedeutet. Das liegt daran, dass das Muster [H|T] mit einer nicht leeren Liste übereinstimmt, die eine Liste mit einem Element enthält. In diesem Fall wäre T an die leere Liste gebunden. Die so gebundenen Variablen können im Körper der Funktion verwendet werden.

Die Körper Ihrer Funktionen sind eine sehr typische Form der Iteration einer Liste in Erlang, um eine neue Liste zu erstellen. Es ist typisch für einen weiteren wichtigen Unterschied zu Java, dass Erlang-Daten unveränderlich sind. Das bedeutet, dass es kein Konzept wie "Setzen eines Elements einer Liste" wie im obigen Java-Code gibt. Wenn Sie eine Liste ändern möchten, müssen Sie eine neue erstellen, was Ihr Code tut. Es sagt effektiv:

  • Das Ergebnis der Erhöhung der leeren Liste ist die leere Liste.
  • das Ergebnis einer nicht-leere Liste Inkrementieren ist:
    • Nehmen Sie das erste Element der Liste: H.
    • Erhöhen Sie den Rest der Liste: increment(T).
    • Prepend H+1 auf das Ergebnis den Rest der Liste erhöht wird.

Beachten Sie, dass Sie vorsichtig sein wollen, wie Sie Listen in Erlang bauen, oder Sie können eine Menge von Ressourcen am Ende verschwenden. Die List Handling User's Guide ist ein guter Ort, um darüber zu lernen. Beachten Sie auch, dass dieser Code ein Konzept verwendet, das als "Rekursion" bezeichnet wird, was bedeutet, dass die Funktion sich selbst aufruft. In vielen populären Sprachen, darunter Java, ist Rekursion von begrenztem Nutzen, da jede neue Funktionsaufruf einen Stack-Frame hinzufügt und Ihren verfügbaren Speicherplatz für Stapelrahmen ist relativ begrenzt. Erlang und viele funktionalen Sprachen unterstützen eine Sache als „Endaufruf elimination“ bekannt, die eine Funktion ist, die korrekt geschriebener Code erlaubt unbegrenzt zu Rekursion ohne Ressourcen zu erschöpfen.

Hoffentlich hilft diese Dinge zu erklären. Wenn Sie eine spezifischere Frage stellen können, erhalten Sie möglicherweise eine bessere Antwort.

Verwandte Themen