> On Nov 30, 2017, at 3:48 PM, Paul Cantrell via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> 
> 
>> On Nov 30, 2017, at 3:40 PM, Douglas Gregor via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>> 
>>> On Nov 30, 2017, at 1:01 PM, Zach Wolfe <zacharyreidwo...@gmail.com 
>>> <mailto:zacharyreidwo...@gmail.com>> wrote:
>>> 
>>> Doug and others have brought up some great points, and I think Doug’s idea 
>>> of a common infrastructure for importing declarations from other languages 
>>> is _extremely_ attractive for the long-term future of Swift. 
>>> 
>>> However, unlike this proposal, that will (I imagine as a non-compiler 
>>> engineer) be a colossal undertaking, and as such it’s not going to make it 
>>> into Swift 5, or possibly even 6 or 7. I understand, then, Chris’s (and 
>>> other’s) desire to start interfacing with Python code now, not later. For 
>>> me, far and away the biggest problem with this proposal (and the only 
>>> outright deal-breaker) is that dynamic member lookups do not differentiate 
>>> themselves in any way from statically-checked member lookups syntactically. 
>>> I don’t object as strongly as others to the idea of adding this kind of 
>>> dynamism to the language, but if it’s going to be there, it should not be 
>>> possible to slightly misspell a static member name and end up with an 
>>> unexpectedly dynamic member that may or may not fail at compile-time.
>> 
>> As noted at the end of my message, I think one can write a Swift library to 
>> make working with the Python runtime much easier, and write a wrapper 
>> generator that produces Swift APIs from Python code that use said Swift 
>> library.
> 
> That might be true for Python; I’m quite certain it’s not the case for Ruby 
> or JS as they exist in the wild. However…
> 
> At the risk of stating a universally unpopular opinion, beyond interop with 
> dynamic languages such as Python, there’s also value in dynamic member lookup 
> for •purely Swift-centric• reasons.
> 
> I say this with mixed feelings. I share Douglas’s concerns about breaking 
> Swift’s safety bubble. I like it that the language generally makes it clear 
> •at the point of use• which language features have runtime pitfalls that the 
> compiler cannot check. The points where this is not true of the language 
> (e.g. array subscripts) always feel a bit gritty between the teeth.
> 
> There can, however, be great value in constructing type membership at 
> runtime. The ergonomic access to JSON that’s been discussed in this proposal 
> is nothing to sneeze at. Dynamic languages make for lovely DSLs in a way that 
> fully statically type checked languages never do. Things like Rails’s 
> programmatically generated named routes (e.g. “user_post_path(id)” because 
> routing configuration created a user resource with nested posts) are possible 
> to approximate with statically typed approaches — but only clumsily, never 
> with the same expressiveness and concision.
> 
> I don’t mean to sneeze at the downside of dynamic typing either. They too are 
> nothing to sneeze at. I’ve spent many years on both sides of the dynamic 
> divide, and all I see is difficult tradeoffs.
> 
> Swift so far has said that dynamism isn’t worth the tradeoffs; it’s 
> aggressively avoided even robust runtime reflection, much less dynamic 
> dispatch. That may indeed be the right call for the language — but I’m not 
> easily convinced there isn’t room to open the door wider.
> 
> I think of Chris’s post back in the early days of this list about the 
> “programmer model” the language creates, and wonder if there’s a way we can’t 
> make a model that leaves the door open to this kind of dynamic dispatch where 
> it makes sense for the people and situation at hand, while still staying true 
> to the language’s spirit of “compile-time safety by default, exceptions to 
> that by intent at point of use.”
> 
> Opening the door to dynamism might take some of the flavor of the way the 
> language currently handles unsafe memory access: it’s possible and even 
> reasonably ergonomic, but you always know when you’ve crossed the Rubicon 
> into Dangerland.

I would really like to see Swift gain more dynamic capabilities eventually.  I 
wrote a lot of Ruby years ago and really enjoyed some aspects of it. 

On the other hand, I do want to see us be very deliberate about adding them and 
do it in the right way and only when we are confident that we have identified 
the right feature(s) and designs for them.  If that means waiting a while I 
would rather wait than have regrets later.  If we can identify a design that 
feels appropriate for Swift and decide now is the time to introduce it I will 
be happy with that, but the timeline shouldn’t be prioritized higher than 
getting the design right.

The absolute minimum criteria I have for something I would consider worth 
taking a close look at is making dynamic member lookup clear at the call site 
as Zach Wolfe suggested earlier.  If you have other ideas about how to make it 
clear when you’ve “crossed the Rubicon into Dangerland” I am interested in 
hearing about them.  

I am not sure whether I would be convinced that a design like this is the right 
thing to do or not but am willing to give it deeper consideration.  I would 
also like to see the direction Doug alluded to explored in detail.  The 
alternatives need to be in explored enough depth that we can evaluate their 
relative strengths and weaknesses.  That hasn’t happened yet.

> 
> Cheers,
> 
> Paul
> 
>> 
>>      - Doug
>> 
>>> 
>>> On Nov 30, 2017, at 2:24 AM, Douglas Gregor via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>>> 
>>>> 
>>>>> On Nov 26, 2017, at 10:04 PM, Chris Lattner via swift-evolution 
>>>>> <swift-evolution@swift.org <mailto: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://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438>
>>>>> https://github.com/apple/swift-evolution/pull/768 
>>>>> <https://github.com/apple/swift-evolution/pull/768>
>>>>> 
>>>>> An implementation of this design is available here:
>>>>> https://github.com/apple/swift/pull/13076 
>>>>> <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.
>>>> 
>>>> 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 
>>>> <https://docs.python.org/3/library/typing.html>. 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 <mailto:swift-evolution@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to