<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 18, 2016, at 2:58 PM, Jacob Bandes-Storch via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">Would it make sense for the standard library Set to provide variants (or parallel versions of the same data structure) that take custom hashValue/== implementations at init time (functions taking in Elements), rather than relying on Hashable/Comparable protocols?</div><div class=""><br class=""></div><div class="">Use case: I want a set of objects that are compared for equality using === rather than ==. This doesn't seem possible today, using Set, without creating some sort of wrapper object.</div><div class=""><br class=""></div><div class="">This particular case would be analogous to using NSHashTable with NSPointerFunctionsObjectPointerPersonality. (Maybe all I'm asking for is a Swiftier API for NSHashTable — including ArrayLiteralConvertible, using generics instead of UnsafePointer&lt;Void&gt;, etc.)</div><div class=""><br class=""></div><div class="">Similarly, C++'s <a href="http://en.cppreference.com/w/cpp/container/unordered_map" class="">unordered_map</a>&nbsp;and friends have template parameters specifying the hash function and equality comparator, which use std::hash and == by default.</div><div class=""><br class=""></div><div class="">(Apologies if this has been discussed already; I haven't seen it.)<br clear="all" class=""><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class="">Jacob<br class=""></div></div></div></div>
</div></div></div></blockquote><br class=""></div><div>At an implementation level, we already pass a bundle of function pointers for the Equatable and Hashable conformances as part of the generic calling convention. In the implementation model, protocol conformances are independent entities, so technically the same type could conform to the same protocol multiple times in different ways. We could theoretically let you provide a scoped private conformance to Hashable overriding the default one:</div><div><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div>func foo() {</div><div>&nbsp; extension Int: private Hashable {</div><div>&nbsp; &nbsp; var hashValue: Int { return myHash(self) }</div><div>&nbsp; }</div><div><br class=""></div><div>&nbsp; // This dictionary would use the local Int: Hashable</div><div>&nbsp; let dict: Foo&lt;Int, Int&gt; = [...]</div><div><br class=""></div><div>&nbsp; use(dict)</div><div>}</div></blockquote><br class=""><div class="">Now, there would definitely be weird effects to this, since it allows for types that look the same but are formally different, since the `Key: Hashable` conformance is an implicit parameter to the type. For example, this wouldn't work:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div>func returnMyWeirdDictionary() -&gt; Dictionary&lt;Int, Int&gt; {</div></div><div class=""><div>&nbsp; extension Int: private Hashable {</div></div><div class=""><div>&nbsp; &nbsp; var hashValue: Int { return myHash(self) }</div></div><div class=""><div>&nbsp; }</div></div><div class=""><div><br class=""></div></div><div class=""><div>&nbsp; // This dictionary would use the local Int: Hashable</div></div><div class=""><div>&nbsp; let dict: Foo&lt;Int, Int&gt; = [...]</div></div><div><br class=""></div><div>&nbsp; // ERROR: dict has type Dictionary&lt;Int, Int&gt; (using local Int: Hashable conformance),</div><div>&nbsp; // but return type is declared Dictionary&lt;Int, Int&gt; (using default Int: Hashable conformance)</div><div>&nbsp; return dict</div><div class=""><div>}</div></div></blockquote><div class=""><br class=""></div><div class="">It also has interesting interactions with the runtime's support for protocol conformance lookup via `x as? P` casts—if there's more than one P conformance for the dynamic type of x, which one should the runtime pick?</div><div class=""><br class=""></div><div class="">-Joe</div></body></html>