You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* Classes are reference types. E.g a `Temperature` class with farenheit property
* When you want to prevent sharing, you manually copy that object.
* Defensive copying
* Copying is all over cocoa touch and objective-c
* NSString, NSArray, NSDictionary all defensively copy. They conform to `NSCopying`
* e.g - NSDictionary calls `-copy` on its keys
* Copying helps, but it's never good enough. You still have bugs. What if we had immutable objects with reference semantics?
### Immutability
* Eliminates many problems caused by reference semantics w/ mutation
* You can't have unintended side effects
* Some downsides:
* can lead to awkard interfaces, i.e: cannot do `temperature.farenhiet += 10.0`
* does not map efficiently to the machine model
* Example: Sieve of Eratosthenes
* Swift implementation
* Entirely relies on mutation
* Here's a "beautiful" Haskell implementation
* Paper by Melisa O'Neill called "The Genuine Seive of Eratosthenes" - shows that the haskel implementation isn't as performant as people thing it is
* Immutability in cocoa/cocoa touch
* e.g NSDate, NSURL, UIImage, NSNumber, etc.
* Improved safety, since there's no need to use copy
* Inefficient - i.e. what if you want to build up a URL from a bunch of components?
* In conclusion, you can't go totally without immutability or you'd be crazy.
### Value Semantics
* Easy to use, straightforward
* Mutating one variable of some value type will never affect a different variable
* We already use it for small types, ie Integer, `CGPoint`. Swift extends this behavior to more complex types.
* In Swift, dicitonaries, arrays, strings, etc. are all values types.
* Value types are composable
* Equality is established by the value of a variable. Not by its identity. Not by how we arrived at the value
**Recommendation*: All your value types should implement `Equatable`
* `==` must be:
* reflexive (`x==x` is `true)
* symetric (if `x==y` then `y==x`)
* transitive (missed this example)
* Defining a value type with `let` will prevent you from chaing its properties
* It seems like there's no actual benefit to using `let` when creating a value type
* Works beautifully in swift.
* `let` means "the value will never change"
* `var` means you can update the value without affecting any other values
* Value types means freedom from race conditions! #blessed
* Performance: What about all those copies? Isn't that lowering performance?
* Nope, copying is cheap in swift. It's constant time. for low level fundamental types and structs, enums or tuples of value types
* Extensible data structures use copy-on-write. I.e for string, dictionaries, arrays.
* They're not copied until necessary
### Value Types in Practice
* Example: Build a diagram made of a circle and a polygone
```
struct Circle: Equatable {
var center: CGPoint
var radius: Double
... (missed the init method)
}
struct Polygon: Equatable {
var corners: [CGPoint] = []
}
//pt 2
protocol Drawable {
func draw()
}
extension Polygon: Drawable {
func draw() { //Draw via core graphics }
}
extension Circle: Drawable {
func draw() { //Draw via core graphics }
}
//pt3
struct Diagram: Drawable {
var items: [Drawable] = []
}
var doc = Diagram()
doc.addItem(Polygon())
doc.addItem(Circle())
doc.addItem(Diagram())
doc.addItem(doc) // This would infinitely recurse if we were using reference semantics. But actually, it's a completely separate instance being added to the array, so it's fine. No problem here.
//missed something here
```
### Mixing value types and reference types
* A value type *can* contain a reference
* Copies of the value type will share the reference
* How is equality affected by this?
* When implementing `==`, you have to use isEqual for reference types.
* References to mutable objects
* ex: 2 instances of `BezierPath` (custom struct) each referencing the same `UIBezierPath`
* Implement copy-on-write
* Use the mutable reference type (carefully) to avoid tooo much copying
### Impleenting Undo using value types
```
var doc = Diagram()
var undoStack: [Diagram] = []
undoStack.append(doc)
doc.addItem(Polygon())
undoStack.append(doc)
doc.addItem(Circle())
undoStack.append(doc)
```
* Every action results in a doc instance
* efficient because of copy on write
* This is the technique used by photoshop
* It slices your photo into tiles represented by value types
* The whole document is represented by a collection of tiles.