<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 3, 2016, at 2:42 PM, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class="">on Tue Feb 02 2016, David Owens II <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""><blockquote type="cite" class="">Awesome for putting this together. I think the rules add some needed<br class="">clarity, but they have the bias that the first argument *should* have<br class="">a defaulted empty parameter label. <br class=""></blockquote><br class="">I disagree with this as a premise. IMO they don't have any such bias.<br class="">The guideline says, only under these very specific conditions does one<br class="">omit an argument label. That would indicate, if anything, a bias<br class="">towards *having* a label.<br class=""></div></div></blockquote><div><br class=""></div><div>In one respect, I agree that the guidelines are written with the intention to be more open on the existence of the first argument label. However, when you apply the guidelines, the “very specific conditions” seem to qualify the vast majority of cases. </div><div><br class=""></div><div>Plus, there is this:</div><div><br class=""></div><div><blockquote type="cite" class=""><div>For better or worse, it is a requirement that Cocoa as imported very<br class="">closely approximates full conformance to the guidelines we choose. We<br class="">are shooting for consistency across APIs used in swift.</div></blockquote><br class=""></div><div>And all of the following conversations around it. This is why I say there seems to be a bias towards APIs with not having an argument label.</div><div><br class=""></div><div>All that being sad said, my post was really about two things:</div><div><br class=""></div><div> 1. clarifying the usage of labels in more than just the first parameter's slot while also simplifying the rule landscape, and</div><div> 2. debating rule #2, which really seems about naming APIs, not really about argument label usage</div><div><br class=""></div><div>I think my critique is still valid, but I'll focus it directly on when the label should be present and leave the debate for rule #2 elsewhere. I think the two are orthogonal issues, and sometimes the “better choice" is really subjective to the APIs being built. However, whether the argument label should exist is actually a much more straight forward issue to address.</div><div><br class=""></div><div>The stated goals of the proposal were these:</div><div><br class=""></div><div></div><blockquote type="cite" class=""><div>* describe when and where to use argument labels</div></blockquote><blockquote type="cite" class=""><div>* require labels in many of the cases people have asked for them<br class="">* are understandable by humans<br class="">* preserve important semantics communicated by existing APIs.</div></blockquote><div><br class=""></div><div>I think the proposal falls short of the first point: the proposal really only addresses the first argument. There are cases when the other arguments should not be present as well.</div><div><br class=""></div><div>If we start with the premise that all parameters should be labeled, then we can have a set of exclusionary rules to help guide the process. I start here because I believe it’s easier to state the cases on when to remove the labels instead of trying to provide rules for both sides.</div><div><br class=""></div><div>The rules:</div><div><br class=""></div><div><i class="">The purpose of an argument label is to provide clear context of the argument’s role within the function. </i></div><div><i class=""><br class=""></i></div><div><i class="">No argument labels are necessary when:</i></div><div><i class=""><br class=""></i></div><div><i class=""> 1. The parameters have a unambiguous meaning with the intent of the function</i></div><div><i class=""> 2. The label would simply be repeating information that is already explicitly or implicitly derived from the function’s name regarding it’s intent</i></div><div><i class=""><br class=""></i></div><div><br class=""></div><div>Here are then the examples of good use cases:</div><div><br class=""></div><div><div class=""><b class="">No First Argument Labels</b></div><div class=""><b class=""><br class=""></b></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Menlo" class="">a.contains(b) // yes, satisfies rules 1 and 2</font></div><div class=""><font face="Menlo" class="">a.contains(object: b) // no, object is adds no value: it’s implicitly there</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><span style="font-family: Menlo;" class="">a.merging(b) // yes, satisfies rules 1 and 2</span></div><div class=""><font face="Menlo" class="">a.merging(items: b) // no, items adds no value: it’s implicitly there</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><span style="font-family: Menlo;" class="">a.readFrom(u, ofType: b) // yes, satisfies rules 1 and 2</span></div><div class=""><font face="Menlo" class="">a.readFrom(source: u, ofType: b) // no, source is explicitly derived by “From”</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">a.addObserver(o) // yes, o has a clear role</font></div><div class=""><font face="Menlo" class="">a.addObserver(observer: o) // no, duplicating info </font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">a.tracksHavingMediaType("Wax Cylinder") // yes, the first param’s role is clear</font><br style="font-family: Menlo;" class=""><font face="Menlo" class="">a.tracksHavingMediaType(mediaType: </font><span style="font-family: Menlo;" class="">"Wax Cylinder"</span><font face="Menlo" class="">) // no, duplicating info</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div></blockquote><b class="">Keep First Argument Labels Labels</b><br class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><br class=""></div><div class=""><font face="Menlo" class="">a.dismiss(b) // no, this seems to be dismissing b</font></div><div class=""><font face="Menlo" class="">a.dismiss(animated: b) // yes, intent is to dismiss; b is a modifier on how to animate.</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">a.read(u, ofType: b) // no, it’s not clear what u’s role is</font></div><div class=""><span class="" style="font-family: Menlo;">a.read(source: u, ofType: b) // yes, the source being read is not clear, it could be stdin,</span></div><div class=""><span class="" style="font-family: Menlo;"> // or it could be reading from a, etc…</span></div><div class=""><span class="" style="font-family: Menlo;"><br class=""></span></div><div class=""><span class=""><font face="Menlo" class="">a.tracksHaving("Wax Cylinder") // no, the param’s role is not clear<br class=""></font><span style="font-family: Menlo;" class="">a.tracksHaving(mediaType: "Wax Cylinder") // yes, provides clear context for the param</span><br style="font-family: Menlo;" class=""></span></div><div class=""><span class=""><span style="font-family: Menlo;" class=""><br class=""></span></span></div></blockquote></div><div><b class="">Ambiguous Argument Labels - Really up to the API surface</b><br class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"></blockquote></div><div><div class=""><font face="Menlo" class=""><br class=""></font></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div><div class=""><span class="" style="font-family: Menlo;">a.moveTo(x: 300, y: 400) // it may not be clear that (x,y) is the movement plane</span></div></div></div><div><div><div class=""><font face="Menlo" class="">a.moveTo(300, 400) // a may provide explicit context for a 2D plane or coordinates</font></div></div></div></blockquote><div><div><br class=""></div><div>The non-labeled `moveTo` example is also an illustration of why `max` would have no labels:</div><div><div class=""><br class=""></div><div class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class="">max(x, y) // yes, x's and y’s role is unambiguous</font></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class="">max(a: x, b: y) // no, there is a clear role for each argument</font></blockquote></div></div><div><br class=""></div><div>I think this ruleset is clearer and provides guidance for the various choices that are before us with your rule #2. I also think that arguments on how to name an API like “tracksHavingMediaType” are better left elsewhere. These guidelines still help you decide on the argument placement though regardless of which API works best for your purposes.</div><div><br class=""></div><div>-David</div></div></body></html>