How to do pattern matching on a binary in Erlang?

2019-02-19 14:37发布

问题:

I would like to do recursion over a binary, and in each call read up to 32 bits from the binary, and return it in a new binary. But I can't get the pattern matching to work as I want.

binaryToBinary(Source) ->
    binaryToBinaryAux(Source, <<>>).

binaryToBinaryAux(<<>>, Target) ->
    Target;
binaryToBinaryAux(<<H:32/binary, T/binary>>, Target) ->
    binaryToBinaryAux(<<T/binary>>, <<Target/binary, H>>).

Here is the error I get for the pattern matching:

10> mymodule:binaryToBinary(<<"JonasPonas">>).
** exception error: no function clause matching
                    mymodule:binaryToBinaryAux(<<"JonasPonas">>,<<>>) 
                                                          (mymodule.erl, line 51)

What am I doing wrong with the pattern matching of the binary?

回答1:

The pattern <<H:32/binary, T/binary>> matches a binary containing at least 32 bytes, assigning the first 32 bytes to H and the remaining bytes to T. The pattern <<>> matches the empty binary. These are your only patterns.

<<"JonasPonas">> is neither empty nor does it have at least 32 bytes. Therefore it does not match either of your patterns and you get the error you do.

To fix this add a pattern that handles binaries that have less than 32 bytes (you can also get rid of the empty pattern as it will then be redundant).



回答2:

This should work correctry:

binaryToBinary(Source) ->
    binaryToBinaryAux(Source, <<>>).

binaryToBinaryAux(<<>>, Target) ->
    Target;
binaryToBinaryAux(<<H:32/binary, T/binary>>, Target) ->
    binaryToBinaryAux(<<T/binary>>, <<Target/binary, H/binary>>);
binaryToBinaryAux(Rest, Target) ->
    binaryToBinaryAux(<<>>, <<Target/binary, Rest/binary>>).