> 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

Reply via email to