[erlang-questions] Status of map pair support in dialyzer
Magnus Lång
margnus1@REDACTED
Mon Apr 11 14:23:20 CEST 2016
On 2016-04-11 13:25, José Valim wrote:
> That's excellent news Kostis!
>
> I have only one question/reservation:
>
> Another problem is related to the meaning of #{}. One would expect
> that this notation means "the empty map," but instead it means
> "any map".
>
>
> #{} in pattern matching also means "any map", so it may be confusing
> to have #{} in specs to mean the empty map, specially because both
> usages are often close to each other. For example:
>
> -spec increment(term(), #{}) -> #{}
>
> increment(Key, #{} = Map) ->
>
> Map#{Key := maps:get(Key, Map) + 1}.
>
> I also understand that [] and {} in typespecs implies emptiness and
> making #{} mean "the empty map" would make the typespecs more consistent.
Actually, that is not the reason I wanted to make this change. Rather,
it is inconsistent with the #{PairList} syntax. Consider the type
#{x=>_, y=>_}. This type may only contain the keys x and y. So, the
value #{x=>1, y=>2, z=>3} does not belong to this type.
Now consider what happens when we change the type to #{x=>_}; the type
is made more restrictive. The key y is no longer allowed. But if we
repeat this process and change it to #{}, suddenly we have not made the
type more restrictive; we made it more allowing!
In fact, I have seen several people (myself included!) be fooled by the
#{} base case into believing that the #{x=>_, y=>_}, means the set of
values that match the pattern #{x=>_, y=>_}, which is not the case
(written with the new syntax, that type would be #{x:=_, y:=_, ...}).
So, I saw an opportunity to make the syntax self-consistent and more
intuitive before it would become harder to change. Either by changing
the semantics of everything but #{} in order to be consistent with
pattern matches, or by just changing #{} to be consistent with the rest.
Considering that the former would have broken the ability to write
associative-array-maps as #{Key => Value} (or required even more special
cases), the choice was clear.
> That said, maybe it would be better to not allow #{} altogether
> (deprecating it now and removing it later) and introduce an
> empty_map() construct? The empty_map() type is slightly more verbose
> but I don't expect it to be used frequently and, as such, the more
> explicit name is worth it. And if I understand the proposal correctly,
> both map() and #{_ => _} can still be used to represent any map, while
> #{_ := _} represents a non-empty map, so it feels all of our bases are
> covered.
>
> Thank you,
>
Although I am not against introducing an empty_map() alias, I don't
think disallowing #{} would solve the problem. Indeed, your example can
be trivially altered to commit the same mistake without using the #{} type;
-spec increment(term(), #{count := C}) -> #{count := C}.
increment(Key, #{count := C} = Map) when C >= 0 ->
Map#{Key := maps:get(Key, Map) + 1}.
If anything, I think the #{} case is the clearest example of type =/=
pattern, and removing it would just obscure the problem.
Thanks for your feedback
// Magnus Lång
> *José Valim*
> www.plataformatec.com.br <http://www.plataformatec.com.br/>
> Skype: jv.ptec
> Founder and Director of R&D
>
> On Mon, Apr 11, 2016 at 12:45 PM, Kostis Sagonas <kostis@REDACTED
> <mailto:kostis@REDACTED>> wrote:
>
> On 03/04/2016 11:59 AM, Björn-Egil Dahlberg XB wrote:
>
>
> I did the initial work for maps in Dialyzer but that
> application is not
> really part of my work area. If you want to contribute to
> Dialyzer you
> should probably talk to Hans Bolinder, Kostis Sagonas and/or
> Stavros
> Aronis. Hans talked about increasing Dialyzers knowledge about map
> associations the other day but I don't think it is on his
> agenda at the
> moment.
>
> I don't think it will be supported in 19.0 either though I
> have no clue
> if Kostis or Stavros, or anyone else for that matter, is
> working on it.
>
>
>
> Hijacking this thread to announce a proposal for a change in the
> type syntax related to maps.
>
> The relevant document is here:
>
> https://gist.github.com/kostis/eaf4a06e643cf49314ba
>
> We would appreciate feedback from the community at this point.
>
> The intention is for this change to be part of Erlang/OTP 19.0.
>
>
> Kostis
>
> PS. Most of the credit for this change goes to Magnus Lång.
>
> PS2. For those that would like to experiment with the new type
> syntax and use the new version of dialyzer, or just fancy reading
> code diffs, there is also a related pull request that implements
> all these:
>
> https://github.com/erlang/otp/pull/1014
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED <mailto:erlang-questions@REDACTED>
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20160411/a6e6c9dd/attachment.htm>
More information about the erlang-questions
mailing list