Sent from my iPad
> On May 9, 2016, at 3:01 AM, Andrew Trick <atr...@apple.com> wrote: > > >>> On May 7, 2016, at 11:51 PM, Dave Abrahams <dabrah...@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
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution