[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