Search code examples
concurrencyelixirspawn

Elixir, what is this program doing?


I have been given this code by our teacher. I am having trouble following what this code does. This is all I know so far: [x1, y1 | z1] = Output2.abc(3) is called, and so function abc(2) will spawn a new process assigned as y. Then it will send the value 2 to y. When it receives 2, I am stuck at what receive is doing. What does z -> z mean?

Also, the prof asks what `x1, y1 are. I don't understand where these variables are located in this code. If someone can just guide me through this it would be much appreciated. Thanks

defmodule Output2 do
  def abc(x) do
    y = spawn_link(__MODULE__, :n, [self()])
    send y, x
    receive do
      z -> z
    end
  end

  def n(z) do
    receive do
      v -> send z, n(v * v, v)
    end
  end

  defp n(x, x), do: [x]
  defp n(x, y), do: [y | n(x, y + y)]
end

[x1, y1 | z1] = Output2.abc(2)

Solution

    1. Output2.abc(2) is called.
    2. A linked process is started with spawn_link/3 using n(z) as the receiver
      1. The original process waits for a message from the recently spawned process.
    3. The parameter x (i.e. 2) is sent to the process started in #2
    4. The process started in #2 sends back the result of n(v * v, v)
      1. n(v * v, v) is a call to n(x, y) because x, and y are different values.
      2. So, we have n(2*2, 2). n(x,y) returns a list of y concatenated with n(x, y+y) where x = 4, and y = 2
      3. From the previous step n(4, 2+2) is called, which invokes n(x, x) returning a single item list of [4]
      4. From 4.2, [2 | [4]] results in [2 | 4] (a list of two elements: 2, 4)
    5. The original process received the list as z, and returns z (z -> z)
    6. Pattern matching is used to assign x1 = 2, and y1 = 4. z1 is the tail of the rest, which is empty.