Open ShannonChenCHN opened 4 years ago
2019.09.13
函数式编程
函数式编程的缺陷
举例子:埃拉托斯特尼筛选法
Cocoa(Touch) 中的 Immutablity
Variables Are Logically Distinct
Value Types Compose
Value Types Are Distinguished by Value
Equatable
Mutation When You Want It, But not when you don’t
Freedom from Race Conditions
Performance: What about all those copies?
see sample code
Value types generally used for “primitive” data of objects:
class Button : Control { var label: String var enabled: Bool // ... }
Copies of the value type will share the reference:
struct ButtonWrapper { var button: Button }
Maintaining value semantics requires special considerations:
Reference identity is not enough:
struct Image : Drawable { var topLeft: CGPoint var image: UIImage } extension Image : Equatable { static func ==(lhs: Image, rhs: Image) -> Bool { // return lhs.topLeft == rhs.topLeft && lhs.image === rhs.image return lhs.topLeft == rhs.topLeft && lhs.image.isEqual(rhs.image) } } var image = Image(topLeft: CGPoint(x: 0, y: 0), image: UIImage(imageNamed:"San Francisco”)!) var image2 = image
在上面的例子中,image 属性是不可变的引用类型,所以不用担心数据的安全性。但是判断相等性时,不能以引用值是否相等作为依据,而应该将其当做值类型一样根据内容去判断对等性。
Unexpected mutation:
struct BezierPath: Drawable { var path = UIBezierPath() var isEmpty: Bool { return path.empty } func addLineToPoint(point: CGPoint) { path.addLineToPoint(point) // Unexpected mutation❌ } }
在上面的例子中,因为 path 属性是可变的引用类型,所以在 addLineToPoint 方法被调用时,path 属性值可能会被改变。
addLineToPoint
struct BezierPath: Drawable { private var _path = UIBezierPath() var pathForReading: UIBezierPath { return _path } var pathForWriting: UIBezierPath { mutating get { _path = _path.copy() as! UIBezierPath return _path } } } extension BezierPath { var isEmpty: Bool { return pathForReading.empty } mutating func addLineToPoint(point: CGPoint) { pathForWriting.addLineToPoint(point) } } var path = BezierPath() var path2 = path var path2 = path if path.empty { print("Path is empty") } var path2 = path path.addLineToPoint(CGPoint(x: 10, y: 20)) path.addLineToPoint(CGPoint(x: 100, y: 125))
The standard library value types uses this throughout:
struct MyWrapper { var _object: SomeSwiftObject var objectForWriting: SomeSwiftObject { mutating get { if !isKnownUniquelyReferenced(&_object)) { _object = _object.copy() } return _object } } }
延伸阅读:
Swift 中的值类型(Building Better Apps with Value Types in Swift)
2019.09.13
1. Reference Semantics
2. Immutablity 是否是一个解决方案?
函数式编程
函数式编程的缺陷
举例子:埃拉托斯特尼筛选法
Cocoa(Touch) 中的 Immutablity
3. Value Semantics
Variables Are Logically Distinct
Value Types Compose
Value Types Are Distinguished by Value
Equatable
Mutation When You Want It, But not when you don’t
Freedom from Race Conditions
Performance: What about all those copies?
4. Value Types in Practice
see sample code
5. Mixing value types and reference types
5.1 Reference Types Often Contain Value Types
Value types generally used for “primitive” data of objects:
5.2 A Value Type Can Contain a Reference
Copies of the value type will share the reference:
Maintaining value semantics requires special considerations:
5.3 Immutable References and Equatable
Reference identity is not enough:
在上面的例子中,image 属性是不可变的引用类型,所以不用担心数据的安全性。但是判断相等性时,不能以引用值是否相等作为依据,而应该将其当做值类型一样根据内容去判断对等性。
5.4 References to Mutable Objects
Unexpected mutation:
在上面的例子中,因为 path 属性是可变的引用类型,所以在
addLineToPoint
方法被调用时,path 属性值可能会被改变。5.5 Copy On Write
The standard library value types uses this throughout:
延伸阅读:
小结
参考