<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 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. 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 class=""><br class=""></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></body></html>