<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="">I agree with some of your points and disagree with others. You are right that Swift did not get everything right when it “Swiftified” some Objective-C names. However, I don’t think your criticisms are all correct.<div class=""><br class=""></div><div class="">At some point, Swift decided to omit needless “helpful” names from method names. This is a good thing. You don’t “string-capitalize” a string; you capitalize it. And since types are known at compile time, there isn’t really a need to name the type of every argument. This would hurt the readability/Englishness of Swift. For instance, `append(contentsOf:)` — in English, you would say “append the contents of that bucket to my array”, not “append the contents of collection that bucket to my array”. Only collections can have contents so you can omit that type, both in English and in Swift. In short, when the argument label clearly implies the type of the argument, there’s no need to explicitly state it. However when that type is not clear then it should be specified.</div><div class=""><br class=""></div><div class="">I think Swift did move in a weird direction with method base-names, as shown in some of your examples. It relies too heavily on a shared verb among methods with argument labels serving as the primary differentiators, when sometimes part of the label should be attached to the verb. And for arguments, it relies too heavily on type information to understand the functionality; somewhat-hidden type information (inspectable in Xcode, but not very obvious if you’re just reading quickly) should be made visible in the argument labels where necessary.</div><div class=""><br class=""></div><div class="">To your specific examples:</div><div class=""><br class=""></div><div class=""><ol class="MailOutline"><li class="">`fetch(withRecordID)` leaves unanswered the question “what is being fetched?”, instead forcing you to infer the answer from the question “how is the thing being fetched, being fetched?” — “it is being fetched by record ID so I guess it must be a record”. Is there even such a thing as a record ID? I think not — there are just IDs, some of which are tied to records. I think that that method should be called `fetchRecord(withID:)`. This makes it clear that a) a record is being fetched and b) its ID is what is used to fetch it.</li><li class="">`string.capitalized(with:)` it very unclear. As an uneducated programmer, I have no idea what you capitalize a string “with”. With a font? With some Unicode machinery? With gusto? (Ok that last one was a joke.) It’s not at all obvious that you capitalize a string with a locale, and hence I think that that method should be called `string.capitalized(withLocale:)`. I explain above why it should be string.capitalized and not string.stringCapitalized.</li><li class="">`dict.remove(at:)` is a bit of a tougher case. It is mutating, so it has to be in the present tense. Yet it does return an element, so maybe it should state that? I think the deciding vote is that it’s @discardableResult, which means it should be treated as primarily removing the element; returning it is secondary. Maybe to indicate the returning of the element, it should be called `dict.pop(at:)`. “Pop" implies the element popped, and probably implies @discardableResult in most programmers’ minds as well.</li><li class="">`date.timeInterval` is another tricky one. IMO the most natural choice is `date.timeIntervalSince(_:)`. I don’t think the date argument label is necessary because given a date, you can only compute a time interval since… another date. See the `array.append(contentsOf:)` example above. And although `since` is a preposition, it should be part of the method name, and not an argument label, because dates do not just “have” time intervals. A database can fetch a record, but a date does not have a time interval — it has a time interval since (another date).</li><li class="">This should definitely be `forEach`. `array.each` would be another name for `array.everyElementSatisfiesCondition(_ f: (Element)-&gt;Bool))`. “For each” specifies that you will do something *for each* element as opposed to asking a question about each element. In English, “for each thing in my bucket…” will probably be followed by “do this thing”. You could say “for each thing in my bucket, it’s true that…” but you’d probably just say “everything in my bucket is…"</li></ol><div class=""><br class=""></div><div class="">So, if I had to come up with my own rules for naming conventions:</div><div class=""><br class=""></div><div class=""><ol class="MailOutline"><li class="">Methods should first state what they do, then how they do it. You fetch a record using an ID; you don’t fetch a thing using a record ID. Ask the question “does the calling variable have such-and-such a thing” or “can the calling variable do such-and-such a thing”, and be specific about exactly what the thing is. If yes, than that thing is a good candidate for a method name. A database can fetch, sure, but more specifically it can fetch records, and that’s about as specific as you can get. A date doesn’t have a collection of time intervals sitting around, but it can compute the *time interval since* another date. Strings can be capitalized (with a locale), dictionaries can remove (at an index), arrays can append (the contents of some collection).</li><li class="">When the preposition/argument label makes it clear what sort of argument it takes, then it’s fine to omit the type. However if the argument label is vague, then the argument type should be included. In this case the type is not just a type specifier — it’s really part of the English description. You don’t say “append the contents of collection that bucket to my array”, but any sentence about capitalizing a string with a locale would use the word “locale” explicitly, either in the name of the variable or otherwise — “capitalize that string with your specified locale”, “capitalize that string with locale XYZ”, etc. The English language doesn’t really have the notion of implicitly locale-like objects the way it has implicitly collection-like objects such as buckets, bags, etc, so the fact that a locale is being used should be explicit while the fact that a collection is being used may be implicit.<br class="">As an aside, I feel that “using Locale” would be better than “with Locale”, but that’s a conversation for another time.</li><li class="">Three nouns may be required in a name, as in the fetch record example. The calling variable is always the subject, and there may be either one or two objects in play. If there are two, then one should go in the method name; the other may or may not be made explicit in the argument label, depending on clarity (see the above point). When a database fetches a record using its ID, you have only two choices: db.fetchRecord(with:) or db.fetchRecord(withID:). In this case, clarity would lead to the second choice, as you don’t know what you’re fetching the record *with*. In the date example, the calling date is the subject, and it is *producing a time interval since* another date. So again, two choices: date.timeIntervalSince(date:) or date.timeIntervalSince(_:). Since you can only find the time interval between two dates, `date:` can be omitted.</li><div class=""><br class=""></div></ol><div class="">It’s hard to make hard-and-fast rules around this because language is far from hard-and-fast itself. But I think these would be good guidelines.</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 2, 2017, at 11:44 AM, Jon Gilbert 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=""><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=""><span style="font-family: HelveticaNeue;" class="">When Swift 3 launched, it introduced a new concept of placing the preposition inside the parentheses. (See discussion here:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160208/009523.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160208/009523.html</a>).&nbsp;</span><br class=""><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">I'm fine with that, however this change got implemented in an inconsistent manner, making Swift and its APIs more vague, thereby decreasing code clarity.&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">I was hoping to see these inconsistencies get cleared up with Swift 4, however they were not. I realized that perhaps I could have spoken up and taken more of an active role in Swift Evolution. So... better late than never. Here are my thoughts, towards consistency and disambiguation in Swift.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Disclaimer: I’m sure the last thing anyone wants are more changes to the APIs. However, I also don't think these inconsistencies should be left in place forever. I have tried to go back and read through as much of the relevant discussions on list as I could, and it seems like&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Please let me some give examples below. After that is some discussion and a proposal.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><b class=""><u class="">EXAMPLES</u></b></div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Take for example the preposition "with." A preposition is meaningless without a subject and an object. Look at the following three sentences:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">&nbsp;(A) "A boy with the dog Molly walked across the street."</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">&nbsp;(B) "With the dog Molly walked across the street."</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">&nbsp;(C) "A boy with Molly walked across the street."</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Sentence (A) is longest, but it makes perfect sense.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Sentence (B) is nonsensical and grammatically incorrect because while the word "with" takes two arguments, only one is present. If there was a comma after "dog," then it would make sense; "With the dog, Molly walked across the street" is fine. But if we were to assume that Molly is not the dog, in this case, we'd actually be wrong.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Sentence (C), while grammatically correct, leaves it unclear whether Molly is a dog, a girl, or… something else. &nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">The reason for this is, whenever a preposition is used in English, it almost always takes a dyadic form, relating a subject to the preposition's object. The two most common dyadic formats are:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><b class="">&lt;subject&gt; [&lt;preposition&gt; &lt;object of preposition&gt;]</b></div><div style="font-family: HelveticaNeue;" class="">&lt;The boy&gt; [&lt;with&gt; &lt;the dog&gt;] crossed the street.&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><b class="">[&lt;preposition&gt; &lt;</b><b class="">&nbsp;object of preposition</b><b class="">&gt;] &lt;subject&gt;</b></div><div style="font-family: HelveticaNeue;" class="">[&lt;In&gt; &lt;space&gt;], &lt;no one&gt; can hear you scream.</div><div style="font-family: HelveticaNeue;" class="">[&lt;On&gt; &lt;the Moon&gt;] are &lt;many craters&gt;.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Now, in Objective C through Swift 1 and 2, prepositions' dyadic nature were generally respected in method signatures. However, Swift 3's migration of the preposition inside the parentheses also seems to have been accompanied by the stripping away of either the subject, the prepositional object, or both—according to no discernible pattern. For example:&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">(1) CloudKit:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><blockquote style="font-family: HelveticaNeue; margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">old:&nbsp;myCKDatabase.fetchRecordWithID(recordID)</div><div class="">new: myCKDatabase.fetch(withRecordID: recordID)</div><div class=""><b class="">(subject "Record" got removed)</b></div></blockquote><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">(2) String:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><blockquote style="font-family: HelveticaNeue; margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">old: myString.capitalizedStringWithLocale(_: myLocale)</div><div class="">new: myString.capitalized(with: myLocale)</div><div class=""><b class="">(subject "String" and prep. object "Locale" both got removed)</b></div></blockquote><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">(3) Dictionary:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><blockquote style="font-family: HelveticaNeue; margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">old: myDict.removeAtIndex(myIndex)</div><div class="">new: myDict.remove(at: myIndex)</div><div class=""><b class="">(subject "element" already missing from both; prep. object "Index" got removed)</b></div></blockquote><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">(4) Date:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><blockquote style="font-family: HelveticaNeue; margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">old: myDate.timeIntervalSinceDate(myDate)</div><div class="">new: myDate.timeIntervalSince(date: myDate)</div><div class=""><b class="">(subject "timeInterval" and object "Date" both still present; but oddly, preposition "since" got left outside of the parentheses)</b></div><div class=""><br class=""></div></blockquote><font face="HelveticaNeue" class="">(5) Array:</font><div class=""><font face="HelveticaNeue" class=""><br class=""></font></div><div class=""><font face="HelveticaNeue" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>&nbsp; &nbsp; old: myArray.forEach({ thing in code})</font></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="HelveticaNeue" class="">new: myArray.forEach() { thing in //code }</font></div></blockquote><div class=""><font face="HelveticaNeue" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b class="">(preposition&nbsp;“for”&nbsp;is outside of the parentheses)</b><br class=""></font><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><b class=""><u class="">DISCUSSION OF EXAMPLES</u></b></div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">These four changes are inconsistent with each other regarding whether the subject, prepositional object, or both were removed, and we don't even have consistency as to whether the preposition got moved inside the parentheses (see A below).&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">As well, these changes generally removed the dyadic arguments to the preposition, which removes cues necessary to disambiguate the prepositional relationship, decreasing code readability (see B below).</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><u class="">(A) Inconsistency</u></div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">The inconsistency between the examples is shown in the bold text of each example, but lets go over why this matters. It matters because any language is easier to learn the more consistently it sticks to its own rules. Autocomplete is our great savior, but still, if we were being consistent, then the new method signatures would have been:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">(1) myCKDatabase.fetchRecord(withRecordID:)</div><div style="font-family: HelveticaNeue;" class="">(2) myString.stringCapitalized(withLocale:)</div><div style="font-family: HelveticaNeue;" class="">(3) myDictionary.elementRemoved(atIndex:)</div><div style="font-family: HelveticaNeue;" class="">(4) myDate.timeInterval(sinceDate:)</div><div style="font-family: HelveticaNeue;" class="">(5) myArray.each(inClosure: ) &nbsp;&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Side note: for plain English readability, we might prefer elementRemoved(fromIndex:) and stringCapitlized(accordingToLocale:).&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Although I do understand removing "string" from the latter was to reduce redundancy in function/method declarations, we only make one declaration, yet we make many calls. So increasing ambiguity in calls does not seem like a good trade-off for decreased boilerplate in declarations. More often than not it's calls that we're reading, not the declarations—unless of course the call was ambiguous and we had to read the declaration to make sense out of it. So perhaps we might question if increased ambiguity is an overall good thing.&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Side note: example (5), .forEach, does seem like a very exceptional case, and possibly a sacred cow. See the Proposal section for further discussion of this.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><u class="">(B) Increased Ambiguity</u></div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">In all of these changes, one of or both parts of the dyadic arguments of the preposition have been excised from the method signatures. This increases ambiguity in Swift 3/4 vs. Objective C and Swift 2, especially in closures, as I will explain below.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">In example (1), the old method argument makes grammatical sense because "record with RecordID" follows the format,&nbsp;<b class="">&lt;subject&gt; [&lt;preposition&gt; &lt;object of preposition&gt;]</b>, just like "boy with dog tag" or "cow with black spots." This improves code readability, because when you read this, you know that this function will give you a record matching a particular recordID. However in Swift 3, we have the equivalent of, "with a recordID"—i.e. is *implied* that the thing being fetched is a record.&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">This isn't a problem you're reading the method signature in the header, and it's not a problem when you're writing the code, because you'll get warnings and errors if you try to assign to the wrong type.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">However this removal of explicit contextual cues from the method signature harms readability, since now, the compiler will let people write code like:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">{ return $0.fetch(withRecordID:$1) }</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Clearly, the onus is now on the developer not to use cryptic, short variable names or NO variable names. However, spend much time on GitHub or in CocoaPods and you will see an increasing number of codebases where that's exactly what they do, especially in closures.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Another problem is that the compiler doesn't care if you write:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">{ ambiguousName in</div><div style="font-family: HelveticaNeue;" class="">let myRecordID =&nbsp;ambiguousName.fetch(withRecordID:myID)&nbsp;</div><div style="font-family: HelveticaNeue;" class="">return myRecordID }</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">This is highly problematic because someone reading this code will have no reason to expect the type of "myRecordID" not to be CKRecordID. (In fact, it's CKRecord.) There is also no way to clarify what ambiguousName is since closures don't have argument labels at all... but that's another problem altogether.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Turning now to example (2), "myString.capitalized(with:myLocale)" sacrifices BOTH the subject and the prepositional object. We have now lost any enforced contextual cues, fully orphaning "with", allowing and even encouraging a final closure argument like:&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">{ return $0.capitalized(with: .current)) }</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">What is $0? Reading this, and being familiar with Swift, you will likely assume it's a string, but will you remember that .current is a Locale? The compiler knows, but why was it a good idea to strip out that information?&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">We also have examples like:&nbsp;</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">{ return $0.draw(with:$1) }</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">What is $0? What is $1? This is a real Apple API, BTW.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">We could also have:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">{array, key in&nbsp;</div><div style="font-family: HelveticaNeue;" class="">let number = array.remove(at:key)</div><div style="font-family: HelveticaNeue;" class="">return number }</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">This will compile and run even though number will be a tuple key-value pair, array will be a dict, and key will be an index type! This may seem like a ridiculous example, but I have literally seen things like this.</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><b class=""><u class="">DISCUSSION</u></b></div><div style="font-family: HelveticaNeue;" class=""><div class=""><br class=""></div><div class="">Making computer code more like natural language and thus more approachable to non-computer-science types was clearly one of the primary goals of Apple's method names in Objective C.&nbsp;</div><div class=""><br class=""></div><div class="">I've been a fan of the general direction in which Swift has taken things, but I'm starting to see code that is quite unreadable as a result of the stripping away of useful information from code, as if more white space will improve our ability to make sense out of our arcane invocations.</div><div class=""><br class=""></div><div class="">The point of code readability is for humans to be able to read and understand code with minimal extra effort. Explicit information is important because humans would like to read code without having to dig through five different headers and read lots of documentation files. This directly increases costs, because when a new developer comes onto a project, the longer it takes them to understand the codebase, the more it will cost the company.</div><div class=""><br class=""></div><div class="">I don't believe the intent with these changes was to increase ambiguity; at WWDC '16 we were told it was to increase clarity. I'm just not sure that's the consistent effect we actually received.&nbsp;</div><div class=""><br class=""></div><div class="">What we got instead is more times we will need to CMD-click things in XCode to get a clue. That's especially annoying because you're at XCode's mercy as to whether it actually wants to jump to a given declaration or not. This seems pretty hit or miss in my experience, even within a basic playground page, and is especially troublesome with jumping to declarations within CocoaPods. Selecting some code to get documentation in the side panel seems equally unreliable.&nbsp;</div><div class=""><br class=""></div><div class="">Perhaps CMD-click problems have to do with a project setting, but is there really a time when you would ever NOT want to have these capabilities? Why is it tied into a setting? Further, when you're reading through a repo on GitHub itself, you don't have CMD-click capability; you want the code to be as clear as possible, without lots of ambiguity.</div><div class=""><br class=""></div><div class=""><u class="">From Ambiguous to Cryptic</u></div><div class=""><br class=""></div><div class="">Orphaning method signatures by stripping useful return type and argument type information wouldn't be so bad if variables were all named descriptively, but that is a strangely optimistic hope for a language that's as paranoid about safety that it was specifically designed to prevent many categories of common mistakes.</div><div class=""><br class=""></div><div class="">The increased ambiguity in Swift from the removal of prepositional components has been further compounded by other forms of ambiguity that are increasingly everywhere in Swift, and which developers have taken copious advantage of to the point of abuse. Examples are:</div><div class=""><br class=""></div><div class="">-&nbsp;arguments labelled as "_" reduce code clarity</div><div class="">-&nbsp;calls to&nbsp;functions that take closures as the final argument can leave the final argument label out, decreasing readability</div><div class="">-&nbsp;closures have lack explicit type information, leaving it up to variable names to let us know what's going on; however, the use $# syntax and/or cryptically named variables often leaves it totally ambiguous</div><div class="">-&nbsp;generic types in method signatures using a single letter give no clue as to the type's purpose</div><div class="">- function types can't have argument labels, which might give a sense of context or informative cues, even if they added boilerplate&nbsp;</div><div class="">-&nbsp;inferred nested type parents (like the ability to do .current instead of being forced to do Location.current)</div><div class=""><br class=""></div><div class=""><u class="">Why is removing context and clue good?</u></div><div class=""><br class=""></div><div class="">Is it possible that this was an overreaction to the perceived over-verbosity of Objective C? I'm honestly curious. I will try to read back through the archives, but perhaps someone can give me a good summary.</div><div class=""><br class=""></div><div class=""><div class="">In the old Objective C style, method names could be quite long, but I never felt a lack of context that made code unclear. The method signatures were basically like sentences without spaces, and they seemed to follow pretty reliable rules. So reading them actually made grammatical sense, improving code readability. I could always tell what a call was doing.</div><div class=""><br class=""></div><div class="">While I won't deny that Objective C went overboard sometimes in verbosity, and while few would dispute that we should clean up its style, could it be we are going too far making Swift encourage code that's ambiguous to everyone except the compiler? Could it be a mistake for Swift to err so far on the side of inferring everything and stripping away contextual information?</div><div class=""><br class=""></div><div class="">A first-time reader of some unseen code is not going to be able to infer things like the original programmer or the compiler can. This increases the possibility of bugs (and exploits) sneaking in "under the radar."</div><div class=""><br class=""></div><div class=""><b class=""><u class="">PROPOSAL</u></b></div><div class=""><b class=""><u class=""><br class=""></u></b></div><div class="">To add more clarity back to Swift, I'd propose the following rules be applied consistently across the language:</div><div class=""><br class=""></div><div class="">• Every time a preposition shows up in a function/method signature, there is an explicit subject and object of the preposition, except in the following exceptions.</div><div class=""><br class=""></div><div class="">• The subject of a preposition can be left out if the function/method is mutating AND doesn't return a value, such as Array's .append(contentsOf:) method. This method would become: .append(contentsOfCollection:) so that it's clear what we're doing here, even within a closure.</div><div class=""><br class=""></div><div class="">•&nbsp;No preposition should be used when it would add no extra meaning between what’s inside and outside the parentheses. For example, userFont(ofSize fontSize:) should just be userFont(size: fontSize), because “of” is completely superfluous here. AVFragmentedMovie’s track(withTrackID:) could just as easily be track(forTrackID:) or track(TrackID:) which tells us that the preposition is superfluous and so why not just have it be track(id:).&nbsp;</div><div class=""><br class=""></div><div class="">• If the preposition goes with a verb in the method signature, the verb should be the last thing before the opening parenthesis (e.g. String's .capitalized function would now look like name.stringCapitalized(accordingToLocale: .current)... no pun intended).</div><div class=""><br class=""></div><div class="">• In the case of .forEach, since it’s almost identical in function to .map, perhaps a solution could be to eliminate .forEach entirely, and simply say that anytime .map’s result is unused (or assigned to _), then the compiler will automatically use .forEach functionality to optimize performance. For example if in Swift 5 you did _ = myArray.map() { print($0) }, this would be the same as doing myArray.forEach() { print($0) } currently. As well, _ = could be inferred.&nbsp;</div><div class=""><br class=""></div><div class="">Note: part of the problem is obviously that parameter names are never used in function calls when there is an argument label, but often, the argument label is now just a preposition, while its prepositional object is the (now hidden) parameter name. Perhaps we can think of a novel solution to this?</div><div class=""><br class=""></div><div class="">I'm interested to know what people think about this. Perhaps there are other ideas or ways to add clarity back in. Thanks for reading this long message.&nbsp;</div></div><div class=""><br class=""></div><div class="">Jon</div></div></div></div>_______________________________________________<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></blockquote></div><br class=""></div></div></body></html>