Last active
June 19, 2019 03:19
-
-
Save owenv/c8c8816d37b089e05e731f5fecb61da1 to your computer and use it in GitHub Desktop.
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
protocol Equatable2 { | |
//@memberwiseDerivable(mapper: equatable2Mapper, reducer: equatable2Reducer, reduceInitialResult: true) | |
static func == (_: Self, _: Self) -> Bool | |
} | |
// lhs and rhs come from the derived requirement, memberKeyPath is added to the argument list | |
// the return type must match the reducer's argument types | |
// Self is replaced by generic parameter T, U is the type of the member (which conforms to the given protocol) | |
func equatable2Mapper<T, U: Equatable2>(_ lhs: T, _ rhs: T, memberKeyPath: KeyPath<T, U>) -> Bool { | |
return lhs[keyPath: memberKeyPath] == rhs[keyPath: memberKeyPath] | |
} | |
// the argument types must match the return type of the mapper | |
// the return type must match the return type of the derived requirement | |
func equatable2Reducer(_ first: Bool, _ second: Bool) -> Bool { | |
return first && second | |
} | |
// Dummy manually conforming type | |
struct A: Equatable2 { | |
static func == (lhs: A, rhs: A) -> Bool { | |
return true | |
} | |
} | |
// Dummy manually conforming type | |
struct B: Equatable2 { | |
static func == (lhs: B, rhs: B) -> Bool { | |
return true | |
} | |
} | |
// Example memberwise conforming type | |
struct Compound: Equatable2 { | |
let a: A = A() | |
let a2: A = A() | |
let b: B = B() | |
// Compiler Synthesized | |
static func == (lhs: Compound, rhs: Compound) -> Bool { | |
return equatable2Reducer(equatable2Reducer(equatable2Reducer(true /* reduceInitialResult expression from attribute */, | |
equatable2Mapper(lhs, rhs, memberKeyPath: \Compound.a)), | |
equatable2Mapper(lhs, rhs, memberKeyPath: \Compound.a2)), | |
equatable2Mapper(lhs, rhs, memberKeyPath: \Compound.b)) | |
} | |
} | |
print(Compound() == Compound()) | |
protocol Hashable2 { | |
//@memberwiseDerivable(mapper: hashable2Mapper, reducer: hashable2Reducer, reduceInitialResult: ())) | |
func hash(into: inout Hasher) | |
} | |
// self parameter is added with generic type T, into: argument is from derived requirement, memberKeyPath is added | |
func hashable2Mapper<T, U: Hashable2>(`self`: T, into hasher: inout Hasher, memberKeyPath: KeyPath<T, U>) -> Void { | |
`self`[keyPath: memberKeyPath].hash(into: &hasher) | |
} | |
// Reducer doesn't need to do anything in this case, the mapper takes care of everything | |
func hashable2Reducer(_ first: Void, _ second: Void) -> Void { | |
return | |
} | |
// Dummy manual conformance | |
extension A: Hashable2 { | |
func hash(into: inout Hasher) { | |
return | |
} | |
} | |
// Dummy manual conformance | |
extension B: Hashable2 { | |
func hash(into: inout Hasher) { | |
return | |
} | |
} | |
// Example memberwise conformance | |
extension Compound: Hashable2 { | |
// Compiler Synthesized | |
func hash(into hasher: inout Hasher) { | |
return hashable2Reducer(hashable2Reducer(hashable2Reducer(() /* reduceInitialResult expression from attribute */ , | |
hashable2Mapper(self: self, into: &hasher, memberKeyPath: \Compound.a)), | |
hashable2Mapper(self: self, into: &hasher, memberKeyPath: \Compound.a2)), | |
hashable2Mapper(self: self, into: &hasher, memberKeyPath: \Compound.b)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment