[erlang-questions] Illegal map key in pattern

Raimo Niskanen raimo+erlang-questions@REDACTED
Mon Aug 5 13:45:24 CEST 2019


On Mon, Aug 05, 2019 at 01:11:36PM +0200, Per Hedeland wrote:
> On 2019-08-05 12:28, Valentin Micic wrote:
> >> On 05 Aug 2019, at 11:03, Per Hedeland <per@REDACTED> wrote:
> >>
> >> On 2019-08-05 09:29, Raimo Niskanen wrote:
> >>> On Sat, Aug 03, 2019 at 06:14:15PM +0200, Valentin Micic wrote:
> >>>> Hi,
> >>>>
> >>>> I am a bit nonplussed with the behaviour of map module&consider the following map:
> >>>>
> >>>>
> >>>> f(MAP), MAP = #{ {12,1} => "some value", {12,2} => "some other value"}.
> >>>>
> >>>>
> >>>> Then, the following works:
> >>>>
> >>>>
> >>>> f(V), case MAP of #{ {1,12} := V} -> V end.
> >>>>                              "some value"
> >>>>
> >>>>
> >>>>
> >>>> Then, surely, a snippet below should also work... except that it doesnt:
> >>>>
> >>>>
> >>>>   f(DCID), f(SORD), DCID = 12, SORD=1.
> >>>>
> >>>> f(V), case MAP of #{ {DCID, SORD} := V} -> V end.
> >>>>
> >>>> * 1: illegal map key in pattern
> >>> The syntax of your examples makes no sense to me, so I take a shot in the
> >>> dark on your gripe.
> >>
> >> It's just "shell syntax", try it:-) - the f/1 is the shell's "forget"
> >> function, to ensure that the variable is unbound.

Sorry, just back from vacation...

> >>
> >>>      fun (K, V, Map) ->
> >>> 	case Map of
> >>> 	    #{ K := V} -> V
> >>> 	end
> >>>      end.
> >>>      fun (K, V, Map) ->
> >>> 	case Map of
> >>> 	    #{ {K} := V} -> V
> >>> 	end
> >>>      end.
> >>>      fun (K, V, Map) ->
> >>> 	K_1 = {K},
> >>> 	case Map of
> >>> 	    #{ K_1 := V} -> V
> >>> 	end
> >>>      end.
> >>> Try those in the shell and you will find out that the first produces a
> >>> fun(), the second barfs with "illegal map key in pattern", and the third
> >>> produces a fun().
> >>> From:
> >>>      http://erlang.org/doc/reference_manual/expressions.html#map-expressions
> >>> section "Maps in Patterns"
> >>>      Matching of key-value associations from maps is done as follows:
> >>>      #{ K := V } = M
> >>>      Here M is any map. The key K must be an expression with bound
> >>>      variables or literals. V can be any pattern with either bound
> >>>      or unbound variables.
> >>> So, the key must be a literal or a bound variable.
> >>
> >> Hm, that's not what the documentation that you quote says - surely, if
> >> K is a bound variable, {K} is "an expression with bound variables", as
> >> is {DCID, SORD} in Valentin's case. And of course there's no way the
> >> variableS can be plural if not combined into an expression somehow...
> >>
> >>> It's a known limitation.
> >>
> >> So it seems the documentation is wrong, and should drop the
> >> "expression" and plurals: "The key K must be a bound variable or a
> >> literal." (as you said).

Good catch!  I read it as I knew it works, not as it stood.

> >>
> >> --Per
> > 
> > Thank you Per for articulating my issue in a way I wasnt able to do. :-)
> > 
> > Indeed, documentation seems a bit misleading. When they are referencing a plural (bound variables), they are probably referring to a multitude of "single" variables used as keys to a multitude of maps.
> 
> I could agree with that, if the sentence didn't start with "The key K
> must be...", clearly referencing the single key K in the single map M
> in the specific expression "#{ K := V } = M".
> 
> > But, documentation aside  that could be corrected; do you think that this kind of implementation is in line with a principle of least astonishment?
> 
> Well, I know basically nothing about how maps are implemented, but *I*
> would certainly be less astonished by the limitation described in the
> documentation (it seems entirely reasonable) than by the actual
> limitation, since in most other cases I can think of, you can use "an
> expression with bound variables" wherever you can use "a bound
> variable".
> 
> But maybe it's "just" something that was a challenge to implement, and
> will be fixed to match the current documentation in a future release...

I think it is precisely like that.  It is documented as it was intended,
but implementing it was a challenge so it got only partly implemented.
(constructing a new term for map lookup in the context of a pattern match
proved an unexpectedly hard problem, I guess)

So it is a known limitation, to us that know it ;-)
unfortunately not nicely documented,
and the goal is to fix it some day...

http://erlang.org/pipermail/erlang-questions/2016-May/089269.html

/ Raimo


> 
> --Per
> 
> > V/
> > 
> >>
> >>> / Raimo
> >>>>
> >>>>
> >>>>
> >>>> To make things worse, when I just replace an explicit term, such as {DCID, SORD}, with something like this:
> >>>>
> >>>>
> >>>> f(GRP_KEY), GRP_KEY={DCID, SORD}.
> >>>>
> >>>> f(V), case MAP of #{ GRP_KEY := V} -> V end.
> >>>>
> >>>> "some value
> >>>>
> >>>>
> >>>>
> >>>> Then the whole thing works again.
> >>>>
> >>>> I would argue that all cases should just work.
> >>>> How come they dont?
> >>>>
> >>>>
> >>>> Kind regards
> >>>>
> >>>> V/
> >>>>
> >>
> >> _______________________________________________
> >> erlang-questions mailing list
> >> erlang-questions@REDACTED
> >> http://erlang.org/mailman/listinfo/erlang-questions
> > 
> 
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions

-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB



More information about the erlang-questions mailing list