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

Matthew Johnson matthew at anandabits.com
Sun May 22 14:23:53 CDT 2016


> On May 22, 2016, at 1:10 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> on Mon May 16 2016, Matthew Johnson <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> 
>>> On May 16, 2016, at 1:39 AM, Dave Abrahams <dabrahams at apple.com <mailto:dabrahams at apple.com>> wrote:
>>> 
>>> 
>>> on Sun May 15 2016, Tyler Fleming Cloutier <cloutiertyler-AT-aol.com <http://cloutiertyler-at-aol.com/> <http://cloutiertyler-at-aol.com/ <http://cloutiertyler-at-aol.com/>>> wrote:
>>> 
>> 
>>>>   On May 15, 2016, at 11:48 AM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
>>>> 
>>>>   on Mon May 09 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
>>>> 
>>>>           On May 8, 2016, at 1:51 AM, Dave Abrahams <dabrahams at apple.com> wrote:
>>>> 
>>>>           on Sat May 07 2016, Andrew Trick <atrick-AT-apple.com> wrote:
>>>> 
>>>>                 On May 7, 2016, at 2:04 PM, Dave Abrahams <dabrahams at apple.com> wrote:
>>>> 
>>>>                     2. Value types are not "pure" values if any part of the aggregate
>>>>                     contains a
>>>>                     reference whose type does not have value semantics. 
>>>> 
>>>>                 Then Array<Int> is not a “pure” value (the buffer contained in an
>>>>                 Array<Int> is a mutable reference type that on its own, definitely does
>>>>                 *not* have value semantics). I don't think this is what you intend, and
>>>>                 it indicates that you need to keep working on your definition.
>>>> 
>>>>               It sounds like you’re changing the definition of value semantics to make it
>>>>               impossible to define PureValue. 
>>>> 
>>>>           Not on purpose.
>>>> 
>>>>               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.  
>>>> 
>>>>               The claim has been made that Array always has value semantics,
>>>>               implying that the array value’s boundary ends at the boundary of it’s
>>>>               element values.
>>>> 
>>>>           Yes, an array value ends at the boundary of its elements' values.
>>>> 
>>>>               That fact is what allows the compiler to ignore mutation of the
>>>>               buffer.
>>>> 
>>>>           I don't know what you mean here.
>>>> 
>>>>               It's perfectly clear that Array<T> is a PureValue iff T is a PureValue.
>>>>               PureValue is nothing more than transitive value semantics.
>>>> 
>>>>           You're almost there.  “Transitive” implies that you are going to look at
>>>>           the parts of a type to see if they are also PureValue's.  So which parts
>>>>           of the Array struct does one look at, and why?  Just tell me the
>>>>           procedure for determining whether a type is a PureValue.
>>>> 
>>>>       We look at the observable parts.  
>>>> 
>>>>   That begs the question.  The “parts” of an Array are the observable
>>>>   features that are considered by equality.
>>>> 
>>>>       We do not look at unobservable parts because we want flexibility to
>>>>       use things like CoW, shared immutable references, etc in our
>>>>       implementation.
>>>> 
>>>>   IMO the important thing when it comes to functional purity is not what
>>>>   you *can* observe, but what you *do* observe.
>>>> 
>>>>       Can you share your definition of value semantics?  
>>>> 
>>>>   Explaining it well and in sufficient detail for this discussion takes
>>>>   some doing, but I think John Lakos and I share an understanding of value
>>>>   semantics and he has a really detailed explanation in
>>>>   https://www.youtube.com/watch?v=W3xI1HJUy7Q and
>>>>   https://www.youtube.com/watch?v=0EvSxHxFknM.  He uses C++ in places,
>>>>   but it's not particularly advanced, and the fundamental ideas apply just
>>>>   as well to Swift.
>>>> 
>>>> Super interesting talk! 
>>>> 
>>>> But consider: isn't a single value type able to represent *multiple*
>>>> ethereal types?
>>> 
>>> “ethereal?”  Does he really use that term?  I don't know what it means.
>>> 
>>>> 
>>>> std::vector is a good example. What are the salient attributes of this
>>>> type? In the talk John says that
>>>> 
>>>> 1. the size is
>>>> 2. the values in the vector are
>>>> 3. the capacity, however *is not*
>>> 
>>> Yup, just like Array.  Thus the equality test for arrays ignores
>>> capacity.
>>> 
>>>> in which case std::vector would be an approximation of an ethereal
>>>> type which has a list of values, and the capacity is just an artifact
>>>> of the approximation. But you could also imagine an ethereal type
>>>> which *does* depend of the capacity of the object, and std::vector
>>>> unwittingly approximates that type too! In this case someone,
>>>> unfamiliar with the implementation might use it under the assumption
>>>> that capacity *is* part of the ethereal type and by extension the
>>>> equality of std::vector.
>>>> 
>>>> John avoids the problem by saying that this must specified in the
>>>> documentation.
>>> 
>>> Yes.
>>> 
>>>> I tend to see this as breaking encapsulation since you need to know
>>>> the implementation of the equality operator to be able to determine if
>>>> a public property, the capacity, is part of the ethereal type. 
>>> 
>>> No, you just need documentation.
>>> 
>>>> It’s not always the case that you have access to either the
>>>> documentation or the implementation.
>>> 
>>> Without the documentation, you're lost.  We go a lot further with naming
>>> conventions in Swift than typical C++ does, but even in Swift you can't
>>> expect to fully understand semantics without documentation.
>>> 
>>>> This implies, therefore, that if salient attributes *define* the
>>>> immutability of the value type, then the public interface is not
>>>> guaranteed to be immutable, since it is allowed to include non-salient
>>>> attributes. For example, a vector’s capacity could change at any time,
>>>> by virtue of it being stored via a reference.
>>>> 
>>>> What I am saying is that a PureValue is a value type whose public
>>>> interface comprises *only* salient attributes. And I also claim that
>>>> this is a useful distinction amongst value types.
>>> 
>>> Then Array<Int> is not a PureValue because it exposes capacity?!  That
>>> sounds crazy to me, since the Array's capacity in no sense has reference
>>> semantics.
>>> 
>>>> John also says that a salient attribute must derive *only* from the
>>>> state of a particular instance of a type. This by extension implies
>>>> that a salient attribute must derive exclusively from pure
>>>> values. However, this also means that without some “indirect” keyword,
>>>> PureValues are restricted to acyclic and non-recursive structures.
>>>> 
>>>> I also claim that equality can be automatically generated for
>>>> PureValues by equating each of there salient attributes.
>>> 
>>> That's true for almost any value, provided we define equality for
>>> reference types properly.
>>> 
>>>> I really apologize if this seems like rambling again, but I am very
>>>> interested in this problem.
>>> 
>>> I'm glad you are! Few programmers dig far enough to understand value
>>> semantics at a deep level.
>>> 
>>> All that said, I still think PureValue is a red herring.  Unless I'm
>>> forgetting something that happened in the thread two weeks ago, nobody
>>> has shown me code that relies on PureValue but could not equally well be
>>> written by using a Value constraint.
>> 
>> Looking forward to hearing your thoughts on the code I just posted.
>> 
>> In addition to that, I think it is also important to note that
>> contained within the notion of PureValue is thread safety.  For
>> example, in CSP PureValues would can be sent as messages on a channel.
>> Clearly sending Array<MutableReferenceType> over a channel is
>> something you would not do in CSP.  
> 
> Not if you were interested in anything other than the identities of the
> elements.  But I can easily imagine representing a selection as a Set<T>
> and passing that across threads, where T might be a mutable reference
> type (using my default definition of == and hashValue for all
> references).

Hmmm.  My understanding of CSP is that it is intended to prevent mutable state from being visible in more than one “process” at the same time.  Synchronization happens by sending values across channels, not with the usual thread-oriented synchronization mechanisms like locks and semaphores, etc.

I realized I overstated the case a bit here.  There are certainly cases where you might want to transfer ownership of a reference through a channel.  It’s a shame that Swift doesn’t yet have the ability to talk about owned references and transfer of ownership.  I’m happy that Chris is supportive of eventually introducing an ownership system of some kind.

> 
>> You can also freely share a ImmutableBox<MyPureValue> and read from it
>> in any thread you wish without any trouble.  You cannot do that with
>> ImmutableBox<Array<MutableReferenceType>>.  In the latter, you cannot
>> mutate the array, but you can still mutate the objects it contains
>> references to.
> 
> Again, it depends on what you look at.  We could create a value type
> that distinguishes object identities, e.g.
> 
>     struct Identity<SomeClass : AnyObject> : Hashable, Comparable  {
> 
>       let subject: SomeClass
>       init(subject: SomeClass) { self.subject = subject }
>       ...         
>     }
> 
>     func == <X>(lhs: Identity<X>, rhs: Identity<X>) -> Bool {
>       return lhs === rhs
>     }
> 
> then you could write:
> 
>     ImmutableBox<Array<Identity<MutableReferenceType>>>
> 
> But would you really make it *impossible* to observe the subject of an
> Identity?  We could, but I'm not sure I would.
>  It would come at a cost
> to efficiency in those places where you have a collection of Identity's
> and you happen to know they're not shared across threads, which I think
> is probably an important use-case.

I’m not trying to argue that you shouldn’t be able to do things like this if you want to.  

What I am arguing for is the ability to distinguish aggregates which are logically isolated from aggregates which contain salient references to shared mutable state.  To be honest, I am really struggling to understand why this distinction seems unimportant to you.

> 
>>> 
>>>> Tyler
>>>> 
>>>>       It may be helpful
>>>>       if we start there and refine your definition to exclude impure value
>>>>       types like Array<UIView>.
>>>> 
>>>>       In the meantime I’ll take another shot:
>>>> 
>>>>       1. Scalars are pure values.
>>>> 
>>>>       2. Any aggregate type with value semantics is a pure value iff all
>>>>         observable parts of the aggregate are pure values.
>>>> 
>>>>   -- 
>>>>   -Dave
>>>>   _______________________________________________
>>>>   swift-evolution mailing list
>>>>   swift-evolution at swift.org
>>>>   https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> 
>>> 
>>> -- 
>>> -Dave
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> -- 
> -Dave
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160522/7cb88524/attachment.html>


More information about the swift-evolution mailing list