[swift-evolution] [Review] SE-0005 Better Translation of Objective-C APIs Into Swift

Austin Zheng austinzheng at gmail.com
Mon Feb 1 15:24:23 CST 2016


+1 to Nate's reasoning. I understand this might be quite controversial, and
I appreciate the work that's been done on Foundation, but I am wary about
canonicalizing a "standard library" that cannot fully embrace Swift
features and idioms as such, at least at this point in time. I understand
the desire to make open-source Foundation a standard for cross-platform
development, but this should not be at the expense of libraries which seek
to provide 'Swiftier' solutions to the same problems.

Best,
Austin

On Mon, Feb 1, 2016 at 1:10 PM, Nate Cook via swift-evolution <
swift-evolution at swift.org> wrote:

> This is a concurring opinion with Drew's review, agreeing that we should
> reconsider removing the "NS" prefix but providing my own reasons. The
> proposal as a whole is exciting and far-reaching, but this particular
> change is misguided. My objections are:
>
> *1) The change will elide the different semantic expectations for
> Foundation and Swift standard library types.*
>
> Prefix-less Foundation types will blur the different norms and
> expectations for Foundation types vs what we have in the Swift standard
> library, particularly in regards to value vs reference semantics of
> collection types.
>
> The Swift standard library defines Array, Set, and Dictionary as
> collection types with value semantics that operate quite differently from
> their peers in Foundation. This change will introduce OrderedSet,
> CountedSet, HashTable, MapTable, and others, all of which use reference
> semantics and therefore don't provide the same set of guarantees about
> ownership and immutability.
>
> As an example, the seemingly similar Set and CountedSet types produce
> different results from nearly identical code. Swift's Set type has value
> semantics, so changes to a copy don't affect the original Set instance:
>
> let simpleSet = Set(["one", "two", "three"])
> var copiedSimpleSet = simpleSet
> copiedSimpleSet.remove("one")
>
> copiedSimpleSet.contains("one")  // false
> simpleSet.contains("one")        // true
>
> CountedSet (née NSCountedSet), on the other hand, uses reference
> semantics, so changes to a copy of an instance. This is true whether the
> copy is an explicit one made via assignment or the implicit copy made when
> calling a function with CountedSet as a parameter. This example shows how
> nearly code nearly identical to the above produces very different results:
>
> let countedSet = CountedSet(array: ["one", "two", "three"])
> var copiedCountedSet = countedSet
> copiedCountedSet.remove("one")
>
> copiedCountedSet.contains("one") // false
> countedSet.contains("one")       // false!
>
> Collections constructed from immutable/mutable class clusters (like
> OrderedSet and MutableOrderedSet) pose the same problems, since you may be
> using a mutable instance of the "immutable" collection. We clearly are
> already dealing with this difference today, but eliminating the "NS" prefix
> implies that Foundation types are on the same level as the standard
> library. This makes the confusion more pronounced and significantly
> increases both the learning curve of the Swift & Foundation APIs and the
> risk of errors when using different collection types.
>
> *2) The change may stifle the development of more Swift-oriented APIs.*
>
> Foundation types were developed in and for a language that uses reference
> semantics and subclassing, rather than value semantics and a
> protocol-oriented approach. The designs therefore use and reinforce norms
> that relate better to Objective-C than to Swift—class clusters of
> non-final, immutable types with mutable subclasses, immutable types with
> separate but related mutable counterparts, etc.
>
> A Swift-native CountedSet (and other collections) would surely have value
> semantics built in. What about other types—do the new
> Calendar/Date/DateComponents types look like the system that we would
> design from the ground up in Swift? How about URL and URLComponents?
> Dropping the "NS" prefix would make it more difficult to gradually expand
> the standard library to encompass bridging versions of these and other
> common types.
>
> *3) The change will make it harder to find information about the revised
> APIs.*
>
> Excellent search-ability is an unintended benefit of the "NS" prefix, and
> can be understood as a way that these types avoid collisions in the vast
> namespace-less sea of Internet search results. Searching for help with URL
> and Calendar will be much more difficult than their NS'ed counterparts.
>
> Especially given the challenges that this proposal will pose for code
> sourced from tutorials, blog posts, Stack Overflow answers, etc., keeping
> at least the class names as sign posts seems valuable.
>
> *4) We'll still be using prefixes after the change.*
>
> While the removal of "NS" is far-reaching, prefixes will still be a common
> occurrence in code written in Swift. UIKit and AppKit, along with all the
> various frameworks, will still retain their prefixes, so removing prefixes
> in the case of Foundation types will be more the exception than the norm.
> As such, any benefit of the removal would be mitigated by the continued use
> of prefixes for the rest of the first-party types we rely on.
>
>
> In sum, the change would make the language and its APIs more confusing and
> more difficult to use today, would make it more difficult to migrate to
> modern designs in the future, and would ultimately provide a very minor
> benefit. I encourage the Swift core team to reconsider the "Strip the "NS"
> prefix from Foundation APIs" portion of the proposal.
>
> Nate
>
>
> On Jan 30, 2016, at 5:01 PM, Drew Crawford via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I am in favor of this proposal on balance, and I leave the bulk of this to
> people who interop with Objective-C more often than I do.
>
> I would like to confine my remarks to one corner where I think we are
> making a very serious mistake.
>
> The removal of the "NS" prefix for the Foundation module (or other
> specifically identified modules) is a mechanical translation for all global
> symbols defined within that module that can be performed in the Clang
> importer.
>
>
> As I understand it (and I am no Cocoa historian) the NS prefix was
> originally introduced because Objective-C lacks namespacing.
>
> The thinking seems to be that since Swift has proper namespacing, this
> historicism is no longer necessary.  I find this argument very flimsy.
>
> Of course Swift has stronger namespacing if one's frame of reference is
> Objective-C or C.  But for those of us coming from other language
> backgrounds, namespacing means something much stronger than Swift's concept
> of it.  I don't mean to suggest that Swift's design is wrong exactly (less
> is sometimes more), but I do mean to say that if we propose to undo a
> decision that worked for several decades and break every Swift project in
> existence on the theory that Swift's namespacing is strong enough we had
> better be right.
>
> For those unfamiliar, I will explain some of the namespacing tools Swift
> lacks relative to other languages.  First, many languages have a
> "hierarchical" namespace system, where one can say
>
> import Foundation.Net.URL
> let s = Session(...)
>
>
> instead of for example
>
> import Foundation
> let s = NSURLSession(...)
>
>
> Some form of this is used in Rust, Python, and C#, as far as I know.  I
> believe Swift has some counterfeit version of this, as the book mentions
> you can import a "submodule
> <https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/import-declaration>",
> but I do not know what that is, do not know how to make one, have never
> seen anyone use one, the book suggests it goes only 2 levels deep, and
> perhaps as a consequences of some of these problems nobody thought of using
> this for Foundation.
>
> A closely related difference is the use of so-called "selective" imports,
> where we import only a single symbol (or a list of explicitly-identified
> symbols) into the scope.  We might express this as
>
> from Foundation.Net.URL import Session, HTTP //import two classes only
> let s = Session(...)
>
>
> Again I think Swift technically supports some way to avoid importing a
> whole gigantic namespace like Foundation, but I am not aware of any actual
> uses of this feature, and certainly the convention is not to write code
> this way.  Meanwhile, let's check in with the Python community, who
> standardized the following guidance on these "wildcard" imports as part of
> their language evolution process:
>
> Wildcard imports ( from <module> import * ) should be avoided, as they
> make it unclear which names are present in the namespace, confusing both
> readers and many automated tools. There is one defensible use case for a
> wildcard import...
>
>
> When a language has a robust namespacing system, which we do not, there
> are many follow-on consequences.  One is that an import statement is much
> more of a scalpel than a bludgeon; each import statement only introduces a
> handful of new names (even if it is a so-called "wildcard" import that
> grabs all children of some namespace, most of those children are themselves
> namespaces), unlike importing Foundation which contains thousands of direct
> child types that are injected into the local scope.
>
> Another consequence is that class names become quite short, shadow each
> other, and nobody bats an eye.  I searched the C# standard library for
> "Session", and found some 12 classes with that name:
>
> <Screen Shot 2016-01-30 at 3.44.23 PM.png>
>
> These "standard library" classes not only potentially shadow
> programmer-defined types, *they also shadow each other*.  But because the
> C# language has a robust namespacing system, the chances of there being
> more than one thing called "Session" in scope in your program (or for that
> matter, when developing the standard library itself) is quite small, so
> it's a non-issue.
>
> Now we return to the question of dropping the NS prefix, which will rename
> thousands of classes in a typical program that has `import Foundation`, in
> a way that potentially (let's be honest.  More like "probably") shadows one
> or more programmer-defined classes.  Our review criteria is:
>
> Is the problem being addressed significant enough to warrant a change to
> Swift?
>
>
> No, the elimination of 2 characters is not significant enough of a problem
> to break all Swift programs, let alone to introduce literally thousands of
> new opportunities for shadowing.
>
> To its credit, the proposal acknowledges this, and offers a concession:
>
> Note that this removal can create conflicts with the standard library. For
> example, NSString and NSArray will become String and Array, respectively,
> and Foundation's versions will shadow the standard library's versions.  In
> cases where the Swift 3 names of standard library entities conflict with
> prefix-stripped Foundation entities, we retain the NS prefix. These
> Foundation entities are: NSArray, NSDictionary, NSInteger, NSRange, NSSet,
> and NSString.
>
>
> But of course this needlessly draws a distinction between NSString et al
> and the "normal" Foundation types, and what's more it draws that
> distinction based on the present composition of the Swift standard library
> and the present composition of Foundation.  But we have already decided not
> to guarantee the source compatibility of the standard library, so what
> happens when that composition changes?  Will we then go back and tweak
> which classes get NS prefixed to them again?
>
> In my view, if Swift's namespacing is not good enough to let us drop the
> NS in NSString it is not good enough to drop any prefix.  If we believe
> that a programmer will struggle to distinguish between Swift String and
> Foundation String then we should expect them to struggle for any two
> classes in any two frameworks, and this is special pleading on the part of
> Foundation.  C#'s libraries declare **twelve** different `Session`s and
> nobody bats an eye, but we have two types share a name and everybody loses
> their minds?  Our namespacing is not good enough to kill the prefix, period.
>
> We should either drop these prefixes or we should not; because the claimed
> motivation–that we have "good enough" namespacing in the language now–is
> either true or it is not.  This proposal admits that it is not, and tries
> to drop the prefixes anyway.  I believe that is a mistake.
>
> I certainly support the goal of eliminating these prefixes, they are ugly,
> they need to be killed, and namespacing is the right solution.  But we must
> not jump out of the plane until we are very sure our parachute is in
> order.  In Swift 3 it is not.
>
> I do think the bulk of the proposal is fine, and I apologize for using
> quite stark language for such a small paragraph in an otherwise reasonable
> proposal, but I think the problem buried in here is quite serious and is
> being overlooked.
>
> Drew
>
>
> On Jan 22, 2016, at 3:02 PM, Douglas Gregor via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Hello Swift community,
>
> The review of SE-0005"Better Translation of Objective-C APIs Into Swift"
> begins now and runs through January 31, 2016. The proposal is available
> here:
>
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md
>
> Reviews are an important part of the Swift evolution process. All reviews
> should be sent to the swift-evolution mailing list at
>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> or, if you would like to keep your feedback private, directly to the
> review manager. When replying, please try to keep the proposal link at the
> top of the message:
>
> Proposal link:
>
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md
>
> Reply text
>
> Other replies
>
> <https://github.com/apple/swift-evolution#what-goes-into-a-review-1>What
> goes into a review?
>
> The goal of the review process is to improve the proposal under review
> through constructive criticism and, eventually, determine the direction of
> Swift. When writing your review, here are some questions you might want to
> answer in your review:
>
>    - What is your evaluation of the proposal?
>    - Is the problem being addressed significant enough to warrant a
>    change to Swift?
>    - Does this proposal fit well with the feel and direction of Swift?
>    - If you have used other languages or libraries with a similar
>    feature, how do you feel that this proposal compares to those?
>    - How much effort did you put into your review? A glance, a quick
>    reading, or an in-depth study?
>
> More information about the Swift evolution process is available at
>
> https://github.com/apple/swift-evolution/blob/master/process.md
>
> Thank you,
>
> -Doug Gregor
>
> Review Manager
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160201/be359707/attachment.html>


More information about the swift-evolution mailing list