> Le 21 févr. 2017 à 22:05, Matthew Johnson <[email protected]> a écrit :
>
>>> Le 20 févr. 2017 à 12:17, Matthew Johnson <[email protected]> a écrit :
>>>
>>>> e) Generic Containers:
>>>> Generic containers that impose requirements on their elements will pose
>>>> some additional problems, for instance: `Set.insert` needs to call
>>>> `hashValue` and `==` on its elements, making the purity of `Set.insert`
>>>> constrained by the purity of those functions. Without a way to express
>>>> this kind of conditional purity, `Set` and `Dictionary` cannot be pure.
>>>
>>> Could we use a mechanism similar to `rethrows` to address this kind of
>>> transitive purity? We have already discussed something along those lines
>>> for handling functions passed as arguments. Maybe that mechanism could be
>>> designed to handle this use case as well.
>>
>> Similar, yes. But more complicated too. In pseudo code, this is what you'd
>> have to express for `Set.insert`:
>>
>> pure(where: Element.hashValue is pure, Element.== is pure)
>> func insert(_ element: Element) { ... }
>>
>> Then the compiler can enforce that `insert` only does things that are
>> allowed in a pure function, but can ignore the purity of Element.hashValue
>> and Element.== because the caller will check for that that.
>
> Yep, that’s the kind of thing I had in mind.
>
> I can imagine being this explicit could get pretty cumbersome though. I
> wonder if there is a way to streamline this. For example, in this case if we
> could just talk about `Element`’s conformance to `Hashable` and we could talk
> about a `pure` conformance (all requirements are met with pure
> implementations) then we could just say something like this:
>
> pure(Element.Hashable)
> func insert(_ element: Element) { ... }
>
> Note: I also removed some redundancies - we could just say that the
> parameters are a list of things the purity of which `insert`’s purity depends.
>
> For function arguments it would look something like this:
>
> pure(transform)
> func map<T>(transform: Element -> T)
The approach is interesting and less heavy than my pseudo code example. The
syntax with protocols is a bit off though. What does `Element.Hashable` mean in
Swift? It refers to a member inside of `Element`, not a conformance of
`Element` to the `Hashable` protocol. I don't think there is any syntax to
refer to a conformance of a certain type to a protocol in Swift. The closest is
a check for the existence of a conformance for generic arguments.
But I'd tend to gravitate towards your last example, which is simpler: just
provide a path to the function that must be pure. Ideally you would be able do
it like this:
pure(Element.hashValue, Element.==)
Unfortunately, it's hard (impossible?) currently to represent the getter of a
property or to get the function associated with an operator like ==, so this is
a bit ad-hoc. (Try to assign the function to a variable to see what I mean.)
There's still some general language improvements required to make this work.
If you want another syntax requiring all functions in a protocol conformance to
be pure, that's an additive thing. I'm not sure it's worth its weight though.
I do agree that it's cumbersome to have these complicated annotations. We could
imitate D and have generic functions infer their purity automatically, but that
wouldn't work well in a language like Swift where generic code can be opaque.
Instead, perhaps the compiler could automatically suggest what to add when it
detects some requirements are missing in a pure function.
--
Michel Fortin
https://michelf.ca
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution