Illegal map key in pattern

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Illegal map key in pattern

Valentin Micic-6
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 doesn’t: 


 f(DCID), f(SORD), DCID = 12, SORD=1. 

f(V), case MAP of #{ {DCID, SORD} := V} -> V end.

* 1: illegal map key in pattern



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 don’t? 


Kind regards

V/


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Raimo Niskanen-11
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 doesn’t:
>
>
>  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.

    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.
It's a known limitation.

/ 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 don’t?
>
>
> Kind regards
>
> V/
>


--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Valentin Micic-6
Thank you, I guess…


> On 05 Aug 2019, at 09:29, Raimo Niskanen <[hidden email]> 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 doesn’t:
>>
>>
>> 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.
>
>    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.
> It's a known limitation.
>
> / 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 don’t?
>>
>>
>> Kind regards
>>
>> V/
>>
>
>
> --
>
> / Raimo Niskanen, Erlang/OTP, Ericsson AB
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Per Hedeland
In reply to this post by Raimo Niskanen-11
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.

>      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).

--Per

> / 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
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Valentin Micic-6
> On 05 Aug 2019, at 11:03, Per Hedeland <[hidden email]> 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.
>
>>     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).
>
> —Per

Thank you Per for articulating my issue in a way I wasn’t 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.

But, documentation aside — that could be corrected; do you think that this kind of implementation is in line with a principle of least astonishment?

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
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Per Hedeland
On 2019-08-05 12:28, Valentin Micic wrote:

>> On 05 Aug 2019, at 11:03, Per Hedeland <[hidden email]> 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.
>>
>>>      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).
>>
>> --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...

--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
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Raimo Niskanen-11
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 <[hidden email]> 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
> >> [hidden email]
> >> http://erlang.org/mailman/listinfo/erlang-questions
> >
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Björn-Egil Dahlberg-2
Den mån 5 aug. 2019 kl 13:45 skrev Raimo Niskanen <[hidden email]>:
>
> 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)

IIRC the case that was troublesome was the failure case, say

K = a

case Map of
   #{ K + 1 := V } -> V;
   ...

Meaning it is essentially no trouble to evaluate the key expression before the case expression, however the semantics for what should happen if the key expression fails were never really defined.
The easy option it just to throw an exception and that makes some sort of sense, but it could make more sense that we say "the pattern does not match" and then test the next clause in the case expression. This latter option is also a bit harder to implement ofc. The core and kernel language does not really expect this behaviour :) go and figure ^^

In other words - it is not implemented because we, well I, missed this case when defining the semantics. 

My bad.
Björn-Egil

 

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


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Per Hedeland
On 2019-08-15 14:12, Björn-Egil Dahlberg wrote:

> Den mån 5 aug. 2019 kl 13:45 skrev Raimo Niskanen <[hidden email] <mailto:raimo%[hidden email]>>:
>
>      >
>      > 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)
>
>
> IIRC the case that was troublesome was the failure case, say
>
> K = a
>
> case Map of
>     #{ K + 1 := V } -> V;
>     ...
>
> Meaning it is essentially no trouble to evaluate the key expression before the case expression, however the semantics for what should happen if the key expression fails were never really defined.

Hm, is this really different from other expressions in a pattern?

1> K = a.
a
2> Map = b.
b
3> case Map of K + 1 -> true; _ -> false end.
* 1: illegal pattern

Which is because

    An arithmetic expression can be used within a pattern if it meets
    both of the following two conditions:

    o It uses only numeric or bitwise operators.
    o Its value can be evaluated to a constant when complied.

I.e. it seems to me that this restriction (and compile-time error)
"should just apply" also to map keys in patterns - it's still "an
aritmetic expression within a pattern". Are there other failure cases,
that would cause problems for expressions that don't violate this
restriction?

--Per

> The easy option it just to throw an exception and that makes some sort of sense, but it could make more sense that we say "the pattern does not match" and then test the next clause in the case
> expression. This latter option is also a bit harder to implement ofc. The core and kernel language does not really expect this behaviour :) go and figure ^^
>
> In other words - it is not implemented because we, well I, missed this case when defining the semantics.
>
> My bad.
> Björn-Egil
>
>
>     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
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Illegal map key in pattern

Dániel Szoboszlay
So the documentation currently says:

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.

I think the problem with it is that the key should be a pattern with bound variables, not an expression. Since #{K := V} is clearly a pattern, it doesn't make sense to allow a part of it to be an expression (which is a more generic thing than a pattern).

At least I wouldn't expect #{httpc:request("https://google.com/") := V} to be a valid pattern, while httpc:request("https://google.com/") is an expression with bound variables or literals.

But I would expect all patterns listed in http://erlang.org/doc/reference_manual/expressions.html#patterns that contain only bounded variables or literals to be usable as K. This would include things like:
#{[X|Y] := Z} % assuming X and Y are bounded
#{1 + 2 := A}
#{"foo" ++ X := Y} % assuming X is bounded

This would make sense because the following patterns work just fine:
{[X|Y], Z}
{1 + 2, A}
{"foo" ++ X, Y}

By the way, one question that would still remain open is whether Erlang shall allow operator = in key patterns:
#{(X = {foo, bar}) := Y}
Because {(X = {foo, bar}), Y} is a valid pattern, regardless of X being bound or not. But this seems to be a lot less important issue.

Cheers,
Daniel

On Thu, 15 Aug 2019 at 15:06, Per Hedeland <[hidden email]> wrote:
On 2019-08-15 14:12, Björn-Egil Dahlberg wrote:
> Den mån 5 aug. 2019 kl 13:45 skrev Raimo Niskanen <[hidden email] <mailto:[hidden email]>>:
>
>      >
>      > 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)
>
>
> IIRC the case that was troublesome was the failure case, say
>
> K = a
>
> case Map of
>     #{ K + 1 := V } -> V;
>     ...
>
> Meaning it is essentially no trouble to evaluate the key expression before the case expression, however the semantics for what should happen if the key expression fails were never really defined.

Hm, is this really different from other expressions in a pattern?

1> K = a.
a
2> Map = b.
b
3> case Map of K + 1 -> true; _ -> false end.
* 1: illegal pattern

Which is because

    An arithmetic expression can be used within a pattern if it meets
    both of the following two conditions:

    o It uses only numeric or bitwise operators.
    o Its value can be evaluated to a constant when complied.

I.e. it seems to me that this restriction (and compile-time error)
"should just apply" also to map keys in patterns - it's still "an
aritmetic expression within a pattern". Are there other failure cases,
that would cause problems for expressions that don't violate this
restriction?

--Per

> The easy option it just to throw an exception and that makes some sort of sense, but it could make more sense that we say "the pattern does not match" and then test the next clause in the case
> expression. This latter option is also a bit harder to implement ofc. The core and kernel language does not really expect this behaviour :) go and figure ^^
>
> In other words - it is not implemented because we, well I, missed this case when defining the semantics.
>
> My bad.
> Björn-Egil
>
>
>     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
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions