Pin operation on struct key value

Can you use a pin operator on a struct key value?

For example, I’m spawning a Task for which I want to monitor incoming messages:
%Task{owner: #PID<0.493.0>, pid: #PID<0.699.0>, ref: #Reference<0.0.3.6279>}

I want to create a wait function that accepts the Task struct so I can match on messages from the task, like this:

def wait(task) do
  receive do
    {^task.ref, response} ->
      {:ok, response}
    {:DOWN, ^task.ref, ^task.pid, _} ->
      {:error}
  end
end

I get an error when I try to compile this function: invalid argument for unary operator ^, expected an existing variable, got: ^task.ref()

I sense this is an illegal operation and I’m going to need to assign the struct key values to variable prior to matching, I just want to make sure. This would be an awesome feature if it worked.

Thanks!

I can be totally wrong, and did not test it, but how about something like this?

def wait(%Task{owner: _, pid: pid, ref: ref) do
  receive do
    {^ref, response} ->
      {:ok, response}
    {:DOWN, ^ref, ^pid, _} ->
      {:error}
  end
end
2 Likes

Brilliant! I still haven’t embraced pattern matching to it’s full potential yet :confounded:

I was going to resort to this:

%{pid: pid, ref: ref} = Task.Supervisor.async_nolink(...)

wait({pid, ref}

def wait({pid, ref} do
  receive do
    {^ref, response} ->
      Process.demonitor(ref, [:flush])
      {:ok, response}
    {:DOWN, ^ref, :process, ^pid, _} ->
      {:error}
  end
end

But I like your approach of passing the struct to the wait function and pattern matching to get the parameters. Much cleaner!