Elixir: Possible bug in pattern matching against pinned varible

Created on 16 May 2018  路  5Comments  路  Source: elixir-lang/elixir

Environment

  • Elixir & Erlang/OTP versions (elixir --version):
Erlang/OTP 20 [erts-9.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] 
[hipe] [kernel-poll:false] [dtrace]
Elixir 1.6.1 (compiled with OTP 20)
  • Operating system: macOS 10.13.4 (17E202)

Current behavior

A pattern match assertion with a literal value passes, but the same assertion fails if a pinned variable with the exact same value is executed.

Expected behavior

Equal behaviour for literal values and pinned variables in pattern matching.

This repro project contains a single test file that reproduces this behaviour, alongside some comments and test output in README.

Most helpful comment

This is expected behaviour. Matching against a pinned variable is effectively an equality check between two values. Matching against a pattern is more complex. Especially in case of maps that is important since map patterns match on subsets of keys, while equality checks verify exact contents.

In other words:

map = %{foo: 1, bar: 2}
%{foo: 1} = map # passes - we check subset of keys
value = %{foo: 1}
^value = map # fails - we check for equality between value and map

All 5 comments

This is expected behaviour. Matching against a pinned variable is effectively an equality check between two values. Matching against a pattern is more complex. Especially in case of maps that is important since map patterns match on subsets of keys, while equality checks verify exact contents.

In other words:

map = %{foo: 1, bar: 2}
%{foo: 1} = map # passes - we check subset of keys
value = %{foo: 1}
^value = map # fails - we check for equality between value and map

Ok, thanks for the clarification. I trust careful thought has gone into this decision. I'd still be interested if there was a backstory to this.

There's no backstory other than the fact that variables hold values not patterns.

Similar how you can't do:

pattern = [_, _]
^pattern = [1, 2]

you can't do what you're trying with a map - you assign a value to a variable, not a pattern. There's no reason for maps to behave different than everything else.

If there's a distinction between the two that makes sense. Maybe they are different things in the parser grammar as well? On reflection, this makes sense. The different nature is also underlined by the fact that one needs the pin operator to place a variable in a pattern, I just realise.

Interestingly, I can use a module attribute to store a pattern (or make my example pass), but I guess that is because these are more similar to macros / textual substitution?

Interestingly, I can use a module attribute to store a pattern (or make my example pass), but I guess that is because these are more similar to macros / textual substitution?

Precisely, they exist at compile-time and are 'injected' into the reference site.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

josevalim picture josevalim  路  3Comments

jdeisenberg picture jdeisenberg  路  4Comments

DEvil0000 picture DEvil0000  路  3Comments

cmeiklejohn picture cmeiklejohn  路  3Comments

whitepaperclip picture whitepaperclip  路  3Comments