CocoaPods trunk is moving to be read-only. Read more on the blog, there are 14 months to go.
| TestsTested | ✓ |
| LangLanguage | SwiftSwift |
| License | MIT |
| ReleasedLast Release | Sep 2016 |
| SPMSupports SPM | ✓ |
Maintained by Tom Quist.
Equals is a Swift µframework to reduce boilerplate code when conforming to Equatable and Hashable protocols.
Add to your Package.swift dependencies:
import PackageDescription
let package = Package(
// ... your project details
dependencies: [
// As a required dependency
.Package(url: "ssh://[email protected]/tomquist/Equals.git", majorVersion: 2)
],
testDependencies: [
// As a test dependency
.Package(url: "ssh://[email protected]/tomquist/Equals.git", majorVersion: 2)
]
)Lets start with a simple struct:
struct Person {
let firstName: String?
let lastName: String
let children: [Person]
}To conform this type to Equatable we first have to declare conformance, e.g. by providing an empty extension and provide an operator overload for ==:
extension Person: Equatable {}
func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.firstName == rhs.firstName
&& lhs.lastName == rhs.lastName
&& lhs.children == rhs.children
}As you can see, this is a lot of code for such a simple type and each property is listed twice.
Even worse, when conforming to Hashable you additionally have to provide a complex hashValue property:
extension Person: Hashable {
var hashValue: Int {
var result = 17
result = 31 &* result &+ (firstName?.hashValue ?? 0)
result = 31 &* result &+ lastName.hashValue
for child in children {
result = 31 &* result &+ child.hashValue
}
return result
}
}Using Equals, this is a lot easier. To conform to Hashable, all you have to do is to conform to the EqualsHashable protocol:
extension Person: EqualsHashable {
static let hashes: Hashes<Person> = Hashes()
.append {$0.firstName}
.append {$0.lastName}
.append {$0.children}
}If you don’t need hashing capabilities, just conform to the EqualsEquatable protocol:
extension Person: EqualsEquatable {
static let equals: Equals<Person> = Equals()
.append {$0.firstName}
.append {$0.lastName}
.append {$0.children}
}That’s it! Now you can compare your type, using the == operator, put it into Sets or use it as a Dictionary key.
Equals currently provides append functions for four types of properties:
Equatable/Hashable propertiesOptional properties of type Equatable/Hashable CollectionType properties where the elements are Equatable/Hashable Sometimes, you explicitly have to specify which append method to use. E.g. lets change the property children of our Person example above into type Set<Person>. Because Set already conforms to Hashable, we now get a compiler error:
Ambiguous use of 'append(hashable:)'
This is because there are potentially several append methods that could be used in this situation. To avoid this error, we can change our implementation of EqualsHashable into this:
extension Person: EqualsHashable {
static let hashes: Hashes<Person> = Hashes()
.append {$0.firstName}
.append {$0.lastName}
.append(hashable: {$0.children})
}