Created
December 12, 2019 19:59
-
-
Save vasarhelyia/2609a22915a0c63cde6ea492cda178ce to your computer and use it in GitHub Desktop.
Trying to find a way to "update" properties of immutable objects without losing their type information
This file contains 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
import Foundation | |
class A { | |
let bool: Bool | |
let string: String | |
init(bool: Bool = false, string: String = "A") { | |
self.bool = bool | |
self.string = string | |
} | |
} | |
class B: A { | |
let int: Int | |
init(bool: Bool, string: String, int: Int) { | |
self.int = int | |
super.init(bool: bool, string: string) | |
} | |
} | |
class C: A { | |
let float: Float | |
init(bool: Bool, string: String, float: Float) { | |
self.float = float | |
super.init(bool: bool, string: string) | |
} | |
} | |
class D: A { | |
let float1: Float | |
let float2: Float | |
init(bool: Bool, string: String, float1: Float, float2: Float) { | |
self.float1 = float1 | |
self.float2 = float2 | |
super.init(bool: bool, string: string) | |
} | |
} | |
func updateFlag(objects: [A]) -> [A] { | |
return objects.map { A(bool: true, string: $0.string) } | |
} | |
let objects: [A] = [ | |
B(bool: false, string: "B", int: 1), | |
C(bool: false, string: "C", float: 1.0), | |
D(bool: false, string: "D", float1: 1.0, float2: 1.0) | |
] | |
print("1. \(updateFlag(objects: objects).map { "name: \($0.string), type: \($0.self)"})") | |
// ["1. name: B, type: A", "name: C, type: A", "name: D, type: A"] | |
// 2. Adding a lens for "updating" the flag | |
struct Lens<T, P> { | |
let from : (T) -> P | |
let to : (P, T) -> T | |
} | |
let flag: Lens<A, Bool> = Lens( from: { $0.bool }, to: { A(bool: $0, string: $1.string) }) | |
func lensUpdateFlag(objects: [A]) -> [A] { | |
return objects.map { return flag.to(false, $0) } | |
} | |
print("2. \(lensUpdateFlag(objects: objects).map { "name: \($0.string), type: \($0.self)"})") | |
// ["2. name: B, type: A", "name: C, type: A", "name: D, type: A"] | |
// 3. Adding one lens per type for "updating" the flag | |
let flagB: Lens<B, Bool> = Lens( from: { $0.bool }, to: { B(bool: $0, string: $1.string, int: $1.int) }) | |
let flagC: Lens<C, Bool> = Lens( from: { $0.bool }, to: { C(bool: $0, string: $1.string, float: $1.float) }) | |
let flagD: Lens<D, Bool> = Lens( from: { $0.bool }, to: { D(bool: $0, string: $1.string, float1: $1.float1, float2: $1.float2) }) | |
// Have to switch over types to update | |
func lensTypeSpecificUpdateFlag(objects: [A]) -> [A] { | |
return objects.map { | |
switch $0 { | |
case let b as B: | |
return flagB.to(false, b) | |
case let c as C: | |
return flagC.to(false, c) | |
case let d as D: | |
return flagD.to(false, d) | |
default: return $0 | |
} | |
} | |
} | |
print("3. \(lensTypeSpecificUpdateFlag(objects: objects).map { "name: \($0.string), type: \($0.self)"})") | |
// ["3. name: B, type: B", "name: C, type: C", "name: D, type: D"] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment