On Dec 1, 2017, at 5:50 PM, Matthew Johnson <matt...@anandabits.com> wrote:
>>> This design introduces a significant hole in the type system which is 
>>> contrary to the spirit of Swift.
>> There is no “hole” in the type system.  The proposal is fully type safe. 
>> Further, the addition is absolutely in the spirit of Swift, because it is 
>> directly analogous to an existing feature: AnyObject lookup.  The difference 
>> between it and AnyObject lookup is that AnyObject lookup is:
>> a) specific to Objective-C interop
>> b) type unsafe
>> c) massively invasive on the rest of the compiler.
>> We’ve made many attempts to narrow the scope of AnyObject lookup, but it is 
>> difficult to do so given backwards compatibility constraints and the limited 
>> nature of Objective-C metadata.
> I may have spoken incorrectly but I do still believe it is contrary to what I 
> (and apparently many others) feel is the spirit of Swift.  
> As I understand it, AnyObject lookup was a necessity during the historical 
> development of Swift.  The attempts to narrow its scope have merit regardless 
> of how far they can go.  They indicate that perhaps it is a feature we would 
> remove if that were possible.  I would love to see that happen someday 
> (although I know it is unlikely), or at least see it be made explicit at the 
> call site.  I suspect if this feature did not exist and it was proposed today 
> it would be met with at least as much resistance as your proposals have.

This isn’t the way I see it.  You’re right that we want to reduce AnyObject 
dispatch wherever possible: types are good after all.  Swift on Linux doesn’t 
even have AnyObject dispatch, so you can tell that it is a means to an end, not 
a feature that we think is great for Swift on its own merits.

What is that end?  It is interoperability with truly dynamic values, which do 
occur in Objective-C, where pervasive casting would harm code clarity and 
usability.  The desire to fix AnyObject you are seeing are related to two 
different issues: 1) The design of AnyObject dispatch itself is problematic in 
some ways, and 2) many values in ObjC APIs were typed as id simply because 
there was no way to describe a more specific type given Objective-C’s original 
type system (which has been improved).  However, given the presence of actually 
polymorphic values being used by some APIs, I don’t imagine it going away 

In the case of other dynamic languages, the situation is even more severe.  
Some dynamic languages have progressive type systems available, but not all do. 
 Those which do have to deal with the fact that the base languages were not 
designed for typing systems, which is far more severe a problem than 
Objective-C’s situation.  

If you haven’t already, I encourage you to read the mypy docs 
<http://mypy.readthedocs.io/en/stable/index.html>) to understand how the type 
system they’re trying to build on top of Python works.  They have to contend 
with things like:

