Created
April 6, 2022 03:43
-
-
Save allevato/e657394c82a687a78bb8bc8d9ffd59ce to your computer and use it in GitHub Desktop.
How to compare two Anys for equality in Swift
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
/// Returns a Boolean value indicating whether the two arguments are equal according to their | |
/// conformance to `Equatable`. | |
/// | |
/// If `lhs` and `rhs` are the same type and that type conforms to ``Equatable``, then this function | |
/// returns the result of evaluating `==` on those values. Otherwise (if the values are different | |
/// types, or the same type but the type does not conform to `Equatable`), this function returns | |
/// false. | |
func areValuesEqual(_ lhs: Any, _ rhs: Any) -> Bool { | |
func isOpenedValueEqual<LHS>(to openedLHS: LHS) -> Bool { | |
let equatable = ExistentialOperations<LHS>.self as? ExistentialEquatable.Type | |
return equatable?.areValuesEqual(lhs, rhs) ?? false | |
} | |
return _openExistential(lhs, do: isOpenedValueEqual(to:)) | |
} | |
/// A host for operations involving an opened existential. | |
/// | |
/// This type cannot be instantiated and has no operations of its own. It is meant to be extended | |
/// with conditional conformances based on the conformances implemented by `Value`. Then, when this | |
/// type is specialized inside functions passed to `_openExistential`, `Value` refers to the | |
/// concrete type of the opened value. Therefore, operations on the concrete `Value` type can be | |
/// invoked indirectly through those conditional conformances. | |
private enum ExistentialOperations<Value> {} | |
/// Provides an operation to test if two existential values are equal. | |
private protocol ExistentialEquatable { | |
/// Returns true if and only if and `lhs` and `rhs` are the same type and are equal. | |
static func areValuesEqual(_ lhs: Any,_ rhs: Any) -> Bool | |
} | |
extension ExistentialOperations: ExistentialEquatable where Value: Equatable { | |
fileprivate static func areValuesEqual(_ lhs: Any,_ rhs: Any) -> Bool { | |
guard let lhsCast = lhs as? Value, let rhsCast = rhs as? Value else { | |
return false | |
} | |
return lhsCast == rhsCast | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment