Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Processes

processes.livemd

Processes

Section

p = spawn(fn -> IO.puts("✨") end)
Process.alive?(p)
p = spawn(fn -> 42 end)
Process.alive?(p)
p =
  spawn(fn ->
    receive do
      sender -> send(sender, 42)
    end
  end)
IO.puts(Process.alive?(p))
me = self()
send(p, me)
Process.sleep(1000)
IO.puts(Process.alive?(p))
receive do
  value -> value
end
# ATM, recursive anonymous functions ain't a thing
print_loop = fn ->
  receive do
    message -> IO.puts(message)
  end

  print_loop.()
end
defmodule Main do
  def print_loop() do
    receive do
      message -> IO.puts(message)
    end

    print_loop()
  end
end
import Main
pp = spawn(&print_loop/0)
send(pp, "Hello!")
send(pp, "Holla!")

Section

# A first version of PF could avoid the permanent process and allocate one new
# when it's called and then let it die.
defmodule PF do
  defstruct pid: nil

  # function single-arged for now. Dunno how to do NOT hardcode the number of args
  def new(function) do
    sender = self()
    pid = spawn(fn -> loop({sender, function}) end)
    %PF{pid: pid}
  end

  def call(pf, arg) do
    pid = pf.pid
    send(pid, {:call, self(), arg})

    receive do
      {:return, ^pid, value} -> value
      _ -> raise "Unexpected message ..."
    end
  end

  # This this is messy! Recursive anonymous functions would solve that, right?
  # here "state" provide information hiding (somehow).
  defp loop(state) do
    {sender, function} = state

    receive do
      {:call, ^sender, arg} -> send(sender, {:return, self(), function.(arg)})
      _ -> raise "Sh*t happened"
    end

    loop(state)
  end
end
pf = PF.new(fn x -> x + 42 end)
PF.call(pf, 56)