On Sun, Dec 3, 2017 at 2:16 PM, Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:
> > On Dec 3, 2017, at 11:36 AM, Chris Lattner <clatt...@nondot.org> wrote: > > On Dec 2, 2017, at 7:11 PM, Matthew Johnson <matt...@anandabits.com> > wrote: > > > This does not improve clarity of code, it merely serves to obfuscate > logic. It is immediately apparent from the APIs being used, the API style, > and the static types (in Xcode or through static declarations) that this is > all Python stuff. > > > It may be immediately apparent when the types involved are obviously > dynamic, such as in this example where Python.import is explicitly used. > However, my concern is less about the intended use case of dynamic language > interop than I am that this feature will be generally available to all > types in Swift. > > This is big change from AnyObject dispatch. It opens up the dynamism to > types and contexts that *are not *necessarily obviously using dynamic > lookup, callable, etc. Maybe this won’t turn out to be a problem in > practice but I still think it’s a legitimate concern. > > > Sure, it is a legit concern, but it is also nothing new. This is the > standard concern with type inference. > > > The concern for me is orthogonal to type inference. The name of a type > supporting dynamic lookup will not necessarily provide any indication that > the type supports dynamic lookup. > > > While there are weird cases, in practice, values do not get magicked out > of no-where. They most commonly are either root values like: > > let np = Python.import(“foo”) > let pyInt = PyVal(42) > > or they come for parameters: > > func f(x : PyVal) { > > The place that is potentially surprising is when the type gets buried > because you’re working with some API that returns a [String, PyVal] > dictionary or something: > > > let x = foo()[“someKey”] > > and you don’t realize that PyVal’s are involved. However, if you are > actively writing the code, you have access to code completion and other > things that tell you these types, and if it is important for the clarity of > the code, you write this instead: > > let x :PyVal = foo()[“someKey”] > > There is nothing specific to this proposal about this issue. > > > See above. In the case of PyVal specifically the concern is somewhat > mitigated by the name of the type. That won’t necessarily always be the > case. > If that's the concern, then it would be pretty straightforward to restrict dynamic protocols for stdlib internal use only and expose only PyVal. The trade-off is that all such bridging code would have to be shipped with Swift itself. > I’m uncertain what the right answer is. I’m still not really comfortable > with opening up dynamic lookup to any user-defined type without some way to > indicate to readers that dynamic lookup is happening in a piece of code. > Maybe there is a less localized annotation that would indicate dynamic > lookup is in effect for a larger chunk of code. > > > You seem to be extremely concerned that people will adopt > DynamicMemberLookup for types where it doesn’t make sense and abuse the > feature. I am having a real problem understanding what your concern is, so > I’d really love for you to explain some theoretical examples of the bad > thing that happens: why someone (non-maliciously) adopts the protocol, what > code gets written, and what harm actually comes from it. > > Let me use a made up tale from a parallel universe to illustrate why I > don’t understand your concern. Imagine if Swift didn’t already > interoperate with C, and did not already have IUOs. Someone who cared > about C language interoperability would quickly realize that the ergonomics > of importing everything as strong optionals is a non-starter, jeopardizing > the usability of C interop, and would propose IUOs as a feature. > > We’d then have a long and drawn out conversation about the various options > on how to model this, the pros and cons of each, and would settle on IUO as > the least bad design (as an aside, in our universe, when we went through > the design process that led to IUOs, this is exactly what happened, we even > considered syntaxing them as interobangs :-). > > At that point, there would be a general uproar because IUOs have high > potential for abuse: Swift is “all about” strong types and safety, which > IUOs undermine. Strong optionals are considered a pain to use by some > people and widely misunderstood (I think they are the biggest challenge in > learning Swift in practice), and so it is a reasonable feature that people > could pervasively adopt IUOs, leading to a much worse world all around. > > > This made up parallel universe is exactly analogous to what is happening > now. DynamicMemberLookup is no more dangerous and harmful than IUOs are. > They will be one more tool in the toolbox. While it is possible that > someone will abuse it, this will not be widespread. People who are > particularly worried will build a single new rule into their linters (which > already flag uses of x!), and the world will keep revolving. > > > There is an important difference between IUOs and dynamic lookup in my > mind. In the case of dynamic lookup a runtime value (the member name) is > masquerading as something that is statically verified everywhere in Swift > *except* in the case of dynamic lookup. I would strongly prefer to not > need to consider the possibility that a member name is actually a runtime > value outside of contexts that make this possibility known to me when I am > reading code. Spelling a member name right is a precondition that is > trivial to violate both by accident and by code evolution. > > That is also why I am not concerned about the potential for failure of the > longhand way of writing this: x.get(“foo”).get(“bar”). It is clear that a > runtime value (which may violate a precondition) is being provided. That > is not at all the case when the dynamic lookup syntax mirrors static lookup > syntax with no contextual hint that it may be in effect. > > An example of the kind of thing I am concerned about is people using > dynamic lookup to avoid more structured forms of polymorphism. I can > imagine this happening for a number of reasons that are not intentionally > abusive or malicious. > > Some people are big fans of dynamic behavior and this feature will make it > much easier to write code in that style. They will do it without feeling > malicious or considering this to be abusive, considering it to be a > legitimate style preference. I wouldn’t be surprised to see people develop > mixins that implement the subscript using mirror and other future > reflection capabilities without considering that to be abusive (I would > almost be surprised if this *didn’t* happen). Requiring some kind of > usage site annotation would both discourage this and help anyone who walks > into a such a code base to understand what is going on. > > > > Even the behavior of AnyObject was carefully designed and considered, and > were really really good reasons for it returning IUO. > > > I am not trying to call into question the choices made in the past. Swift > wouldn’t be the great language with a bright future that it is today > without an incredibly successful migration of a large user base from > Objective-C to Swift. This is a huge accomplishment and couldn’t have > happened without making really good decisions about some really hard > tradeoffs. > > > You miss my point. My point is that AnyObject lookup was carefully > considered, has stood the test of time, and is the *right* answer. Swift 1 > would not have been nearly as successful without it. > > > I don’t think I do. I was trying to agree with exactly the point that it > was the right answer in the early days of Swift and getting it right then > was essential to Swift’s success. > > Aside from the historical necessity of AnyObject, it is also a very > specific and widely know type that doesn’t have *any* statically > available members at all and only looks up @objc members. These properties > help to reduce the risk that somebody misunderstands what is going on. > I imagine we could restrict all such dynamic types from having any statically available members without losing much.
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution