lufte
lufte

Reputation: 1364

How to spawn an anonymous function with arguments?

In elixir we have spawn/1 to spawn an anonymous function without any arguments and spawn/3 to spawn a fully qualified function with arguments. But how do I spawn an anonymous function that requires arguments?

Example: I want to run an anonymous function that receives messages until a certain condition is met. The argument is the function itself to be able to perform the recursive step.

loop = fn f ->
  receive do
    {:end, pid} -> send(pid, "exiting")
    {_, pid} ->
      send(pid, "unrecognized message, keep waiting...")
      f.(f)
  end
end

child = spawn()  # How do I spawn it passing itself as an argument?

Upvotes: 5

Views: 1659

Answers (1)

Dogbert
Dogbert

Reputation: 222128

You can create a new anonymous function to handle the first call to loop, and let loop handle the rest:

spawn(fn -> loop.(loop) end)
iex(1)> loop = fn f ->
...(1)>   receive do
...(1)>     {:end, pid} -> send(pid, "exiting")
...(1)>     {_, pid} ->
...(1)>       send(pid, "unrecognized message, keep waiting...")
...(1)>       f.(f)
...(1)>   end
...(1)> end
#Function<6.52032458/1 in :erl_eval.expr/5>
iex(2)> pid = spawn(fn -> loop.(loop) end)
#PID<0.90.0>
iex(3)> send pid, {:foo, self}
{:foo, #PID<0.80.0>}
iex(4)> flush
"unrecognized message, keep waiting..."
:ok
iex(5)> send pid, {:end, self}
{:end, #PID<0.80.0>}
iex(6)> flush
"exiting"
:ok
iex(7)> Process.alive? pid
false

Upvotes: 7

Related Questions