<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div><br></div><div><br>On Nov 11, 2017, at 10:33 AM, Chris Lattner <<a href="mailto:sabre@nondot.org">sabre@nondot.org</a>> wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Nov 11, 2017, at 10:15 AM, Joe Groff 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 dir="auto" class=""><div class=""></div><div class=""><br class=""></div><div class=""><br class="">On Nov 11, 2017, at 10:04 AM, Chris Lattner <<a href="mailto:sabre@nondot.org" class="">sabre@nondot.org</a>> wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><meta http-equiv="Content-Type" content="text/html; charset=us-ascii" class=""><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Nov 11, 2017, at 6:29 AM, Joe Groff 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=""><div class="Singleton"><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">below the fold as far as the rest of the language is concerned. You could just as well written what the importer synths up in Swift directly:<br class=""><br class="">func foo(bar: String) {<br class="">unsafeBitCast(objc_msgSend, to: @convention(c) (AnyObject, Selector, NSString) -> ().self)(self, "fooWithBar:", NSString(bar))<br class="">}<br class=""><br class="">and the rest of the language would be none the wiser.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Though, since you bring up objc_msgSend, the way it works in ObjC might be a better fit for Swift's name lookup model, since their keyword argument models are similar. If Swift had a 'method of last resort' like ObjC's</span></div></div></blockquote></div><br class=""><div class="">In fact, this is the subject of the next proposal that I will write up when I have time.</div></blockquote><br class=""><div class="">It seems to me like a dynamic method-of-last-resort feature would subsume this proposal. Out of curiosity, why would we need both?</div></div></div></blockquote><br class=""></div><div>It seems that you missed the "[Discussion] Swift for Data Science / ML / Big Data analytics” thread, in which a lot of context was discussed, as well as multiple design approaches. </div></div></blockquote><div><br></div><div>Mea culpa, though data science is not my forte so I wouldn't have noised up a thread with that topic without being asked to.</div><br><blockquote type="cite"><div><div>In any case, I will summarize here:</div><div><br class=""></div><div>There are two fundamental operations that need to be supported to make a big impact on dynamic language interop: member lookup and calls.</div><div><br class=""></div><div>Many languages treat these as separable concepts. In Python for example, these are equivalent:</div><div><br class=""></div><div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>return foo.bar(x: 1, 23, y: 17)</div><div class="">and:</div></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>a = foo.bar</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>return a(x: 1, 23, y: 17)</div><div><br class=""></div><div>Swift and the other Smalltalk inspired languages are the odd ones out who tie method arguments into the base name of a function. With no language changes, it is possible to implement a pretty reasonable Python interop layer with the call and member operations explicit, it looks like this:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>func example(foo : PyVal) -> PyVal {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> return foo.get(member: “bar”).call(args: (“x”, 1), (“”, 23), (“y”, 17))</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div>and while it is totally possible to sugar common cases, e.g.:</div><div><br class=""></div><div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>func example(foo : PyVal) -> PyVal {</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span> return foo.call(member: “bar”, args: (“x”, 1), (“”, 23), (“y”, 17))</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div><div class="">you still need to support the basic model because Python supports currying and has global functions with keyword arguments. FWIW, Perl follows a similar model, but doesn’t have keyword arguments.</div></div></div></blockquote><div><br></div><div>Sure, the language models are different, but they're also different languages with different idioms, and bridging one to the other IMO doesn't mean it's a good idea to port over all the idioms literally. Allowing:</div><div><br></div><div><blockquote type="cite"><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">a = foo.bar</span></font></div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">return a(x: 1, 23, y: 17)</span></font></div></blockquote><br></div><div>may provide some initial familiarity to someone fresh from Python, but it will delay their ability to transition to Swift's way of doing things and confuse them when their own Swift code they write doesn't work the Python way. We should be able to make the more Swift-idiomatic `a = foo.bar(x:y:); a(1, 23, 17)` form work.</div><div>-Joe</div><br><blockquote type="cite"><div><div><div class="">I don’t really care much about the implementation approach (if this proposal isn’t the right one, fine!) but it is important to get this down to:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func example(foo : PyVal) -> PyVal {</div></div><div><div><span class="Apple-tab-span" style="white-space: pre;">        </span> return foo.bar(x: 1, 23, y: 17)</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div></div><div>which I hope you’ll agree is a *HUGE* readability and writability benefit, so much so that users would reject the long hand notion.</div><div><br class=""></div><div><br class=""></div><div>The discussion phase in the previous thread considered several approaches, including burning python specific support in, implementing a python importer, and implementing a single “dynamic thing” protocol. These are all bad ideas for reasons described in the thread. If you’re curious, I’m happy to elaborate in alternatives considered.<br class=""></div><div class=""><br class=""></div><div>As such, discussion converged on pitching two proposals, which are generally useful beyond this niche:</div><div><br class=""></div><div>1. The dynamically callable one already written.</div><div>2. A dynamically member lookupable proposal to sugar things like foo.get(member: “bar”) - and the corresponding setter.</div><div><br class=""></div><div>The former one is presumably useful for things outside dynamic languages, e.g. implementing dynamic “proxy” type interfaces.</div><div>The second one is useful for far more than just dynamic languages, e.g. sugaring json keypath traversals.</div><div><br class=""></div><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></div></blockquote></body></html>