<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 Jan 27, 2016, at 2:09 AM, Radosław Pietruszewski &lt;<a href="mailto:radexpl@gmail.com" class="">radexpl@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">This is great! Thank you Doug for taking a look at this.</div><div class=""><br class=""></div><div class="">This is a huge patch, so I haven’t looked through it all, but a few interesting bits:</div><div class=""><br class=""></div><div class=""><pre style="word-wrap: break-word; white-space: pre-wrap;" class=""><blockquote type="cite" class="">-  func finishWritingWithCompletionHandler(handler: () -&gt; Void)
+  func finishWriting(completionHandler handler: () -&gt; Void)</blockquote></pre><div class="">This is something I mentioned in my review of SE-0023. An example with a completionHandler param was made in the Guidelines (that should have an explicit label because it has a default value), and I argued that it would make sense for the “completionHandler” to have a label _even if it didn’t have a default value_. A few examples in the diff seem to confirm this notion for me.</div></div></div></div></blockquote><div><br class=""></div>Ah, good point. “WithCompletionHandler” is a well-followed convention, so I’d expect to see more</div><div><br class=""></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><pre style="word-wrap: break-word; white-space: pre-wrap;" class=""><blockquote type="cite" class="">-  func respondWith(data: Data)
+  func respond(data data: Data)</blockquote></pre></div><div class="">This one is unusual. I don’t mind `respond(data: …)`, but generally there’s a word to the right of “with”, and here the “with” was just to imply the argument without naming it.</div></div></div></blockquote><div><br class=""></div>The original ObjC method name was “respondWithData:”. “Data” restates type info, so SE-0023 stripped it off; this transformation makes it the first argument label.<br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><pre style="word-wrap: break-word; white-space: pre-wrap;" class=""><blockquote type="cite" class="">-  class func instantiateWith(audioComponentDescription: AudioComponentDescription, options: AudioComponentInstantiationOptions = [], completionHandler: (AVAudioUnit?, Error?) -&gt; Void)
+  class func instantiate(componentDescription audioComponentDescription: AudioComponentDescription, options: AudioComponentInstantiationOptions = [], completionHandler: (AVAudioUnit?, Error?) -&gt; Void)</blockquote></pre><div class="">Another unusual one. I don’t know AV* APIs, but for whatever reason they have an “instantiate” class method instead of just init. But just like with init the first param name is moved from the “initWithFoo” name to an label, here it also seems to make a lot of sense.</div></div></div></div></blockquote><div><br class=""></div><div>Note that the instantiated audio unit is provided to a completion handler, so this can’t be an initializer.</div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><pre style="word-wrap: break-word; white-space: pre-wrap;" class=""><blockquote type="cite" class="">-  func indexOfItemWithTitle(title: String) -&gt; Int
-  func indexOfItemWithTag(tag: Int) -&gt; Int
-  func indexOfItemWithRepresentedObject(obj: AnyObject?) -&gt; Int
-  func indexOfItemWithTarget(target: AnyObject?, andAction actionSelector: Selector) -&gt; Int
+  func indexOfItem(title title: String) -&gt; Int
+  func indexOfItem(tag tag: Int) -&gt; Int
+  func indexOfItem(representedObject obj: AnyObject?) -&gt; Int
+  func indexOfItem(target target: AnyObject?, andAction actionSelector: Selector) -&gt; Int</blockquote></pre><div class="">An example of a method family that does the same fundamental job but takes different parameters. To me, it makes a ton of sense that they have the same name and then overload it by parameters. You couldn’t do that in ObjC, but I suppose that’s how a Swift-first API would be designed. But if you do that, it’s good for readability to have the first parameter explicitly described.</div></div></div></div></blockquote><div><br class=""></div><div>Thanks for the feedback!</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>- Doug</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">
<div class="">— Radek</div>
</div>
<br class=""><div class=""><blockquote type="cite" class=""><div class="">On 27 Jan 2016, at 08:50, Douglas Gregor &lt;<a href="mailto:dgregor@apple.com" class="">dgregor@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jan 25, 2016, at 6:55 AM, Radosław Pietruszewski &lt;<a href="mailto:radexpl@gmail.com" class="">radexpl@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Hello all,</div><div class=""><br class=""></div><div class="">I’m overwhelmingly *for* this proposal. I think removing needless verbosity and keeping the signal-to-noise ratio high is one of the most immediately appealing aspects of Swift, as well as a great general improvement to the programming experience.</div><div class=""><br class=""></div><div class="">And so unswiftified (yes, it’s a word now) APIs from Objective-C stick out like a sore thumb. Not only are they harder to read and write, they visually overwhelm the less verbose, information-dense Swift-first code.</div><div class=""><br class=""></div><div class="">Just like previous 1.0—2.0 attempts at bridging the gap (with NSError params being translated to Swift errors, factory methods translated to initializers, etc.), automating this will be an error-prone process, and almost bound to be a bit annoying at first, before all the glitches and poor translations are smoothed out. And yet I feel like just like the previous automated translations were overwhelmingly a great thing, so will the result of this proposal.</div><div class=""><br class=""></div><div class="">* * *</div><div class=""><br class=""></div><div class=""><div class=""></div><blockquote type="cite" class=""><div class="">&nbsp; &nbsp;Add First Argument Labels</div><div class="">&nbsp; &nbsp;</div><div class="">&nbsp; &nbsp;- func enumerateObjectsWith(_: NSEnumerationOptions = [], using: (AnyObject, UnsafeMutablePointer) -&gt; Void)</div><div class="">&nbsp; &nbsp;+ func enumerateObjects(options _: NSEnumerationOptions = [], using: (AnyObject, UnsafeMutablePointer) -&gt; Void)</div></blockquote><br class=""></div><div class="">Good! The Guidelines recommend an explicit first parameter label for arguments with a default value, but this is a good change also for another reason, a use case not included in the Guidelines (I have more to say about this in the SE-0023 thread):</div><div class=""><br class=""></div><div class="">“Options” is the description of the parameter, not the method itself. Even if (for whatever reason!) `options` didn’t have a default value and the word “Options” wasn’t omitted in the translation,</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;enumerateObjects(options: …)</div><div class=""><br class=""></div><div class="">would be clearer than</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;enumerateObjectsWithOptions(…)</div><div class=""><br class=""></div><div class="">It’s not even about the extra word, about the four useless characters, it’s simply that “WithOptions” doesn’t describe the operation at all. It’s a word that conveys no information (“with”), and “options”, which describes the first parameter. In Objective-C, there’s no such thing as parameter labels, it’s all one name, so “With” is used as a separator. But in Swift, making the first parameter’s label explicit just makes more sense.</div></div></div></blockquote><div class=""><br class=""></div><div class="">That’s an interesting thought! If “with” is truly used as a convention for separating the description of the operation from the description of the first parameter, that’s something that can be codified in the Clang importer. I was curious, so I hacked it up. Here’s a diff of the Cocoa APIs that shows what things would look like if we treated “with” as a separator:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><a href="https://github.com/apple/swift-3-api-guidelines-review/pull/5/files" class="">https://github.com/apple/swift-3-api-guidelines-review/pull/5/files</a></div><div class=""><br class=""></div><div class="">It’s a diff against SE-0005, and it introduces a significant number of first argument labels. Indeed, you’ll need to grab the patch to see them all:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><a href="https://github.com/apple/swift-3-api-guidelines-review/pull/5.patch" class="">https://github.com/apple/swift-3-api-guidelines-review/pull/5.patch</a></div><div class=""><br class=""></div><div class="">A brief survey shows that some cases seem to be lining up with the guideline proposals that have been under discussion. For example, the patch includes:</div><div class=""><br class=""></div><div class=""><div class="">- &nbsp;func fillWith(blendMode: CGBlendMode, alpha: CGFloat)</div><div class="">- &nbsp;func strokeWith(blendMode: CGBlendMode, alpha: CGFloat)</div><div class="">+ &nbsp;func fill(blendMode blendMode: CGBlendMode, alpha: CGFloat)</div><div class="">+ &nbsp;func stroke(blendMode blendMode: CGBlendMode, alpha: CGFloat)</div><div class=""><br class=""></div></div><div class=""><div class="">- &nbsp;func encodeWith(aCoder: Coder)</div><div class="">+ &nbsp;func encode(coder aCoder: Coder)</div><div class=""><br class=""></div><div class="">which you might recognize, because it’s the example you used:</div><div class=""><br class=""></div></div><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">And with that in mind, I object to these translations:</div><div class=""><br class=""></div><div class=""><div class="">&nbsp; &nbsp;func fillWith(_: CGBlendMode, alpha: CGFloat)</div><div class="">&nbsp; &nbsp;func strokeWith(_: CGBlendMode, alpha: CGFloat)</div><div class="">&nbsp; &nbsp;func encodeWith(_: Coder)</div></div><div class=""><br class=""></div><div class="">Even though these don’t have default values, I believe this version to be clearer and make more sense, even if slightly more verbose:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;func fill(blendMode: CGBlendMode, alpha: CGFloat)</div><div class="">&nbsp; &nbsp;func stroke(blendMode: CGBlendMode, alpha: CGFloat)</div><div class="">&nbsp; &nbsp;func encode(coder: Coder)</div></div></div></blockquote><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Another random interesting example I encountered:</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">- &nbsp;func addArcWithCenter(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)</div><div class="">+ &nbsp;func addArc(center center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)</div><div class=""><br class=""></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">which seems to match the idea behind Erica’s "semantic relationship between the parameters is stronger than their relation to the operation” (or Paul Cantrell’s similar notion of "the direct object is several args taken together”, which feels more in line with the way the API guidelines are written).</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">There’s also this:</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">- &nbsp;func tracksWithMediaType(mediaType: String) -&gt; [AVMovieTrack]</div><div class="">+ &nbsp;func tracks(mediaType mediaType: String) -&gt; [AVMovieTrack]</div><div class=""><br class=""></div><div class="">- &nbsp;func tracksWithMediaCharacteristic(mediaCharacteristic: String) -&gt;</div><div class="">+ &nbsp;func tracks(mediaCharacteristic mediaCharacteristic: String) -&gt; [AVMovieTrack]</div><div class=""><br class=""></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">which feels reminiscent of Paul’s “resource” example:</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="" style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(88, 126, 168);"><span class="" style="">&nbsp; &nbsp;&nbsp;</span>service<span class="" style="">.</span>resource<span class="" style="">(</span><span class="" style="color: rgb(132, 62, 100);">"/foo"</span><span class="" style="">)</span></div><div class="" style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(88, 126, 168);">service</span>.<span class="" style="color: rgb(88, 126, 168);">resource</span>(absoluteURL:&nbsp;<span class="" style="color: rgb(132, 62, 100);">"<a href="http://bar.com/" class="">http://bar.com</a>"</span>)</div><div class="" style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(88, 126, 168);">service</span>.<span class="" style="color: rgb(88, 126, 168);">resource</span>(absoluteURL:&nbsp;<span class="" style="color: rgb(88, 126, 168);">NSURL</span>(string:&nbsp;<span class="" style="color: rgb(132, 62, 100);">"<a href="http://bar.com/" class="">http://bar.com</a>"</span>))</div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">where (I think) the argument is that the various methods should all have the same base name because they’re all returning “tracks” or a “resource”, respectively.</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">There is a ton of data in that patch. I’d be interested to hear whether the resulting Cocoa APIs feel better in Swift—are they following the evolving set of guidelines for first argument labels that are under discussion, and are the resulting APIs clearer/more Swifty? What specific APIs work well and where does this “with-as-separator” heuristic break down?</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>- Doug</div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>