5

I want to do a selective receive where a record property needs to be matched, but whatever syntax I try, I get an "illegal pattern" message.

loop(State) ->
  receive
    {response, State#s.reference} -> do_something()
  end.

Is this not possible?

John Galt
  • 257
  • 3
  • 6
  • 2
    This is an illegal pattern because it literally means: bind this element of the record to the value received by receive. Not to mention that record element access is basically a function call, which cannot appear on the left side of a binding. – Zed Oct 08 '09 at 08:54

2 Answers2

22

Just an alternative which uses pattern matching:

loop(#s{reference = Reference} = State) ->
  receive
    {response, Reference} ->
      do_something()
  end.
Zed
  • 57,028
  • 9
  • 76
  • 100
  • 1
    This is what I was really looking for. – John Galt Oct 08 '09 at 18:10
  • It's a little baffling, though. Reference in the loop line looks like it's being bound to State#s.reference, yet it's on the rhs. – John Galt Oct 08 '09 at 22:33
  • 1
    That's because that is a different kind of equal sign :) This is "syntactic sugar" for records, but your equal sign is Erlang's binding operator. – Zed Oct 09 '09 at 05:47
  • Ok, good. I just wanted to make sure that was the case, and there wasn't some deeper principle I was missing. Even when I wrote my original, I knew it was wrong for the reason you gave, because that syntax isn't for binding, but I was trying to illustrate the gist. I knew I had seen record pattern matching like this example before! – John Galt Oct 09 '09 at 19:00
  • Forgot to add that you can use this form to match on values, e.g.: `loop(#s{reference = undefined} = State) ->` – Zed Oct 10 '09 at 14:05
8
loop(State) ->
    receive
       {response, R} when R =:= State#s.reference ->
             do_something()
    end.