> On May 7, 2016, at 3:03 PM, Dave Abrahams <dabrah...@apple.com> wrote:
> 
> 
> on Sat May 07 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:
> 
>> This depends on the type. For types representing resources, etc it works just
>> fine. But for models it does not work unless the model subgraph is entirely
>> immutable and instances are unique. 
>> I agree that it isn't a good idea to provide a default that will
>> certainly be wrong in many cases.
> 
> Please show an example of a mutable model where such an equality would
> be wrong.  

This is somewhat orthogonal to the main points I have been making in this 
thread.  I have been focused on discussion about reference types that have 
value semantics and the distinction between value semantics and pure values.  
In any case, here you go:

let a: NSMutableArray = [1, 2, 3]
let other: NSMutableArray = [1, 2, 3]
let same = a === other // false
let equal = a == other // true

Reference equality does not match the behavior of many existing mutable model 
types.  You seem to be making a case that in Swift it should.  But that is a 
separate discussion from the one I am trying to engage in because mutable 
reference types *do not* have value semantics.  

> 
>>    I assume what is meant by "PureValue", is any object A, whose own 
>> references
>>    form a subgraph, within which a change to any of the values would 
>> constitute
>>    a change in the value of A (thus impermissible if A is immutable). Thus
>>    structs would quality as “PureValues”.
>> 
>> As you noted in a followup, not all structs qualify. Structs that whose 
>> members
>> all qualify will qualify. References to a subgraph that doesn't allow for any
>> observable mutation (i.e. deeply immutable reference types) also qualify.
>> 
>> This means the following qualify:
>> 
>> * primitive structs and enums
>> * observable immutable object subgraphs
>> * any type composed from the previous
>> 
>> It follows that generic types often conditionally qualify depending on their
>> type arguments.
>> 
>>    I also assume that enforcing immutability on an object graph, via CoW or
>>    otherwise, would be unfeasible. You could enforce it on all values
>>    accessible by traversing a single reference for reference types, however.
>> 
>>    This is why I don’t really buy the argument that there is no such this as
>>    deep vs shallow copy. Deep copy means copying the whole “PureValue” or
>>    subgraph, shallow copy means traversing a single reference and copying all
>>    accessible values.
>> 
>>                I don’t mean to imply that it is the *only* valuable
>>            property. However, it I (and many others) do believe it is an
>>            extremely
>>            valuable
>>            property in many cases. Do you disagree?
>> 
>>            I think I do. What is valuable about such a protocol? What generic
>>            algorithms could you write that work on models of PureValue but
>>            don't
>>            work just as well on Array<Int>?
>> 
>>            Array<Int> provides the semantics I have in mind just fine so 
>> there
>>            wouldn’t be
>>            any. Array<AnyObject> is a completely different story. With
>>            Array<AnyObject> you cannot rely on a guarantee the objects
>>            contained
>>            in the array will not be mutated by code elsewhere that also 
>> happens
>>            to have a reference to the same objects.
>> 
>>        Okay then, what algorithms can you write that operate on PureValue 
>> that
>>        don't work equally well on Array<AnyObject>?
> 
> You haven't answered this question.  How would you use this protocol?

I answered elsewhere but I’ll repeat that one use that immediately comes to 
mind is to constrain values received in the initializer of a (view) controller 
to ensure that the observable state will not change over time.  This is not an 
algorithmic use but is still perfectly valid IMO.

If I read Andrew’s post correctly it sounds like it may also be of use to the 
optimizer in some cases.

> 
>>            let t = MyClass()
>>            foo.acceptWrapped(Wrap(t))
>>            t.mutate()
>> 
>>            In this example, foo had better not depend on the wrapped instance
>>            not
>>            getting
>>            mutated.
>> 
>>            foo has no way to get at the wrapped instance, so it can't depend 
>> on
>>            anything about it.
>> 
>>            Ok, but this is a toy example. What is the purpose of Wrap? Maybe
>>            foo
>>            passes the
>>            wrapped instance back to code that *does* have visibility to the
>>            instance. My
>>            point was that shared mutable state is still possible here. 
>> 
>>            And my point is that Wrap<T> encapsulates a T (almost—I should 
>> have
>>            let
>>            it construct the T in its init rather than accepting a T 
>> parameter)
>>            and
>>            the fact that it's *possible* to code something with the structure
>>            of
>>            Wrap so that it has shared mutable state is irrelevant.
>> 
>>            The point I am trying to make is that the semantic properties of
>>            Wrap<T> depend
>>            on the semantic properties of T (whether or not non-local mutation
>>            may be
>>            observed in this case). 
>> 
>>        No they do not; Wrap<T> was specifically designed *not* to depend on 
>> the
>>        semantic properties of T. This was in answer to what you said:
>> 
>>                A struct wrapping a mutable reference type certainly doesn’t
>>            “feel” value semantic to me and certainly doesn’t have the
>>            guarantees usually associated with value semantics (won’t
>>            mutate behind your back, thread safe, etc).
>> 
>>        I have been trying to get you to nail down what you mean by PureValue,
>>        and I was trying to illustrate that merely being “a struct wrapping a
>>        mutable reference type” is not enough to disqualify anything from 
>> being
>>        in the category you're trying to describe. What are the properties of
>>        types in that category, and what generic code would depend on those
>>        properties?
> 
> Again, the key questions are above, asked a different way.
> 
> -- 
> -Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to