Closed usaoc closed 1 week ago
This looks great! In trying it out, I notice one issue:
> def {"1": a, "2": b = 2} = {}
def: value does not satisfy annotation
value: {}
annotation: matching(Map{"1": _, "2": _})
The constructed annotation shown in the error message suggests that a "2"
is needed. Should keys with defaults be left out there?
A danger of just leaving them out is that an error like this (simulated) one might be confusing:
> def {"1": a, "2": b :: Int = "oops"} = {"1": 1}
def: value does not satisfy annotation
value: {"1": 1}
annotation: matching(Map{"1": _})
I think this matters less than the first example above, though.
Maybe we can add = ....
to the right of value binding to indicate that a default value is supplied. It can still be confusing when the produced default value doesn’t match the value binding, though. This feature is unusual in that the “default” value is specified in the Map
binding, and I’m not sure how to best phrase the error.
I think you're right about = ....
. My initial thought was that the consuming side wouldn't want to expose the use of that key, but now I think that doesn't make sense. And it addresses the second example by suggesting that the issue may be within the ....
.
Now a = ....
(in this form, regardless of whether an expression or block is supplied) is added to the right of value binding to indicate that a default value is supplied.
Thanks! LGTM
In a
Map
binding, a key can be made optional by supplying a default expression/body, which is used to produce a "default" value to further match in case the key is missing. This is similar in functionality to the 2-ary case ofMap.get
.Resolve #547.