# ValueSemantic protocol

**URL:** <https://forums.swift.org/t/valuesemantic-protocol/41686>\
**Category:** Discussion\
**Created:** [November 2, 2020, 3:53am UTC](https://forums.swift.org/t/valuesemantic-protocol/41686 "2020-11-02T03:53:26Z")\
**Posts on this page:** 11\
**Page:** 7

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [April 26, 2021, 6:07pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/121 "2021-04-26T18:07:17Z")

</div>

I think value semantics are best summarized by an out-of-place transform function:

```swift
func transformedCopy<T>(
  _ x: T, transform: (inout T)->()
) -> T {
  var result = x
  transform(&result)
  return result
}

```

That implementation is correct if and only if `T` has value semantics.

• • •

More concretely, a type `T` has value semantics if and only if, for all possible instances of `T` and all possible `transform` operations (edit: which do not mutate anything other than the `inout` argument), the use of `transformedCopy` does not modify its argument.

Thus, in the following snippet:

```swift
var x: T = ...
// 1
let y = transformedCopy(x){ ... }
// 2

```

If at lines 1 and 2 we print out a complete description of all salient features of `x`, and they are not identical to each other, then `T` does not have value semantics.

In particular, if there exists any possible `x` and any possible `transform` (edit: same caveat as above) for which they are different, then the type does not have value semantics.

• • •

Edit:

Of course, if `transform` captures and mutates the variable which is being passed in as `x` then we get the same situation as in `MutableReference` above, so we ought to rule that out.

But even if it doesn’t, we can still get situations like this:

```swift
var a: Int = 1

var b: Int {
  get { a }
  set { a = newValue }
}

print(b) // 1

let c = transformedCopy(b){
  a += 1
  $0 += a
}

print(b) // 2

```

So indeed the definition is quite slippery.

I do, however, still maintain that the implementation of `transformedCopy` is correct if and only if `T` has value semantics. Indeed, functions like that are exactly and precisely where I would want to use a `T: ValueSemantics` constraint.

---

<div class="post-metadata">

**Author:** ![sighoya](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@sighoya](https://forums.swift.org/u/sighoya)\
**Post date:** [April 26, 2021, 9:24pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/122 "2021-04-26T21:24:31Z")

</div>

> [@zrfrank](#):
>
> Well, I think one could still argue that `a` is "value semantic", if we consider `b.value` is equivalent to call `{ a }()` at the call site, and `b.value += 2` is equivalent to ` { a += 2 }()` , i.e. the value of `a` is always captured, copied, assigned "on-site".

So you prefer to think it is some kind of mathematical equivalence taking every time it is called the closure argument `a` again into it.

Well this isn't the case for closures in general.  
But for now assume this is true.  
When `a` is passed, why does setting `a` in callee scope mutate the `a` in the caller scope, passing value `a` would normally allocate a new resource or reuse some resource which isn't accessed mutably by other vars.  
So mutating `a` in the callee shouldn't cause an effect in the caller scope unless we make it an `out` argument, but that would prohibit mutable shared access to other threads which I think is still possible with Swift closures.

> [@Nevin](#):
>
> More concretely, a type `T` has value semantics if and only if, for all possible instances of `T` and all possible `transform` operations (edit: which do not mutate anything other than the `inout` argument), the use of `transformedCopy` does not modify its argument.

I think a type with value semantic is a type which forces all variables bounded by this type to follow value semantics such that passing an instance of that type to a function mutating its first arguments is safe as the type forces the resource system to copy (parts of) the instance (lazily) in case a mutation occurs.

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dabrahams/32/9815_2.png) [@dabrahams](https://forums.swift.org/u/dabrahams)\
**Post date:** [April 26, 2021, 9:40pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/123 "2021-04-26T21:40:41Z")

</div>

> [@sighoya](#):
>
> I think what @algal describes here covers exactly value semantics.

What do you mean by “covers exactly?”

> [@](#):
>
> I think projecting value semantics to types is a failure, if we were allowed to pass structs by plain reference (not inout) then we would undermine the concept of "Value Semantics" for Types.

We can effectively pass structs by “plain reference” just by using an `UnsafePointer` (or a wrapped one) as a proxy. If that possibility breaks the idea that a type has value semantics, then the ability to form an `UnsafePointer` to a threadsafe queue breaks the idea that you can build a threadsafe type.

Unsafe operations aside, I don't understand how your claim is more meaningful than it would be to say “talking about immutable instances is a failure, because if we were allowed to mutate a let binding we'd undermine the concept of immutability,” which is clearly absurd. To me, your claim seems just as tautological. The language puts up certain guardrails that allow us (unsafe operations aside) to guarantee properties of the entities we define, be they types or instances. Not allowing you to form a reference to a value type instance is one of them.

> A type shouldn't provide value semantics, instead variables should do that with appropriate annotations/keywords.

Well, that's an interesting idea certainly, but:

1. It seems rather speculative; is there a language that reifies that idea?
2. If you don't tie value semantics to type, you are describing a very different concept than those of us who have been talking about (mutable) value semantics for many years. It may be a useful concept (maybe even more useful!) and is probably related, but I suggest for the sake of everyone's understanding that you pick different terminology.

The motivation behind the exercise of defining value semantics here was to capture what those of us discussing value semantics as a property of types for many years have meant, in a way that is useful and formalizable. If you are claiming that the definition I've offered doesn't do that, I'd like to better understand your reasons for saying so.

---

<div class="post-metadata">

**Author:** ![sighoya](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@sighoya](https://forums.swift.org/u/sighoya)\
**Post date:** [April 26, 2021, 10:30pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/124 "2021-04-26T22:30:33Z")

</div>

> [@dabrahams](#):
>
> What do you mean by “covers exactly?”

Okay, maybe a bit exaggerated, but I think it state quite well the point what value semantics are, they are all about treating variables as constants for values.

> [@dabrahams](#):
>
> We can effectively pass structs by “plain reference” just by using an `UnsafePointer` (or a wrapped one) as a proxy. If that possibility breaks the idea that a type has value semantics, then the ability to form an `UnsafePointer` to a threadsafe queue breaks the idea that you can build a threadsafe type.

I would exclude unsafe operations out of consideration as they introduce a possible axiom break in the type system, i.e. they introduce an assumption which may not hold.  
Yes unsafe keywords belong to the language but they represent a backdoor behind type system guarantees.

> [@dabrahams](#):
>
> I don't understand how your claim is more meaningful than it would be to say “talking about immutable instances is a failure, because if we were allowed to mutate a let binding we'd undermine the concept of immutability,”

Good point, but would you say a `let` is a `let` if we directly mutate it like a `var`?  
And would you say that a `struct` is a `struct` if we mutate it?

I think in case of the latter, this makes sense, but yeah, given the current semantics in Swift it may not be a struct anymore.

> [@dabrahams](#):
>
> It seems rather speculative; is there a language that reifies that idea?

I think Swift already did this to some extent with `inout`, [likewise](https://dlang.org/spec/const3.html) in D. D has also the `immutable` keyword making a deep copy of any type.  
Julia doesn't differentiate at all between value and reference types, all things are objects, you have structs for classes and structs, but still they tie (im)mutability to types.

> [@dabrahams](#):
>
> If you are claiming that the definition I've offered doesn't do that, I'd like to better understand your reasons for saying so

We can for sure consider value semantic types, but their value-semantics strongly depends on (future) keywords.

My concerns:

Did your definition exclude `Int` to be a value type?  
Most people would consider `Int` to follow Value Semantics, and now an integer variable changes because a closure changes this var in an unexpected way because the said closure is executed in a threaded context.

Even if we currently have a type following value semantics, does an addition of a keyword for variables break the conformance to the Value Semantic Protocol in the future, the other way around, is the evolution of Swift hindered with the introduction of the Value Semantic Protocol in adding new keywords for variables?

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dabrahams/32/9815_2.png) [@dabrahams](https://forums.swift.org/u/dabrahams)\
**Post date:** [April 27, 2021, 4:17pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/125 "2021-04-27T16:17:02Z")

</div>

> [@sighoya](#):
>
> they are all about treating variables as constants for values.

I'm not sure I understand what you mean, but on the face of it, this sounds like you mean something very different from what I mean when you say “value semantics.” For value semantics as I intend it to be interesting, mutation is required, so AFAICT it has nothing to do with treating anything as constant.

> [@sighoya](#):
>
> We can for sure consider value semantic types, but their value-semantics strongly depends on (future) keywords.

I disagree, and this goes directly to the nature of “value semantics” as I intend the phrase. A meaningful definition is not dependent on having language guarantees, just as `Collection` has meaning that can't be enforced by language mechanisms.

In fact, one of the most important points is that we can create types with value semantics by properly combining types that don't have value semantics. Any useful definition of value semantics has to allow for the creation of types like Swift's `Array<Int>`, which uses a reference type under the covers. It's _possible_ there's a collection of keywords and language features that simultaneously prevents all non-value-semantic use of reference types while _allowing their use in all ways that preserve value semantics_, but I'm not sure how we'd prove to ourselves that we'd actually found one. I am even less sure that—even if we _can_ find such a collection—it would be worth adding to the language, in terms of complexity cost.

None of that is to say we shouldn't try; it would be really interesting to see the result. But in the meantime, we have all these types whose variables have an independent, well-defined value, and there are all kinds of conclusions we can draw about thread-safety, side-effects, and local reasoning on that basis. My definition addresses that reality.

> [@sighoya](#):
>
> Did your definition exclude `Int` to be a value type?  
> Most people would consider `Int` to follow Value Semantics, and now an integer variable changes because a closure changes this var in an unexpected way because the said closure is executed in a threaded context.

Yes, `Int` is a value type by my definition. The fact that you can touch the same mutable `Int` value via multiple access paths when it is captured in a closure is not news nor is it a problem for my definition; the same thing happens when the `Int` is a stored property of a class instance. Closures and class instances have reference semantics in Swift. It's rather unfortunate, IMO, that Swift closures _implicitly_ capture by reference, making it all too easy to cause a problem unintentionally. IIUC there was supposed to be some work to address that in connection with the concurrency efforts, but I don't know what it is or how it's been realized.

---

<div class="post-metadata">

**Author:** ![sighoya](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@sighoya](https://forums.swift.org/u/sighoya)\
**Post date:** [April 27, 2021, 5:24pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/126 "2021-04-27T17:24:03Z")

</div>

> [@dabrahams](#):
>
> Yes, `Int` is a value type by my definition.

Damn, I wanted to ask if ` Int` is a value semantic type. Following your definition this seems to be true.  
But I don't think this is the case.

> [@dabrahams](#):
>
> For value semantics as I intend it to be interesting, mutation is required, so AFAICT it has nothing to do with treating anything as constant.

Puh, then we might talk past each other, treating anything as constant is only at abstraction, mutability or not for a operation on a constant + rebinding is just an implementation detail and solved by the backend then.

I'm referring to the vague definition of [wikipedia](https://en.wikipedia.org/wiki/Value_semantics). A more common term is [referential transparency](https://en.wikipedia.org/wiki/Referential_transparency)

Edit:

After long thinking, we need some point of clarification.

Does your definition of a value semantic type implies [value semantic behavior](https://en.wikipedia.org/wiki/Referential_transparency) for all declared variables of the said type?

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [September 21, 2021, 2:12pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/127 "2021-09-21T14:12:46Z")

</div>

What would go wrong if Siesta resource is a reference type?

In SwiftUI, I used State to hold optional reference to reference type, because it needed to be created and destroyed dynamically. In this case observing changes in identity are separated from observing changes in object state. Parent view is responsible for the former, why child views are responsible for the latter. Contract is pretty clear, and as long as all parties respect it - everything works well. It’s a somewhat exotic case, but IMO, not an anti-pattern.

---

<div class="post-metadata">

**Author:** ![Paul\_Cantrell](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/paul_cantrell/32/16764_2.png) [@Paul\_Cantrell](https://forums.swift.org/u/Paul_Cantrell)\
**Post date:** [September 21, 2021, 3:02pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/128 "2021-09-21T15:02:01Z")

</div>

> [@Nickolas\_Pohilets](#):
>
> What would go wrong if Siesta resource is a reference type?

Resources in Siesta are reference type, very close to being main thread actors in the new regime. It’s the resource payload that’s the concern. Two things:

1. The resource payload gets passed across thread boundaries. For this, the newly minted `Sendable` would suffice.
2. Resource observers will want to know what the content of the payload changes. For this, you truly do want value semantics, not just `Sendable`. One could finagle around it, but it does break the expectation of “if the state changes, views of that state will find out about it” that underlies all these reactive-programming-shaped approaches. The same applies in your SwiftUI case, I think.

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [September 22, 2021, 9:54pm UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/129 "2021-09-22T21:54:21Z")

</div>

Based on how Swift handles mutability of the class references, I agree with @Joe_Groff that “value” of the class type includes only object’s identity, and does not include object’s stored properties.

`let` declarations should have immutable value. Thus everything that can be mutated through `let`-variable is not a part of the value.

It is possible to have different mental model, but that means not benefiting from compiler’s mutability analysis. Which is a pretty high penalty, IMO.

Based on this definition of value, Swift already provides a protocol for semi-regular types, and it is `Any`. If value semantics means semi-regular type which can cross thread isolation boundaries, then `ValueSemantics = Any & ActorSendable = ActorSendable`.

I don’t think ValueSemantics is useful as a marker protocol, without any members (or any members in addition to ActorSendable). If protocol is empty, this means that the only thing that generic code does with values is just passing them around. Technically, even `Any` is sufficient for that.

Maybe instead it would be more useful to be able to write a protocol which declares some members and specifies if they are part of the value or not.

We already have a small tool to make a property not part of the value. If setter is marked as `nonmutating` by the logic above this excludes setter from the value.

I have a vague idea, that maybe this could be extended to declare that property is a part of the value. Currently we by default setters are mutating in the protocol, but protocol requirement will be satisfied by the non-mutating setter as well (all setters in classes are non-mutating). Maybe we need a new modifier, something like `mustmutate`, disallowing non-mutating implementations.

For read-only properties, it gets more complicated, we need to express “I don’t require a setter, but if you provide one, it must be mutating”.

Maybe both could be combined into a single modifier `value`.

Something like this:

```swift
protocol P {
    value var foo: Foo { get }
    value var bar: Bar { get set }
    var baz: Baz { get }
    func addBazObserver(observer: @escaping () -> Void) -> AnyCancellable
}

class User<T: P> {
    var item: T {
        didSet {
            // I can be confident that this is the only point where changes in foo and bar need to be handled.
            // But I know that with baz it’s more complicated.
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dabrahams/32/9815_2.png) [@dabrahams](https://forums.swift.org/u/dabrahams)\
**Post date:** [September 24, 2021, 4:32am UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/130 "2021-09-24T04:32:26Z")

</div>

> [@Nickolas\_Pohilets](#):
>
> Based on how Swift handles mutability of the class references, I agree with @Joe_Groff that “value” of the class type includes only object’s identity, and does not include object’s stored properties.
> 
> `let` declarations should have immutable value. Thus everything that can be mutated through `let` -variable is not a part of the value.
> 
> It is possible to have different mental model, but that means not benefiting from compiler’s mutability analysis. Which is a pretty high penalty, IMO.

It's not that cut-and-dried. It's easy to define an immutable `final` class whose value includes the stored properties; such types have perfectly well-behaved value semantics.

There's also the problem that the value of a type has to do with the _meaning_ of that type; in general, it's not mechanically derivable by looking at source code. In practice, people have written (mutable and/or subclassable) classes and given them `Equatable` conformances based on the stored properties. However ill-conceived, these types _do_ have a notional value that includes their stored properties.

> Based on this definition of value, Swift already provides a protocol for semi-regular types, and it is `Any` .

As noted in [my definition](https://forums.swift.org/t/valuesemantic-protocol/41686/59) of value semantics, it is true that any type can be said to have value semantics, depending on how we define its value. So it's legitimate, in a sense to say “every type has value semantics” and “`Any` is the protocol for values”… it's just… not useful. A distinction that includes everything has no meaning.

> I don’t think ValueSemantics is useful as a marker protocol, without any members (or any members in addition to ActorSendable). If protocol is empty, this means that the only thing that generic code does with values is just passing them around. Technically, even `Any` is sufficient for that.

The reason you can't find a set of required operations for value semantics (the hard, local reasoning, part) is that it is a purely semantic distinction, and what it specifies is a particular relationship between pass-by-value/assignment/initialization and all mutating operations on the type, whatever they may be.

Being purely semantic would not make a `ValueSemantic` protocol useless; this is probably the simplest generic algorithm you could write that depends on this relationship:

```swift
extension ValueSemantic {
  /// Returns a copy of `self`, with `mutator` applied.
  func mutated(by mutator: (inout Element)->Void) -> Self {
   var x = self
   mutator(&x)
   return x
  }
}

```

That said, I would be happy to have a `ValueSemantic` protocol refine `Equatable` or maybe `Hashable`, so it needn't lack syntactic requirements.

> Maybe instead it would be more useful to be able to write a protocol which declares some members and specifies if they are part of the value or not.

That's a fascinating thought… I can't quite see how it would play out, though.

> We already have a small tool to make a property not part of the value. If setter is marked as `nonmutating` by the logic above this excludes setter from the value.

That is true, but some properties that are not part of the value are read-only, like the `capacity` of an `Array`. And if we imagine that it could have a setter, the only way to implement that setter would be by mutating the `Array`… so `nonmutating` would be prohibited by the compiler.

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dabrahams/32/9815_2.png) [@dabrahams](https://forums.swift.org/u/dabrahams)\
**Post date:** [March 3, 2022, 1:10am UTC](https://forums.swift.org/t/valuesemantic-protocol/41686/132 "2022-03-03T01:10:57Z")

</div>

In case anyone is interested, a paper that (among other things) defines “mutable value semantics” has been accepted into the [Journal of Object Technology](http://www.jot.fm/)‘s upcoming issue. A preprint is available [here](https://daveabrahams.files.wordpress.com/2022/02/implementation_strategies_for_mutable_value_semantics-preprint.pdf).

(correcting link and deleting the original post, thanks @David_Sweeris !)

[Previous page](https://forums.swift.org/t/valuesemantic-protocol/41686.md?page=6)
