The Mutation Game • Victor the Valucist: • chooses a type Foo • defends value of variable v • Salazar the SideEffector: • defines attack statement, using variable s • defines pure audit function valueOf
The Mutation Game Players: Victor the Valucist vs Salazar the SideEffector. Arena: var v:Foo = Foo() // Valucist chooses Foo to var s = v // defend the variable v let v0 = valueOf(v) /* { SideEffector attacks v using only s } */ let v1 = valueOf(v) assert(v0 == v1) // v unchanged? Valucist wins!
Valucist wins with Int var v:Int = 100 var s = v let v0 = valueOf(v) s = 200 // attempted attack! let v1 = valueOf(v) assert(v0 == v1) // but true, Valuecist wins!
SideEffector wins with NSMutableString var v:NSMutableString = NSMutableString() var s = v let v0 = valueOf(v) s.append("Hello, world") // attempted attack! let v1 = valueOf(v) assert(v0 == v1) // false! SideEffector wins
So what? Benefits of value types • prevent unintended mutation • makes reasoning easier and more local • makes functions great again • helps with thread safety
Many great talks on value types ! Building Better Apps with Value Types, Gregor & Dudney, wwdc2015/s414; ! Making Friends with Value Types, Matuschak (2015), Realm; ! Protocol-Oriented Programming, Abrahams, wwdc2015/s408; ! What’s New in Foundation for Swift, Parker & LeHew, wwdc2016/s207; ! Value of Values. Rich Hickey (2012), InfoQ; ! Structs or Class. Crawford (2016); ! When to Use Swift Structs and Classes. Ash (2015). Value Semantics and Concepts-based Polymorphism Sean Parent (2012), BoostCon.
Does SideEffector win with classes? • No. Consider immutable classes. var v:UIImage = UIImage(named:"smile.jpg") var s = v let v0 = valueOf(v) // Hammer on s all you please. It's useless! let v1 = valueOf(v) assert(v0 == v1)
Does Valucist win with structs? • No. Consider structs containing classes: var v:Array = [NSMutableString()] var s = v let v0 = valueOf(v) s[0].append("Hello, world") let v1 = valueOf(v) assert(v0 == v1) // false, SideEffector wins
The Mutation Game is the defining test of value semantics A type Foo has value semantics if the Valucist always wins: var v:Foo = Foo() // Valucist chooses Foo to defend v var s = v let v0 = valueOf(v) /* { SideEffector attacks v using only s } */ let v1 = valueOf(v) assert(v0 == v1) // v unchanged? Valucist wins!
conceptual definition of value semantics Value semantics is a guarantee of the independence of values of variables. A type has value semantics if the only way to modify a variable's value is through the variable itself. (where a variable's value is just the value of its instance, and an instance's value is defined as if by Equatable.)
Recipe for Value Semantic Types • primitive value type → sit tight They provide value semantics by default. • reference type → make it immutable Use let-constant stored properties of value semantic types. • composite value type → make a choice • either, use stored properties all of value semantic types • or, handle the tricky copy-on-write case
Recipe for Value Semantic Types The tricky copy-on-write case 1. Pick the value semantic access level for the type's users 2. Restrict any mutable reference-type properties to a lower acces level 3. Define accessible setters and mutating functions to copy the mutable instance instead of mutating a shared instance 4. Verify it passes the Mutation Game Test.
One consistent survey response: 1. Are structs value types? Yes, definitionally, since they use assign-by-(shallow)-copy. 2. Do structs have value semantics? No. But yes when designed to pass the mutation game test. 3. Are classes value types? No, by definition, as they use assign-by-reference. 4. Do class have value semantics? No. But yes when immutable.
Key points (my take?) on value semantics • definable as: only a variable can affect its own value • testable by: the Mutation Game • can be built by recipe, from value or reference types • defined relative to access level • is about interface
Acknowledgements Thanks for informal discussion and manuscript criticisms: • Chris Belanger, Russ Bishop, Alan Cannistraro, Chris Eidhof, Benjamin Encz, Tyler Fox, Steven Van Impe, Andy Matuschak, Jordan Rose All errors are where I did not listen.