<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 14 Mar 2017, at 19:30, Joe Groff 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 class=""><br class=""><blockquote type="cite" class="">On Mar 14, 2017, at 11:27 AM, David Hart &lt;<a href="mailto:david@hartbit.com" class="">david@hartbit.com</a>&gt; wrote:<br class=""><br class=""><br class=""><br class=""><blockquote type="cite" class="">On 14 Mar 2017, at 16:41, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Mar 13, 2017, at 8:38 AM, Vincent Esche via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">Source compatibility<br class=""><br class="">Making use of "extending protocols to conform to protocols":<br class=""><br class="">extension Hashable: HashVisitable <br class="">{<br class=""><br class="">func hash&lt;H: Hasher&gt;(_ hasher: inout<br class="">H) {<br class=""><br class="">self.hashValue.hash(&amp;<br class="">hasher)<br class=""> &nbsp;}<br class="">}<br class=""></blockquote><br class="">We're unlikely to add this feature soon. It seems reasonable to me to instead have `HashVisitable` refine `Hashable` and provide a default implementation of `hashValue` using a default hasher. I think we still want `Hashable` to be the currency protocol most APIs work with for performance in unspecialized code, since we could inline the visitation and hasher implementation together inside the specialized `hashValue` witness.<br class=""></blockquote><br class="">Can you explain the performance argument? How does it fare (in your opinion) compared to the arguments in the proposal?<br class=""><br class="">How about:<br class=""><br class="">protocol Hashable {<br class=""> &nbsp;&nbsp;func hash&lt;H: Hasher&gt;(with hasher: inout H)<br class="">}<br class=""><br class="">extension Hashable {<br class=""> &nbsp;&nbsp;var hashValue: Int {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var hasher = StdLibDefaultHasher()<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash(with: hasher)<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return hash.finish()<br class=""> &nbsp;&nbsp;}<br class="">}<br class=""></blockquote><br class="">For unspecialized code that takes a generic T: Hashable, that will place the only dynamic dispatch point on `hash`, so that will place an abstraction barrier between the Hasher and Self type being hashed, so would likely mean a dynamic call for every component of the value being hashed. Having `hashValue` be a dynamic dispatch point allows the hasher to be inlined together with the type's visitor implementation.<br class=""><br class="">-Joe<br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></div></blockquote></div><div class=""><br class=""></div>Couldn’t we solve that by adding hashValue with the protocol requirements (and with a default implementation)? IIRC, the standard library already does this for things like map. They are defined as requirements even though they are completely optional in practice.<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class="">protocol Hashable {</div></div></div><div class=""><div class=""><div class="">&nbsp;&nbsp;func hash&lt;H: Hasher&gt;(with hasher: inout H)</div></div></div><div class=""><div class="">&nbsp; var hashValue: Int { get }</div></div><div class=""><div class="">}</div></div><div class=""><div class=""><br class=""></div></div><div class=""><div class="">extension Hashable {</div></div><div class=""><div class="">&nbsp;&nbsp;var hashValue: Int {</div></div><div class=""><div class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var hasher = StdLibDefaultHasher()</div></div><div class=""><div class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash(with: hasher)</div></div><div class=""><div class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return hash.finish()</div></div><div class=""><div class="">&nbsp;&nbsp;}</div></div><div class=""><div class="">}</div></div></blockquote>- Karl<div class=""><span id="x-apple-selection:end"></span></div></body></html>