<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Dec 3, 2017, at 11:36 AM, Chris Lattner via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">On Dec 2, 2017, at 7:11 PM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:<br class=""><div class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><blockquote type="cite" class=""><div class=""><div class=""><div class=""><div class=""><br class=""></div></div><div class="">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. </div></div></div></blockquote><div class=""><br class=""></div><div class="">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. </div><div class=""><br class=""></div><div class="">This is big change from AnyObject dispatch. It opens up the dynamism to types and contexts that <i class="">are not </i>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.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Sure, it is a legit concern, but it is also nothing new. This is the standard concern with type inference.</div><div class=""><br class=""></div><div class="">While there are weird cases, in practice, values do not get magicked out of no-where. They most commonly are either root values like:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let np = Python.import(“foo”)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let pyInt = PyVal(42)</div><div class=""><br class=""></div><div class="">or they come for parameters:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func f(x : PyVal) {</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let x = foo()[“someKey”]</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x :PyVal = foo()[“someKey”]</div><div class=""><br class=""></div><div class="">There is nothing specific to this proposal about this issue.</div></div></div></div></div></blockquote><div><br class=""></div><div>Going with this line of thought: a lot of these concerns could be a job for static analysis. Autocomplete, linters, refactoring tools, etc. can all help us reason wisely about dynamism where it appears.</div><div><br class=""></div><div>One important factor in the success of Swift’s type inference is that modern dev tools are up to the task of working with it. Xcode (and AppCode for that matter) have, shall we say, a long way to go to realize their potential — but even with their warts, the fact is that a developer today can reasonably expect real-time feedback about code structure that is not explicitly surfaced in the syntax itself.</div><div><br class=""></div><div>It’s worth asking why Java didn’t add Swift-like type inference 20 years ago. Java is a language whose type system at the time (no function types, no generics even!) would if anything have made inference much easier to implement, and for developers to reason about. I don’t think this was just down to Gosling’s taste, though; language designers can assume some ready availability of static analysis at edit time in a way they couldn’t back in the 90s.</div><div><br class=""></div><div>• • •</div><div><br class=""></div><div>What do I mean by this in practice? Well:</div><div><br class=""></div><div>I agree with Chris that this syntax is…yucky:</div><div><br class=""></div><div><font face="Menlo" class=""> let y = np^.arange^(24)^.reshape^(2, 3, 4)</font><br class="" style="font-family: HelveticaNeue;"></div><div><span style="font-family: HelveticaNeue;" class=""><br class=""></span></div><div><span style="font-family: HelveticaNeue;" class="">…but an editor could use syntax coloring to differentiate dynamic dispatches:</span></div><div><span style="font-family: HelveticaNeue;" class=""><br class=""></span></div><div><div><div><font face="Menlo" class=""> let y = np.<font color="#d36c3c" class="">arange</font>(24).<font color="#d36c3c" class="">reshape</font>(2, 3, 4)</font><br class="" style="font-family: HelveticaNeue;"></div><div class=""><font face="Menlo" class=""><br class=""></font></div></div></div><div><span style="font-family: HelveticaNeue;" class="">Teams worried about their abuse or inadvertent use could make them bold and red. This would achieve the same purpose as the separate syntax, sans yuckiness.</span></div><div><span style="font-family: HelveticaNeue;" class=""><br class=""></span></div><div><span style="font-family: HelveticaNeue;" class="">Refactoring tools could flag •potential• </span><span style="font-family: HelveticaNeue;" class="">name</span><span style="font-family: HelveticaNeue;" class=""> </span><span style="font-family: HelveticaNeue;" class="">matches in dynamic dispatches much the same they currently do for comments.</span></div><div><span style="font-family: HelveticaNeue;" class=""><br class=""></span></div><div><span style="font-family: HelveticaNeue;" class="">For those teams concerned about abuse of the feature, a lint tool could enable individual project to either prohibit dynamic calls or limit them to certain files or comment-fenced code sections.</span></div><div><span style="font-family: HelveticaNeue;" class=""><br class=""></span></div><div><span style="font-family: HelveticaNeue;" class="">Most of the concerns I’ve heard expressed in this thread could be addressed by sensible developers and good tools. The latter are feasible; the former no language can enforce.</span></div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class="">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. </div></div></div></blockquote><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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 :-).</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><div class="">Even the behavior of AnyObject was carefully designed and considered, and were really really good reasons for it returning IUO.</div></div></div></blockquote><div class=""><br class=""></div><div class="">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.</div></div></div></div></blockquote></div><br class=""><div class="">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.</div><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>