Az Elixirben minden kód folyamatokon belül fut.
Alapértelmezés szerint egy függvény ugyanabban a folyamatban fut le, amelyből meghívták. Ha egy adott függvényt kifejezetten egy új folyamatban szeretnél futtatni, használd a spawn/1-et:
spawn(fn -> 2 + 2 end)
# => #PID<0.125.0>
A spawn/1 létrehoz egy új folyamatot, amely lefuttatja a megadott 0 aritású függvényt, és visszaad egy folyamatazonosítót (PID). Az új folyamat mindaddig életben marad, amíg a függvény le nem fut, majd csendben kilép.
Az Elixir folyamatait nem szabad összekeverni az operációs rendszer folyamataival. Az Elixir folyamatai sokkal kevesebb memóriát és CPU-t használnak. Teljesen rendben van, ha egy Elixir-alkalmazás több száz Elixir-folyamatot futtat.
A folyamatok nem osztanak meg egymással közvetlenül információt. Az adatok megosztásához a folyamatok üzeneteket küldenek és fogadnak.
Az send/2 függvénnyel bármelyik folyamatnak küldhetsz üzenetet. Az send/2 első argumentuma a címzett PID-je, a második argumentuma az üzenet.
Egy üzenet bármilyen típusú lehet. Gyakran atomokból és tuple-okból áll. Ha választ szeretnél kapni, valahol az üzenetben fel kell tüntetned a küldő PID-jét. Az aktuális folyamat PID-jét a self() függvénnyel kérheted le.
Az send/2 nem ellenőrzi, hogy a címzett megkapta-e az üzenetet, és azt sem, hogy a címzett még életben van-e. Az üzenet a címzett postaládájába kerül, és csak akkor olvasódik el, ha a címzett kifejezetten az üzenetek fogadását kéri.
Egy üzenet a receive/1 makróval olvasható ki a postaládából. Ez elfogad egy do blokkot, amely mintaillesztést végezhet az üzeneteken.
receive do
{:ping, sender_pid} -> send(sender_pid, :pong)
:do_nothing -> nil
end
A receive/1 egyetlen üzenetet vesz ki a postaládából, amely illeszkedik a megadott minták bármelyikére, és lefuttatja az adott mintához tartozó kifejezést. Ha nincs üzenet a postaládában, vagy a postaládában lévő üzenetek egyike sem illeszkedik egyetlen mintára sem, a receive/1 várni fog egyre.
Ha egynél több üzenetet szeretnél fogadni, rekurzívan kell meghívnod a receive/1-et. Gyakori minta egy rekurzív függvény megvalósítása, például loop néven, amely meghívja a receive/1-et, tesz valamit az üzenettel, majd újra meghívja önmagát, hogy további üzenetekre várjon. Ha valamilyen állapotot át kell vinned egyik receive/1 hívásból a másikba, azt úgy teheted meg, hogy argumentumként átadod a loop függvénynek.
A folyamatazonosítók külön adattípust alkotnak. Postaládcímekként működnek: ha ismered egy folyamat PID-jét, üzenetet küldhetsz annak a folyamatnak. A PID-eket általában közvetetten hozzák létre, olyan függvények visszatérési értékeként, amelyek új folyamatokat hoznak létre, mint például a spawn.
Beágyazott rendszert írsz egy Take-A-Number géphez. Ez egy nagyon egyszerű modell. Egymást követő számokat tud kiadni, és meg tudja mondani, mi volt az utoljára kiadott szám.
Valósítsd meg a start/0 függvényt. Hozzon létre egy új folyamatot, és adja vissza a folyamat PID-jét. Az új folyamatnak egyelőre nem kell semmit tennie.
TakeANumber.start()
# => #PID<0.138.0>
Ne feledd, hogy a PID minden futtatáskor eltérő lehet.
Módosítsd a gépet úgy, hogy az újonnan létrehozott folyamat készen álljon az üzenetek fogadására (indíts egy receive-ciklust) 0 kezdőállapottal. Legyen képes fogadni a {:report_state, sender_pid} üzeneteket. Ezekre az üzenetekre válaszul küldje el az aktuális állapotát (az utoljára kiadott sorszámot) a sender_pid-nek, majd várjon további üzenetekre.
machine_pid = TakeANumber.start()
# a client sending a message to the machine
send(machine_pid, {:report_state, self()})
# a client receiving a message from the machine
receive do
msg -> msg
end
# => 0
Módosítsd a gépet úgy, hogy fogadni tudja a {:take_a_number, sender_pid} üzeneteket. Növelje az állapotát 1-gyel, küldje el az új állapotot a sender_pid-nek, majd várjon további üzenetekre.
machine_pid = TakeANumber.start()
# a client sending a message to the machine
send(machine_pid, {:take_a_number, self()})
# a client receiving a message from the machine
receive do
msg -> msg
end
# => 1
Módosítsd a gépet úgy, hogy fogadni tudja a :stop üzenetet. Ekkor hagyja abba a további üzenetekre való várakozást.
Módosítsd a gépet úgy, hogy amikor váratlan üzenetet kap, hagyja figyelmen kívül, és folytassa a további üzenetekre való várakozást.
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Elixir nyelvet 58 fogalom168 feladat segítségével, valódi emberi mentorálással, mindez ingyen.