+1 to the concerns voiced by Doug, Matthew and others. I , too, would prefer a generator which generates a statically typed bridge instead of the dynamic lookup ature proposed which effectively undermines Swift's static type system.
-Thorsten > Am 30.11.2017 um 15:15 schrieb Matthew Johnson via swift-evolution > <swift-evolution@swift.org>: > > > > Sent from my iPad > >> On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> >> >>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution >>> <swift-evolution@swift.org> wrote: >>> >>> I’d like to formally propose the inclusion of user-defined dynamic member >>> lookup types. >>> >>> Here is my latest draft of the proposal: >>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 >>> https://github.com/apple/swift-evolution/pull/768 >>> >>> An implementation of this design is available here: >>> https://github.com/apple/swift/pull/13076 >>> >>> The implementation is straight-forward and (IMO) non-invasive in the >>> compiler. >> >> >> I think better interoperability with Python (and other OO languages in >> widespread use) is a good goal, and I agree that the implementation of the >> feature described is straight-forward and not terribly invasive in the >> compiler. >> >> However, I do not think this proposal is going in the right direction for >> Swift. I have objections on several different grounds. > > +1 to everything Doug says here. He articulates the concerns I tried to > voice in an earlier thread more clearly and more thoroughly. > > This design introduces a significant hole in the type system which is > contrary to the spirit of Swift. It doesn’t just make dynamic language > interop easy, it also changes the semantics of any type which conforms to > DynamicMemberLookupProtocol. That is not something that is locally visible > when looking at a piece of code. Worse, it does so in a way that trivial > mistakes such as a typo can turn into runtime errors. Worst of all, as Doug > points out it is possible to use retroactive conformance to change the > semantics of vast quantities of widely used types in one fell swoop. > > One additional concern that I don’t believe has been mentioned is that of > evolution. When a library is imported from a dynamic language and the > library makes breaking changes Swift code written using this feature will > break without notice until a runtime error occurs. Is that acceptable? That > may be what users of dynamic languages are accustomed to but can we do better > in Swift? If we can make the process of upgrading dependencies less a less > harrowing experience perhaps that could be a major selling point in moving > them to Swift. But we won’t accomplish that with this design. > > Interop with dynamic languages is a worthy goal, but we should do it in a way > that has no potential impact on code that does not need the feature. A > semantic variant of “don’t pay for what you don’t use” should apply here. If > we add this feature everyone will pay for it every time they read unfamiliar > Swift code. They will have to contend with the potential for conformances to > this protocol, even on standard library types. That feels like a pretty high > cost to me, especially for programmers who aren’t using the dynamic language > interop features themselves. > > Further, a consistent theme has been the desire to avoid things like compiler > flags that could fragment the community. I fear this feature has the > potential to do that, especially if it is really successful at attracting > people from the dynamic language community. I think we should consider > carefully the following questions: > > * Do we want to encourage these programmers to continue writing code in an > extremely dynamic style when they come to Swift or do we want to encourage > them to embrace the advantages of relying on the type system? > * If we want them to embrace the type system but that would keep them away > from Swift how do we feel about that? > > Matthew > >> >> Philosophy >> Swift is, unabashedly, a strong statically-typed language. We don’t allow >> implicit down casting, we require “as?” so you have to cope with the >> possibility of failure (or use “as!” and think hard about the “!”). Even the >> gaping hole that is AnyObject dispatch still requires the existence of an >> @objc declaration and produces an optional lookup result, so the user must >> contend with the potential for dynamic failure. Whenever we discuss adding >> more dynamic features to Swift, there’s a strong focus on maintaining that >> strong static type system. >> >> IMO, this proposal is a significant departure from the fundamental character >> of Swift, because it allows access to possibly-nonexistent members (as well >> as calls with incorrect arguments, in the related proposal) without any >> indication that the operation might fail. It’s easy to fall through these >> cracks for any type that supports DynamicMemberLookupProtocol—a >> single-character typo when using a DynamicMemberLookupProtocol-capable type >> means you’ve fallen out of the safety that Swift provides. I think that’s a >> poor experience for the Python interoperability case, but more on that in >> the Tooling section below. >> >> While we shouldn’t necessarily avoid a feature simply because it can be used >> distastefully, consider something like this: >> >> public extension NSObject : DynamicMemberLookupProtocol, >> DynamicCallableProtocol { … } >> >> that goes directly to the Objective-C runtime to resolve member lookups and >> calls—avoiding @objc, bridging headers, and so on. It’s almost frighteningly >> convenient, and one could imagine some mixed Objective-C/Swift code bases >> where this would save a lot of typing (of code)… at the cost of losing >> static typing in the language. The presence of that one extension means I >> can no longer rely on the safety guarantees Swift normally provides, for any >> project that imports that extension and uses a subclass of NSObject. At >> best, we as a community decide “don’t do that”; at worse, some nontrivial >> fraction of the community decides that the benefits outweigh the costs (for >> this type or some other), and we can no longer say that Swift is a strong >> statically-typed language without adding “unless you’re using something that >> adopts DynamicMemberLookupProtocol”. >> >> Tooling >> The Python interoperability enabled by this proposal *does* look fairly nice >> when you look at a small, correctly-written example. However, absolutely >> none of the tooling assistance we rely on when writing such code will work >> for Python interoperability. Examples: >> >> * As noted earlier, if you typo’d a name of a Python entity or passed the >> wrong number of arguments to it, the compiler will not tell you: it’ll be a >> runtime failure in the Python interpreter. I guess that’s what you’d get if >> you were writing the code in Python, but Swift is supposed to be *better* >> than Python if we’re to convince a community to use Swift instead. >> * Code completion won’t work, because Swift has no visibility into >> declarations written in Python >> * Indexing/jump-to-definition/lookup documentation/generated interface won’t >> ever work. None of the IDE features supported by SourceKit will work, which >> will be a significant regression for users coming from a Python-capable IDE. >> >> Statically-typed languages should be a boon for tooling, but if a user >> coming from Python to Swift *because* it’s supposed to be a better >> development experience actually sees a significantly worse development >> experience, we’re not going to win them over. It’ll just feel inconsistent. >> >> Dynamic Typing Features >> It’s possible that the right evolutionary path for Swift involves some >> notion of dynamic typing, which would have a lot of the properties sought by >> this proposal (and the DynamicCallableProtocol one). If that is true—and I’m >> not at all convinced that it is—we shouldn’t accidentally fall into a >> suboptimal design by taking small, easy, steps. If we’re to include >> dynamic-typing facilities, we should look at more existing practice—C# >> ‘dynamic' is one such approach, but more promising would be some form of >> gradual typing a la TypeScript that let’s one more smoothly (and probably >> explicitly) shift between strong and weak typing. >> >> How Should Python Interoperability Work? >> Going back to the central motivator for this proposal, I think that >> providing something akin to the Clang Importer provides the best >> interoperability experience: it would turn Python declarations into *real* >> Swift declarations, so that we get the various tooling benefits of having a >> strong statically-typed language. Sure, the argument types will all by >> PyObject or PyVal, but the names are there for code completion (and >> indexing, etc.) to work, and one could certainly imagine growing the >> importer to support Python’s typing annotations. But the important part here >> is that it doesn’t change the language model at all—it’s a compiler feature, >> separate from the language. Yes, the Clang importer is a big gnarly >> beast—but if the goal is to support N such importers, we can refactor and >> share common infrastructure to make them similar, perhaps introducing some >> kind of type provider infrastructure to allow one to write new importers as >> Swift modules. >> >> In truth, you don’t even need the compiler to be involved. The dynamic >> “subscript” operation could be implemented in a Swift library, and one could >> write a Python program to process a Python module and emit Swift wrappers >> that call into that subscript operation. You’ll get all of the tooling >> benefits with no compiler changes, and can tweak the wrapper generation >> however much you want, using typing annotations or other Python-specific >> information to create better wrappers over time. >> >> - Doug >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution