Skip to content

Instantly share code, notes, and snippets.

@jayrhynas
Created October 16, 2024 14:34
Show Gist options
  • Save jayrhynas/cf7a56fdf3f3edaf17386e9412c20ee2 to your computer and use it in GitHub Desktop.
Save jayrhynas/cf7a56fdf3f3edaf17386e9412c20ee2 to your computer and use it in GitHub Desktop.
@dynamicMemberLookup
struct Compose<Left, Right> {
var left: Left
var right: Right
subscript<Value>(dynamicMember keyPath: KeyPath<Left, Value>) -> Value {
left[keyPath: keyPath]
}
subscript<Value>(dynamicMember keyPath: KeyPath<Right, Value>) -> Value {
right[keyPath: keyPath]
}
subscript<Value>(dynamicMember keyPath: WritableKeyPath<Left, Value>) -> Value {
get { left[keyPath: keyPath] }
mutating set { left[keyPath: keyPath] = newValue }
}
subscript<Value>(dynamicMember keyPath: WritableKeyPath<Right, Value>) -> Value {
get { right[keyPath: keyPath] }
mutating set { right[keyPath: keyPath] = newValue }
}
}
extension Compose: Equatable where Left: Equatable, Right: Equatable {}
extension Compose: Hashable where Left: Hashable, Right: Hashable {}
extension Compose: Encodable where Left: Encodable, Right: Encodable {
func encode(to encoder: any Encoder) throws {
try left.encode(to: encoder)
try right.encode(to: encoder)
}
}
extension Compose: Decodable where Left: Decodable, Right: Decodable {
init(from decoder: Decoder) throws {
try self.init(
left: Left(from: decoder),
right: Right(from: decoder)
)
}
}
extension Compose: Identifiable where Left: Identifiable, Right: Identifiable {
var id: Compose<Left.ID, Right.ID> {
.init(left.id, right.id)
}
}
extension Compose {
init(_ left: Left, _ right: Right) {
self.left = left
self.right = right
}
}
typealias Compose3<A, B, C> = Compose<Compose<A, B>, C>
typealias Compose4<A, B, C, D> = Compose<Compose<A, B>, Compose<C, D>>
extension Compose3 {
init<A, B>(_ a: A, _ b: B, _ c: Right) where Left == Compose<A, B> {
self.init(.init(a, b), c)
}
}
extension Compose4 {
init<A, B, C, D>(_ a: A, _ b: B, _ c: C, _ d: D) where Left == Compose<A, B>, Right == Compose<C, D> {
self.init(.init(a, b), .init(c, d))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment