<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=""><div class="">Let’s try again with less of a sleepy-sick stupor. =)</div><div class=""><br class=""></div><div class="">My concern is that the name of the function is the only indicator for non-struct types when looking at the signature. For structs, we can get more assurance; e.g. the bug demonstrated below cannot happen. However, that doesn’t mean the opposite bug is avoidable: return a copying instead of mutating self.</div><div class=""><br class=""></div><div class=""><div class="">The problem I was trying to illustrate, and did a really poor job at, is that the convention doesn’t actually provide us with any guarantees that our implementations are correct. So when I say this:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">I guess my point is this: codifying a convention seems pre-mature as that convention doesn't bring the safety goals of the language into a place that's verifiable. All of the other guidelines are simply about clarity of use, this convention has a far reaching impact.</blockquote></div></div><div class=""><br class=""></div><div class="">Here’s a demonstration of when the guidelines was applied incorrectly, either due to ignorance of the guidelines or simply a copy/paste type bug.</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">var bar = Bar(items: [2, 1, 3])</font></div><div class=""><font face="Menlo" class="">let filteredBar = bar.filter { $0 != 3 }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">bar.items // output: [2, 1 3]</font></div><div class=""><font face="Menlo" class="">filteredBar.items // output: [2, 1]</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let filteredSortedBar = bar</font></div><div class=""><font face="Menlo" class=""> .filter { $0 != 3 }</font></div><div class=""><font face="Menlo" class=""> .sort()</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">bar.items // output: [2, 1, 3]</font></div><div class=""><font face="Menlo" class="">filteredSortedBar.items // output: [1, 2]</font></div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">let sortedFilterBar = bar</font></div><div class=""><font face="Menlo" class=""> .sort()</font></div><div class=""><font face="Menlo" class=""> .filter { $0 != 3 }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">bar.items // output: [1, 2, 3] WHAT?</font></div><div class=""><font face="Menlo" class="">sortedFilterBar.items // output: [1, 2]</font></div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">var expected = Bar(items: [2, 1, 3])</font></div><div class=""><span style="font-family: Menlo;" class="">expected</span></div><div class=""><font face="Menlo" class=""> .filterInPlace { $0 != 3 }</font></div><div class=""><font face="Menlo" class=""> .sortInPlace()</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><span style="font-family: Menlo;" class="">expected.items // output: [1, 2]</span></div></blockquote><div class=""><br class=""></div><div class="">When reading the code with an understanding of the guidelines, this code is misleading as to what it should be doing. That’s what I find dangerous. Of course, we can argue on the merits of these types of bugs, but we’ve all seen conventions misused and it sucks.</div><div class=""><br class=""></div><div class="">If this convention is just a stop-gap until a language feature can be built to help with this, then ok. </div><div class=""><br class=""></div><div class="">-David</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">sample implementation that demonstrates the bug that gets us out-of-sync with the guidelines:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">public class Bar<T : Comparable> {</font></div><div class=""><font face="Menlo" class=""> var items: [T]</font></div><div class=""><font face="Menlo" class=""> </font></div><div class=""><font face="Menlo" class=""> init(items: [T]) {</font></div><div class=""><font face="Menlo" class=""> self.items = items</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> </font></div><div class=""><font face="Menlo" class=""> func sortInPlace() -> Self {</font></div><div class=""><font face="Menlo" class=""> self.items.sortInPlace { $0 < $1 }</font></div><div class=""><font face="Menlo" class=""> return self</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> </font></div><div class=""><font face="Menlo" class=""> func sort() -> Self {</font></div><div class=""><font face="Menlo" class=""> self.items.sortInPlace { $0 < $1 }</font></div><div class=""><font face="Menlo" class=""> return self</font></div><div class=""><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class="">}</span></div><div class=""><font face="Menlo" class=""> </font></div><div class=""><font face="Menlo" class=""> func filterInPlace(includeElement: (T) -> Bool) -> Self {</font></div><div class=""><font face="Menlo" class=""> self.items = self.items.filter(includeElement)</font></div><div class=""><font face="Menlo" class=""> return self</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> </font></div><div class=""><font face="Menlo" class=""> func filter(includeElement: (T) -> Bool) -> Bar<T> {</font></div><div class=""><font face="Menlo" class=""> let newItems: [T] = self.items.filter(includeElement)</font></div><div class=""><font face="Menlo" class=""> return Bar(items: newItems)</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 24, 2016, at 7:18 PM, Dave Abrahams <<a href="mailto:dabrahams@apple.com" class="">dabrahams@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class="">on Sun Jan 24 2016, David Owens II <<a href="http://david-at-owensd.io" class="">david-AT-owensd.io</a>> wrote:<br class=""><br class=""><blockquote type="cite" class="">Sorry, I meant to add the do() version too in order to show the<br class="">difference better. /sigh<br class=""></blockquote><br class="">do() version?<br class=""><br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" class="">On Jan 24, 2016, at 4:53 PM, David Owens II via swift-evolution<br class=""><<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">I guess my point is this: codifying a convention seems pre-mature as<br class="">that convention doesn't bring the safety goals of the language into a<br class="">place that's verifiable. All of the other guidelines are simply about<br class="">clarity of use, this convention has a far reaching impact.<br class=""></blockquote><br class="">Sorry, could you clarify what you mean by "bring the safety goals of the<br class="">language into a place that's verifiable" and clarify why having a "far<br class="">reaching impact" would somehow conflict with being "about clarity of use?"<br class=""><br class="">It seems to me that this convention is about how to express whether a<br class="">method is going to mutate so it's clear at the use-site. What am I<br class="">missing?<br class=""></blockquote><br class=""><br class="">The problem is it's unclear to me whether you mean mutate in the<br class="">true sense of the word or only applied to a struct with a function<br class="">annotated with the mutating keyword.<br class=""><br class="">The naming convention provides no safety when dealing with<br class="">non-struct types as we cannot enforce that a method on a class does<br class="">not mutate it's internal members.<br class=""><br class="">That's the clarity I'm looking for.<br class=""><br class="">Given this API set:<br class=""><br class="">protocol InPlaceable {<br class=""> mutating func doInPlace()<br class="">}<br class=""><br class="">public struct Foo: InPlaceable {<br class=""> mutating func doInPlace() {}<br class="">}<br class=""><br class="">public class Bar: InPlaceable {<br class=""> func doInPlace() {}<br class="">}<br class=""><br class="">var lie: InPlaceable = Bar()<br class="">lie.doInPlace()<br class=""><br class="">let lie2 = Bar()<br class="">lie2.doInPlace()<br class=""><br class="">The convention will tell us a lie unless we are extremely<br class="">careful. It's this lie that concerns me. We cannot guarantee that<br class="">the "doInPlace" truly matches the definition we are seeking.<br class=""><br class=""><br class="">-David<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=""></blockquote><br class=""></blockquote><br class="">-- <br class="">-Dave<br class=""></div></div></blockquote></div><br class=""></body></html>