afaik KeyPath must always be concrete
say you have property myArray: Int[] (which conforms to Collection), that doesn't mean you can safely assign a dictionary [String: Float] to it just because the dictionary is also a Collection (yet key path is still KeyPath<MyClass, any Collection>. get the idea?
I guess you can experiment with parameter packs, for example this works import Foundation func hash<T, each P: Hashable>( _ item: T, props: repeat KeyPath<T, each P> ) -> Int { var hasher = Hasher() repeat (hasher.combine(item[keyPath: each props])) return hasher.finalize() } struct Example { var p1 = 0 var p2 = true var p3 = "string" } print( hash(Example(), props: \.p1, \.p2, \.p3), hash(Example(), props: \.p1, \.p2, \.p3), hash(Example(), props: \.p1, \.p2), separator: "\n" ) Output: -4549848955267135610 -4549848955267135610 3558766014151656816
try writing to WritableKeyPath with protocol
Well I guess it might not work, but this will (at least you can declare another overload in isolation from the logic) public struct HashingPath<Root> { @usableFromInline internal let _extract: (Root) -> AnyHashable @inlinable public init<Value: Hashable>(_ path: @escaping (Root) -> Value) { self._extract = { path($0) } } // You can declare more overloads here @inlinable public func extract(from root: Root) -> AnyHashable { return _extract(root) } } public func hash<T>(_ item: T, props: [HashingPath<T>]) -> Int { return props.reduce(into: Hasher()) { hasher, prop in hasher.combine(prop.extract(from: item)) }.finalize() }
Btw this works with the first implementation struct Example { var string: String = "" var protocolValue: any Hashable = 0 } hash(Example(), props: \.string, { AnyHashable($0.protocolValue) })
так, стой, у тебя тип свойства структуры — протокол (ставить туда ты можешь любое значение с этим протоколом). но ты не можешь писать в конкретное значение протокольное значение. WritableKeyPath туда тоже не запишет ничего
Так изначально проблема не подразумевала запись, но вообще по идее решение со структурой будет нормально работать
Обсуждают сегодня