<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 3, 2016 at 1:17 PM, Douglas Gregor <span dir="ltr"><<a href="mailto:dgregor@apple.com" target="_blank">dgregor@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><div><div class="h5"><blockquote type="cite"><div>On Feb 3, 2016, at 1:10 PM, Jonathan Tang <<a href="mailto:jonathan.d.tang@gmail.com" target="_blank">jonathan.d.tang@gmail.com</a>> wrote:</div><br><div><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 3, 2016 at 9:44 AM, Douglas Gregor <span dir="ltr"><<a href="mailto:dgregor@apple.com" target="_blank">dgregor@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><blockquote type="cite"><span><div>On Feb 2, 2016, at 10:17 PM, Jonathan Tang via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br></span><div><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><br><br><div class="gmail_quote"><span>On Tue, Feb 2, 2016 at 4:32 PM, Dave Abrahams via swift-evolution<span> </span><span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span><span> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br></blockquote></span><div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">2. Words that describe attributes of an *already-existing* instance<br> should go in the base name rather than in a label:<br><br> <span> </span>a.tracksHavingMediaType("Wax Cylinder") // yes<br> <span> </span>a.removeFirstTrackHavingMediaType("BetaMax") // yes<br><br> <span> </span>a.tracks(mediaType: "Wax Cylinder") // no<br> <span> </span>a.removeFirstTrack(havingMediaType: "BetaMax") // no<br><br> [yes, we could use "With" instead of "Having", but it's more<br> ambiguous]<br><br> Words that describe attributes of an instance *to be created* should<br> go in argument labels, rather than the base name (for parity with<br> initializers):<br><br> <span> </span>AudioTrack(mediaType: "BetaMax") // initializer<br> <span> </span>trackFactory.newTrack(mediaType: "Wax Cylinder") // yes<br><br> <span> </span>trackFactory.newTrackWithMediaType("Wax Cylinder") // no<br><br></blockquote><div><br></div><div>Very mixed feelings on this, probably adding up to a +0.2 or so. I'll mention a couple concerns that I haven't seen anyone raise:</div><div><br></div><div>Please consider the first-class function case when naming. Particularly since Swift encourages passing functions around as objects rather than using string selectors. #2 implies that the prepositional phrase will appear when *referencing* the method (vs. calling it):</div><div><br></div><div> let ops = [</div><div> self.removeFirstTrackHavingMediaType,</div><div> self.addTrackWithMediaType</div><div> self.populateTrackOperationsForMediaType</div><div> self.play</div><div> ]</div><div><br></div><div>vs.</div><div><br></div><div> let ops = [</div><div> self.removeFirstTrack</div><div> self.addTrack</div><div> self.populateTrackOperations</div><div> self.play</div><div> ]</div><div><br></div><div>The second option wins on verbosity, but the first arguably gives more clarity as to what the methods actually do. Also, the second has a potentially annoying semantic problem: if you have overloads for these methods that differ only in keyword, Swift won't be able to disambiguate them:</div><div><br></div><div> // Compile error: Invalid redeclaration of removeFirstTrack</div><div> func removeFirstTrack(havingMediaType: String) { ... }</div><div> func removeFirstTrack(named: String) { ... }</div><div> func removeFirstTrack(byArtist: String) { ... }</div><div><div><br> // Compile error only when the function is referenced</div><div> func removeTrack(n: Int, named: String)</div><div> func removeTrack(n: Int, byArtist: String)</div><div> let f = self.removeTrack // named: or byArtist:?</div></div><div><br></div><div> // Legal...</div><div> func removeFirstTrackHavingMediaType(_: String) { ... }</div><div> func removeFirstTrackNamed(_: String) { ... }</div><div> func removeFirstTrackByArtist(_: String) { ... }</div><div><br></div><div>Unless the Swift compiler were to change to make the former set legal, I think this is a powerful argument in favor of this proposal, because otherwise you may find that the compiler prevents you from writing the code that the guidelines encourage. You might also find that changing the type of an overload means you have to change the name to prevent a collision, which could be very surprising to users.</div></div></div></div></div></div></div></blockquote><br></div><div>I suspect that you missed SE-0021:</div><div><br></div><div><span style="white-space:pre-wrap">        </span><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0021-generalized-naming.md" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0021-generalized-naming.md</a></div><div><br></div><div>which lets you name the arguments in a function reference, e.g:</div><div><br></div><div><span style="white-space:pre-wrap">        </span>let f = self.removeTrack(_:named:)</div><div><div><span style="white-space:pre-wrap">        </span>let f2 = self.removeTrack(_:byArtist:)</div><div><br></div><div><span style="white-space:pre-wrap">        </span>let ops = [</div><div><span style="white-space:pre-wrap">        </span> self.removeFirstTrack(mediaType:),</div><div><span style="white-space:pre-wrap">        </span> self.addTrack(mediaType:),</div><div><span style="white-space:pre-wrap">        </span> self.populateTrackOperationsForMediaType,</div><div><span style="white-space:pre-wrap">        </span> self.play</div><div><span style="white-space:pre-wrap">        </span>]</div><div><span style="white-space:pre-wrap">        </span></div></div><div><span style="white-space:pre-wrap">        </span>- Doug</div><div><br></div><br></div></blockquote></div><br></div><div class="gmail_extra"><br></div><div class="gmail_extra">There's still no outstanding proposal to that lets you disambiguate functions only by the first argument at the point of definition, right?</div><div class="gmail_extra"><br></div><div class="gmail_extra"> class C {</div><div class="gmail_extra"> // Still a compiler error: "Invalid redeclaration of doSomething"</div><div class="gmail_extra"><span> </span><span>func</span><span> doSomething(withBar: </span><span>String</span><span>) -> </span><span>String</span><span> { </span><span>return</span><span> </span><span>"Bar</span><span>\</span><span>(</span><span>withBar</span><span>)"</span><span> }</span></div><div class="gmail_extra"><span> </span><span>func</span><span> doSomething(withFoo: </span><span>String</span><span>) -> </span><span>String</span><span> { </span><span>return</span><span> </span><span>"Foo</span><span>\</span><span>(</span><span>withFoo</span><span>)"</span><span> }</span></div><div class="gmail_extra"> }</div><div class="gmail_extra"><br></div><div class="gmail_extra">Without this, I think there's still a big problem with moving the preposition to the first argument label, because it leads to recommended names that don't compile.</div></div></div></blockquote><div><br></div></div></div><div>You’re tripping over the default behavior. If you want two different functions, doSomething(withBar:) and doSomething(withFoo:), then you need to specifically provide an argument label for each:</div><div><br></div><div><span style="white-space:pre-wrap">        </span>class C {</div><div><span style="white-space:pre-wrap">        </span> func doSomething(withBar bar: String) -> String { return “Bar\(withBar)” }</div><span style="white-space:pre-wrap">        </span> func doSomething(withFoo foo: String) -> String { return “Foo\(withFoo)” }</div><div><span style="white-space:pre-wrap">        </span>}</div><div><br></div><div>Per SE-0021, you can reference these with “C.doSomething(withBar:)” and “C.doSomething(withFoo:)”, respectively.</div><div><span class=""><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra">With SE-0021 and the ability to define overloads that differ only in the first-arg label (they'd have to be called or referenced with the label, otherwise you'd get a compiler error at point of use) I think I'd move to about -0.5 on proposal #2, because:</div><div class="gmail_extra"><br></div><div class="gmail_extra">1. Moving the preposition to the first argument adds brevity in the common case where there is no overload conflict.</div><div class="gmail_extra">2. You can still disambiguate or add clarity at the point of reference by including all the argument labels</div><div class="gmail_extra">3. It's more uniform with how you'd reference multi-arg functions.</div></div>
</div></blockquote><div><br></div></span><div>Given the above clarification, does this opinion still hold?</div></div><div><br><span style="white-space:pre-wrap">        </span></div><div><span style="white-space:pre-wrap"><br></span></div></div></blockquote><div><br></div><div>Thanks, yes it does. </div></div><br></div></div>