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

Dave Abrahams dabrahams at apple.com
Sun May 8 01:02:51 CDT 2016


on Sat May 07 2016, Matthew Johnson <matthew-AT-anandabits.com> wrote:

>> 
>> You haven't answered this question.  How would you use this protocol?
>
> I think the best example was given by Andy when discussing pure
> functions.  Maybe I want to write a generic function and ensure it is
> pure.  I can only do this if I know that any arguments received that
> compare equal will always present the same observable state.  

And that it doesn't touch any globals.

> For example, maybe I wish to memoize the result.
>
> I cannot write such a function for all T, and I also cannot write such
> a function for all T that have value semantics if we adopt the
> “references are values” view of the world.  

Oh, you absolutely can, because if the function applies to all T that
have value semantics, it only has a few operations to work with:
initialization, assignment, and equality.  Assignment is the only
mutating one of these.

> I need an additional constraint that rejects things like
> Array<UIView>.  (T would obviously also be constrained by a protocol
> that exposes the properties or methods my function requires to compute
> its result)

Did you just start referring to T as the element type of the array
instead of the function's parameter type?  I think you're
unintentionally pulling a fast one, reasoning-wise.  It might help to
write down some actual code.

> In general, it would be used where you need to ensure that the result
> of any operation observing the state of any part of the aggregate
> value will always return the same value at any point in the future.
> If I observe a[0].foo now I know with certainty the result of
> observing a[0].foo at any point in the future.  

Sure, but what you need then is a constraint on a's Element type that it
has value semantics, not some kind of new PureValue concept to use as a
constraint on the array itself.  

> This aspect of preservation of observed values across time is
> essential to the distinction between Array<LayoutValue> (see below)
> and Array<UIView>.  It doesn’t matter when I observe the frames of the
> elements of Array<LayoutValue>, I will always get the same rects back.
> With Array<UIView> that is obviously not the case as the frame of the
> view could be mutated by anyone with a reference to the views at any
> time in between my observations of the frame values.
>
> struct LayoutValue {
> 	frame: CGRect
> }
>
>> 
>>>            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

-- 
-Dave


More information about the swift-evolution mailing list