There has always been an implementation limitation for matching
of binaries (for technical reasons). For example:
foo(Bin) ->
<<A:8>> = <<X:4,Y:4>> = Bin,
{A,X,Y}.
This would fail to compile with the following message:
t.erl:5:5: binary patterns cannot be matched in parallel using '='
% 5| <<A:8>> = <<X:4,Y:4>> = Bin,
% | ^
This commit lifts this restriction, making the example legal.
A restriction for map matching is also lifted, but before we can
describe that, we'll need a digression to talk about the `=` operator.
The `=` operator can be used for two similar but slightly differently
purposes.
When used in a pattern in a clause, for example in a function head,
both the left-hand and right-hand side operands must be patterns:
Pattern1 = Pattern2
For example:
bar(#{a := A} = #{b := B}) -> {A, B}.
The following example will not compile because the right-hand side
is not a pattern but an expression:
wrong(#{a := A} = #{b => B}) -> {A, B}.
t.erl:4:23: illegal pattern
% 4| wrong(#{a := A} = #{b => B}) -> {A, B}.
% | ^
Used in this context, the `=` operator does not imply that the two
patterns are matched in any particular order. Attempting to use a
variable matched out on the left-hand side on the right-hand side, or
vice versa, will fail:
also_wrong1(#{B := A} = #{b := B}) -> {A,B}.
also_wrong2(#{a := A} = #{A := B}) -> {A,B}.
t.erl:6:15: variable 'B' is unbound
% 6| also_wrong1(#{B := A} = #{b := B}) -> {A,B}.
% | ^
t.erl:7:27: variable 'A' is unbound
% 7| also_wrong2(#{a := A} = #{A := B}) -> {A,B}.
% | ^
The other way to use `=` is in a function body. Used in this way,
the right-hand side must be an expression:
Pattern = Expression
For example:
foobar(Value) ->
#{a := A} = #{a => Value},
A.
Used in this context, the right-hand side of `=` must **not** be a pattern:
illegal_foobar(Value) ->
#{a := A} = #{a := Value},
A.
t.erl:18:21: only association operators '=>' are allowed in map construction
% 18| #{a := A} = #{a := Value},
% | ^
When used in a body context, the value of the `=` operator is the
value of its right-hand side operand. When multiple `=` operators are
combined, they are evaluted from right to left. That means that any
number of patterns can be matched at once:
Pattern1 = Pattern2 = ... = PatternN = Expr
which is equivalent to:
Var = Expr
PatternN = Var
.
.
.
Pattern2 = Var
Pattern1 = Var
Given that there is a well-defined evaluation order from right to
left, one would expect that the following example would be legal:
baz(M) ->
#{K := V} = #{k := K} = M,
V.
It is not. In Erlang/OTP 25 or earlier, the compilation fails with the
following message:
t.erl:28:7: variable 'K' is unbound
% 28| #{K := V} = #{k := K} = M,
% | ^
That restriction is now lifted, making the example legal.
Closes erlang#6348
Closes erlang#6444
Closes erlang#6467