[swift-evolution] Should we rename "class" when referring to protocol conformance?

Matthew Johnson matthew at anandabits.com
Mon May 9 10:43:25 CDT 2016



Sent from my iPad

> On May 9, 2016, at 3:01 AM, Andrew Trick <atrick at apple.com> wrote:
> 
> 
>>> On May 7, 2016, at 11:51 PM, Dave Abrahams <dabrahams at apple.com> wrote:
>>> 
>>> Does Array<T> have value semantics then only if T also has value
>>> semantics?
>> 
>> This is a great question; I had to rewrite my response four times.
>> 
>> In my world, an Array<T> always has value semantics if you respect the
>> boundaries of element values as defined by ==.  That means that if T is
>> a mutable reference type, you're not looking through references, because
>> == is equivalent to ===.
>> 
>> Therefore, for almost any interesting SomeConstraint that doesn't refine
>> ValueSemantics, then
>> 
>>  Array<T: SomeConstraint>
>> 
>> only has value semantics if T has value semantics, since SomeConstraint
>> presumably uses aspects of T other than reference identity.  
> 
> I just had a chance to digest Dave's answer. It explains a lot.
> 
> PureValue was defined in terms of the type's physical representation:
> - A struct with no reference properties
> - Recursively, a reference to immutable or uniquely referenced memory.
> 
> It's defined such that we can say Array<T> is a PureValue iff T is a PureValue.
> 
> There is currently no procedure for determining PureValue because we have no way to declare that references are immutable or uniquely referenced. It would be a promise by the developer.
> 
> Now attempting to look at it from Dave's direction, value semantics apply to the variable's type, not the object's physical representation:
> 
> let v2 = v1
> f(v1)
> assert(v1 == v2)
> 
> If everything is a value, then this always works. Great!
> 
> If the variable's type does not allow mutating shared state, then operations on the variable are operating on a value.
> 
> protocol ValueP {
>   func compute() -> Result // nonmutating
> }
> 
> func g(v1 : ValueP) {
>   let v2 = v1
>   v1.compute()
>   assert(v1 == v2)
> }
> 
> Nice. ‘compute' cannot change the value. Those value semantics do not tell me anything about shared state or function purity. For that, I need some additional constraint on 'compute'. Knowing that it does not mutate the 'self' value is insufficient.
> 
> One way of doing that, for example, is to declare that 'compute' transitively cannot access globals *and* ValueP must be a PureValue. Now I can safely write this:
> 
> protocol ValueP : PureValue {
>   @strawman_noglobal func compute() -> Result
> }
> 
> /// Return (v1.compute, v2.compute)
> func g(v1 : ValueP, v2 : ValueP) -> (Result, Result) {
>   let r1 = v1.compute()
>   if v1 == v2 {
>     return (r1, r1)
>   }
>   return (r1, v2.compute())
> }
> 
> So, Dave is right that we need to decide soon whether we can make stronger assumptions about value semantics. But that is a separate question from how to express function purity. I don't think there is any urgency in introducing things like the PureValue protocol or @strawman_noglobals attribute, now that we have clearly established shared-state-mutability-by-default. When we want to seriously have that discussion, we should consider other alternatives. I would prefer to wait until indirect structs and improved CoW support have had more discussion.

One more thing that I think we would all agree must come first is some way to specify in code that a type has value semantics (whether or not it is pure).  Is there any ongoing discussion about that?

> 
> -Andy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160509/5ed4dbf3/attachment.html>


More information about the swift-evolution mailing list