Regards
(From mobile)

> On May 22, 2016, at 9:23 PM, Matthew Johnson via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> 
>> On May 22, 2016, at 1:10 PM, Dave Abrahams via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> 
>> on Mon May 16 2016, Matthew Johnson <swift-evolution@swift.org> wrote:
>> 
>>>> On May 16, 2016, at 1:39 AM, Dave Abrahams <dabrah...@apple.com> wrote:
>>>> 
>>>> 
>>>> on Sun May 15 2016, Tyler Fleming Cloutier <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@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 <dabrah...@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 
>>>>> <dabrah...@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.
> 

There was a recent talk about some changes to the structure of the ISA pointer 
and brief mention about where some thread info could be added


>> 
>>> 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@swift.org
>>>>>   https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>> 
>>>> 
>>>> -- 
>>>> -Dave
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> -- 
>> -Dave
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to