2012-06-10 7 views
9

Also habe ich begonnen, Erlang zu lernen, und ich bin ein wenig verwirrt mit diesem Stück Code.Selektives Empfangen in Erlang

-module(prior). 
-compile(export_all). 


    important() -> 
     receive 
    { Priority, Msg } when Priority > 10 -> 
     [Msg | important()] 
    after 0 -> 
    normal() 
    end. 

normal() -> 
    receive 
    { _, Msg } -> 
     [Msg | normal()] 
    after 0 -> 
     [] 
    end. 

Ich rufe den Code mit.

10> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}. 
    {17,high} 
    11> prior:important(). 
     [high,high,low,low] 

Ich verstehe, dass dieser Code zuerst alle Nachrichten mit hoher Priorität und dann die mit niedriger Priorität durchlaufen wird. Ich bin verwirrt, wie der Rückgabewert [hoch, hoch, niedrig, niedrig] ist, da ich nicht sehe, wo sie miteinander verkettet sind.

+1

Nicht verkettet, consed. Verkettung ist, wenn Sie zwei Listen haben, "L1" und "L2" und verketten Sie sie: "L1 ++ L2". Consing ist, wenn Sie ein Element 'E' und eine Liste' L' haben und dann die erweiterte Liste '[E | bilden L] '. –

Antwort

14

Wie der letzte Rückgabewert aufgebaut ist ...

Wenn [Msg | important()] zum ersten Mal zurückgegeben wird, wird die Form des endgültigen Rückgabewert bestimmt wird. Die einzige Sorge ist, dass wir noch nicht alle Details des endgültigen Rückgabewerts kennen. So wird die important() in der [Msg | important()] weiterhin ausgewertet werden. Die folgende Abbildung zeigt, wie der endgültige Rückgabewert [high,high,low,low] erstellt wird.

[high | important(     )] <---- Defines the final form 
     --------------------------------- 
     [high | important(   )] <---- Adds more details 
       ------------------------ 
       normal(    ) <---- Adds more details 
       ------------------------ 
       [low | normal(  )] <---- Adds more details 
         ---------------- 
         [low | normal()]  <---- Adds more details 
           -------- 
           [  ]  <---- Adds more details 
------------------------------------------ 
[high | [high | [low | [low | []]]]] 
[high,high,low,low]       <---- The final return value 

Wie der Code funktioniert ...

In Funktion important/0 bedeutet after 0 einfach: „Ich warte nicht auf Nachrichten kommen“ - wenn es eine Nachricht in meinem Briefkasten, ich werde es anschauen; Wenn es keine gibt, werde ich weitermachen (execute normal()), anstatt dort zu warten.Im Postfach befinden sich {15, hoch}, {7, niedrig}, {1, niedrig}, {17, hoch} sitzen dort schon. In Erlang sind die Nachrichten in der Mailbox Nicht in der Reihenfolge der Reihenfolge, in der sie zuerst eingehen. Die Klausel receive kann wählerisch sein. Es durchsucht alle Nachrichten in der Mailbox und "wählt" die gewünschten aus. In unserem Fall werden {15, hoch} und {17, hoch} zuerst nach {Priority, Msg} when Priority > 10 ausgewählt werden. Danach übernimmt die Funktion normal/0. Und {7, niedrig}, {1, niedrig} werden verarbeitet (consed) in der Reihenfolge. Schließlich haben wir [high,high,low,low].

Eine modifizierte Version, die die Verarbeitungsreihenfolge enthüllt ...

wir den Code ein wenig modifizieren, kann die Verarbeitung (consing), um deutlicher zu machen:

-module(prior). 
-compile(export_all). 

important() -> 
    receive 
    {Priority, Msg} when Priority > 10 -> 
     [{Priority, Msg} | important()] % <---- Edited 
    after 0 -> 
    normal() 
    end. 

normal() -> 
    receive 
    {Priority, Msg} -> % <---- Edited 
     [{Priority, Msg} | normal()] % <---- Edited 
    after 0 -> 
     [] 
    end. 

Run es in der Schale:

4> c(prior). 
{ok, prior} 
5> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}. 
{17,high} 
6> prior:important(). 
[{15,high},{17,high},{7,low},{1,low}] 
+2

Ich schrieb den Code der OP gefragt (Ich glaube, das ist meine Priorität erhalten in Learn You Some Erlang) und ich stimme dieser Antwort. –

4

sie hier

[Msg | important()] 

diese important() ist eine Funktion concated, so dass es einen Rückgabewert hat, während Sie dies in REPL läuft er Rückgabewert aus der Funktion gedruckt wird. Dieser Wert ist der Effekt [Head | Tail] Liste Gebäude aus import()

important() hier eine reguläre Funktion ist :)

Ist es hilfreich?

+0

Danke für die schnelle Antwort. Daher werden selbst die Nachrichten mit niedriger Priorität, die von dem Aufruf von normal() nach empfangen werden, mit der Liste hoher Priorität in der [Msg | verkettet wichtig()] -Klausel? – tkblackbelt

+0

alles. Auch wird es wahrscheinlich Ihren Flam überfluten, wenn Sie wie viele Nachrichten haben, so sollten Sie es in Tail Recursive-Funktion zu konvertieren. Ich weiß nicht, was Sie versuchen zu bauen, weil es im Allgemeinen ein gen_server mit einer Priorität als interne Datenstruktur sein sollte. Sie versuchen, es innerhalb einer Prozessnachricht que zu tun, und dieses Ding ist begrenzt, also ist es schlechte Idee im Allgemeinen. –

2

Alle Erlang-Funktionen geben immer einen Wert zurück. Die Funktion important/0 empfängt eine Nachricht mit hoher Priorität und ruft sich dann rekursiv in dem Ausdruck [Msg | important()] auf, der eine Liste erstellt, die die letzten Msg und alle anderen Nachrichten enthält, die important/0 empfangen werden. Es ist diese Liste, die von important/0 zurückgegeben wird. Wenn keine Nachrichten mit hoher Priorität mehr vorhanden sind, ruft important/0 stattdessen normal/0 auf, um alle verbleibenden Nachrichten zu lesen. Die Nachrichten, die normal/0 liest, werden als eine Liste in der gleichen Weise important/0 zurückgegeben. Dies wird an important/0 zurückgegeben, die es dann in der gleichen Liste zurückgibt, wie es seine Nachrichten zurückgegeben hat.

Beachten Sie, dass, sobald normal/0 aufgerufen wurde, es keine spezielle Behandlung von Nachrichten mit hoher Priorität gibt, da important/0 nie wieder aufgerufen wird. Auch important/0 verarbeitet wirklich nur die Nachrichten mit hoher Priorität, die sich bereits in der Warteschlange befinden, da es, sobald es nicht mehr findet, normal/0 aufruft.

Der Timeout-Wert 0 ist insofern speziell, als er sofort abläuft, aber garantiert, dass zuerst die gesamte Nachrichtenwarteschlange nach übereinstimmenden Nachrichten durchsucht wird.