- the single array subscript operator taking both scalars and ranges, and 
returning different type results depending on their input (Python has no 
- pervasive use of duck typing, e.g. int is duck type compatible with float and 
complex (duck typing is for many non-primitive types as well)
- pervasive use of variance
- APIs creep to “just work” when passed all sorts of weird values, meaning that 
their API contract is extremely loose.
- Python supports *dynamically computed base classes* and lots of other crazy 
- and more..

Mypy also only supports a subset of Python - it doesn’t support properties with 
setters as one example, and its generic and class system is only partially 
implemented.  The only way to use it in practice is to use their ability to 
silence warnings, it is not an acceptable basis for a sound type system that we 
could depend on in Swift.

For all those reasons, we really do need something like AnyObject dispatch if 
we care about working with dynamically typed languages.  The design I’m 
suggesting carefully cordons this off into its own struct type, so it doesn’t 
infect the rest of the type system, and is non-invasive in the compiler.

>>> 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.
>> This is a feature, like many others, which can be misused.  This has not 
>> been the metric we have used to judge what should go into Swift.  I can 
>> elaborate if my response to Doug wasn’t clear.
> The primary problem I have is that misuse is too easy and too subtle.  It is 
> at least as easy to misuse as other features in Swift which have been 
> carefully designed to be obvious at usage sites.  
> I was happy to see that you are willing to consider Xiaodi’s suggestion to 
> require conformance to be stated as part of the original type declaration.  
> That would be a significant improvement to the proposal IMO.

I’ve revised the proposal to require this.

> I strongly urge you to reconsider the decision of that dynamic members must 
> be made available with no indication at usage sites.  An indication of 
> dynamic lookup at usage sites aligns very well (IMO) with the rest of Swift 
> (AnyObject lookup aside) by calling attention to code that requires extra 
> care to get right.

I don’t understand this.  The proposal is fully type safe, and this approach is 
completely precedented by AnyObject.  Swift’s type system supports many ways to 
express fallibility, and keeping those decisions orthogonal to this proposal is 
the right thing to do, because it allows the author of the type to decide what 
model makes sense for them.

In any case, I hear loud and clear that there is concern about possible abuse 
of this proposal, so I added a section in the alternatives section to discuss 
further ways to reduce possibility for abuse:

More suggestions are welcome.

>>> 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.
>> How would you this to work with *any* interoperability approach?  Dynamic 
>> languages are in fact dynamic, and need the ability to do dynamic lookups 
>> somehow.  Those dynamic lookups will all have the problem you observe.
> I’ll mostly let Doug continue the discussion of the approach he is 
> suggesting.  It looks to me like that is an approach that might help in this 
> area.  For example, if a symbol is removed it may be possible to produce a 
> compiler error in at least some cases.  I don’t think Doug’s suggestion 
> precludes full dynamism but would offer a much better experience in at least 
> some cases.  Perhaps it would even be enough to call into question whether 
> full dynamism is really necessary or not (as Doug seems to think).  We won’t 
> know for sure without exploring this further.
> I understand that you believe the direction he has advocated is not 
> realistic.  Perhaps, but I do appreciate that the conversation is happening 
> before a final decision is made.  I support further exploration of this at 
> least as long as Doug believes it is a good idea to do so.

Yes, I agree, it is important to get aligned on this.

>>> 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 really fail to see how this concern relates here.  This has nothing to do 
>> with compiler flags.  This has the potential to expand the community, not 
>> fragment it.
> One of the stated aims of this proposal is to bring many new programmers into 
> the Swift community.  That is a wonderful goal!  
> Of course that may include programmers with a different set of technical 
> values than are currently predominant in the Swift community.  If we make it 
> really easy to use Swift as a highly dynamic language we may soon see a large 
> sub-community form that uses Swift in this way.  Regardless of how you would 
> feel about this I think it’s an important possible outcome to consider.
> You mentioned that many of them may prefer proper Swift APIs for the 
> libraries they use and are hoping that the issues with dynamism will 
> incentive them to create these in time.  Perhaps requiring some kind of 
> call-site annotation would increase this incentive without being significant 
> enough to disincentive using these libraries in Swift.

I think you over-estimate how awesome Python (and other language APIs) are 
going to be, even with these two proposals.  Keep in mind that Python has the 
GIL for example, the naming conventions and design patterns are completely 
different, etc.  Even with both of these proposals, there will be high 
incentive for building pure Swift APIs to replace things over time.  The 
situation is similar to C interop with Swift: it is incredibly important that 
it exist, but people aren’t exactly aiming to use UnsafePointer for everything 
:-).  It is possible someone would do so, but people do all sorts of bad things 
locally in their codebase.  We cannot prevent that.

In fact, I would argue that making Python interoperability *too good* is the 
bigger risk we have.  If there is no reason for people to move off of using 
those APIs, they will continue to do so forever.  That isn’t a transition path, 
that’s a merger of communities.

> In particular, if you continue to insist on standard dot syntax for member 
> lookup I would appreciate hearing more about why that is a sticking point for 
> you, especially in light of your recent comment about people looking to move 
> away from Python.

Thanks, I addressed this in the alternative section.


swift-evolution mailing list

Reply via email to