Last active
May 5, 2020 06:48
-
-
Save inamiy/0ec54da159f01a7215f4125f65d375ae to your computer and use it in GitHub Desktop.
This file contains 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
// https://twitter.com/inamiy/status/1257538502226358272 | |
struct Hashable1: Hashable { | |
struct Hashable1a: Hashable {} | |
} | |
struct Hashable2: Hashable {} | |
Hashable1().hashValue | |
Hashable1.Hashable1a().hashValue | |
Hashable2().hashValue | |
// all same | |
AnyHashable(Hashable1()).hashValue | |
AnyHashable(Hashable1.Hashable1a()).hashValue | |
AnyHashable(Hashable2()).hashValue | |
// all same | |
var dict: [AnyHashable: Int] = [Hashable1(): 999] | |
//dict[Hashable1()] // 999 | |
//dict[Hashable1.Hashable1a()] // nil | |
//dict[Hashable2()] // nil | |
//---------------------------------------- | |
enum Hashables: Hashable { | |
case x1(Hashable1) | |
case x1a(Hashable1.Hashable1a) | |
case x2(Hashable2) | |
} | |
var dict2: [Hashables: Int] = [.x1(Hashable1()): 999] | |
dict2[.x1(Hashable1())] // 999 | |
dict2[.x1a(Hashable1.Hashable1a())] // nil | |
dict2[.x2(Hashable2())] // nil | |
//---------------------------------------- | |
struct MyAnyHashable: Equatable, Hashable { // NOTE: Ugly impl. | |
let _hashValue: Int | |
let _hash: (inout Hasher) -> Void | |
let _isEqual: (Any) -> Bool | |
let _value: Any | |
init<H: Hashable>(_ value: H) { | |
self._hashValue = value.hashValue | |
self._hash = value.hash(into:) | |
self._isEqual = { | |
if let x = $0 as? H { | |
return value == x | |
} else { | |
return false | |
} | |
} | |
self._value = value | |
} | |
var hashValue: Int { self._hashValue } | |
func hash(into hasher: inout Hasher) { _hash(&hasher) } | |
static func == (l: MyAnyHashable, r: MyAnyHashable) -> Bool { | |
l._isEqual(r._value) | |
} | |
} | |
var dict3: [MyAnyHashable: Int] = [MyAnyHashable(Hashable1()): 999] | |
dict3[MyAnyHashable(Hashable1())] // 999 | |
dict3[MyAnyHashable(Hashable1.Hashable1a())] // nil | |
dict3[MyAnyHashable(Hashable2())] // nil | |
// P.S. Just to make sure `MyAnyHashable` works like `AnyHashable`... | |
AnyHashable(Hashable1()) == AnyHashable(Hashable1()) // true | |
AnyHashable(Hashable1()) == AnyHashable(Hashable2()) // false | |
MyAnyHashable(Hashable1()) == MyAnyHashable(Hashable1()) // true | |
MyAnyHashable(Hashable1()) == MyAnyHashable(Hashable2()) // false | |
//---------------------------------------- | |
// https://twitter.com/inamiy/status/1257558273676328960 | |
struct Foo: Hashable { | |
let value: String | |
init(_ value: String) { self.value = value } | |
// Manual impl | |
static func == (l: Foo, r: Foo) -> Bool { | |
return true | |
// return l.value == r.value | |
} | |
// Manual impl | |
func hash(into hasher: inout Hasher) { | |
hasher.combine(self.value) | |
} | |
} | |
Foo("ok") == Foo("not ok") | |
Foo("ok") == Foo("err") | |
var dict4: [Foo: Int] = [Foo("ok"): 999] | |
dict4[Foo("ok")] // 999 | |
dict4[Foo("not ok")] // sometimes 999, sometimes not! | |
dict4[Foo("err")] // sometimes 999, sometimes not! | |
// Quiz: Try using / commenting-out "Manual impl"s to see behavior difference. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Explanation from @lorentey : https://twitter.com/lorentey/status/1257549455907160066