tags:

views:

65

answers:

3
+2  Q: 

Records in a guard

I'm attempting to use a record in a guard as described here[1]. If I use the short form described there:

handle(Msg, State) when Msg==#msg{to=void, no=3} ->

... I never get a match... however, if I fully expand it to:

handle(Msg, State) when Msg#msg.to==void, Msg#msg.no==3 ->

... all is well. As it seems I do with most erlang docs, am I reading it wrong?

Thanks, --tim

[1] - http://www1.erlang.org/doc/reference_manual/records.html#id2278275

+3  A: 

I see you solved the problem already. Just a note: in idiomatic Erlang you'd usually write the match like this:

handle(Msg = #msg{to = void, no = 3}, State) ->

Of course, it comes down to taste, and at times you'll want to use guards instead to get more pleasing line alignment.

legoscia
+7  A: 

When you say #msg{to=void, no=3} in a guard, all the fields that you haven't mentioned will be set to their default (usually undefined). So your guard is failing to match because some of the fields not listed don't match.

I tend to always use a pattern rather than a guard where possible, so I would write the clause as:

handle(Msg = #msg{to=void, no=3}, State) ->
    ...

This pattern requires Msg to msg record (a tuple the size of an msg record with the first element being msg), the to element must be void and the no element must be 3. The other elements of the msg record can be anything.

archaelus
Thanks everyone, as all have surmised, I should be using a pattern instead... this learning curve is steep but enjoyable... thanks again...
williamstw
+2  A: 

You might want to use the following pattern instead, its succinct

handle(#msg{to=void, no=3}=Msg, State) ->
    do_stuff(Msg).

If you don't need the whole msg record value, but only some field within it then you can match and destruct like this

handle(#msg{to=void, no=3, data=Data}, State) ->
    do_stuff(Data).
Christian