-
Notifications
You must be signed in to change notification settings - Fork 62
make lookup operator honor refined return type of "get()" #4517
Comments
[@gdejohn] I've had this same thought. |
This is for eclipse-archived/ceylon#5946. Justification for the new workaround is related to eclipse-archived/ceylon#4517 (the new code actually aligns more closely with what the typechecker does).
Bumped into this too. 👍 I created a map that automatically creates items if they did not exist in the map before, and thus the return value is never null.. |
If only I would have had the foresight to define shared interface Correspondence<in Key, out Item=Anything>
given Key satisfies Object {
shared formal Item get(Key key);
...
} Or to have defined shared interface Map<out Key=Object, out Item=Anything>
satisfies Collection<Key->Item> &
Correspondence<Object,Item?>
given Key satisfies Object { ... }
shared interface List<out Element=Anything>
satisfies Collection<Element> &
Correspondence<Integer,Element?> &
Ranged<Integer,Element,List<Element>> { I screwed up here, it seems to me :-( |
Does the x[y] operator have to be tied to the Correspondence interface? It can't just alias to x.get(y) ? |
On the other hand, there's a somewhat strong argument that for a "total" correspondence, the correct type to use is |
Well, that's the way all other operators in Ceylon are defined. |
We could, in principle, the next time we break BC, make the following change: shared interface Correspondence<in Key, out Item=Anything, out Absent=Null>
given Key satisfies Object {
shared formal Item | Absent get(Key key);
...
} |
is that better/less breaking than the earlier suggestion you had? |
Less breaking. |
That would require #3950 to be useful. |
For the shared interface Correspondence<in Key, out Item=Object>
given Key satisfies Object
given Item satisfies Object If one tries to write a generic function for storing arbritary values, Alternatively, although I don't know if it's possible, |
@phlopsi There's nothing stopping you from doing that today. For example: alias Maybe<Element> => [Element] | [];
Map<String, Maybe<Integer>> m = map { "a"->[], "b"->[1] }; But I haven't seen that done in Ceylon code, and I'm not sure it would be a good idea to force people to use that pattern. Taking a step back, we know that optionals can be represented by monads (
Which one is better varies by use case. (Although, it's worth noting that unions have the additional advantage that Now, your suggestion is have two standard ways to represent optionals in order to eliminate the above tradeoff. But I doubt that would work well in practice:
A very "simple" type that I think would be confusing to work with: Map<String, Maybe<Map<String, Maybe<String>>>> as opposed to the more Ceylonic: Map<String, Map<String, String?>?> So, I think it's better for a language to stick with one approach or the other, which for Ceylon has been to use union types. |
@jvasileff Deep-nesting has nothing to do with this. It's exactly 1 wrapper, if and only if the If the language would provide a way to model the inverse of The only other way to not be ambiguous is to reserve a type, that may not be included in the |
[@jvasileff] In "6.8.7. Correspondence, subrange, and stream operators", the lookup operator is defined as yielding the result of
lhs.get(index)
with typeY?
forlhs
Correspondence<X,Y>
. But the actual return type oflhs.get(index)
may be a subtype ofY?
.It would be nice if the lookup operator honored the actual return type of
get
rather than assuming an optional type.Usage example:
[Migrated from ceylon/ceylon-spec#1411]
The text was updated successfully, but these errors were encountered: