<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Nov 28, 2017, at 10:12 AM, Paul Cantrell &lt;<a href="mailto:cantrell@pobox.com" class="">cantrell@pobox.com</a>&gt; wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Chris wrote:</div><div class=""><blockquote type="cite" class="">Paul wrote:</blockquote><blockquote type="cite" class="" style="font-family: HelveticaNeue;"><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><div class=""></div></div></div></blockquote><blockquote type="cite" class=""><blockquote type="cite" class="" style="font-family: HelveticaNeue;"><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><div class=""><b class="" style="background-color: rgb(255, 255, 255);">An “always use parens” bridge to Ruby has bad ergonomics</b></div><div class=""><div class="" style="font-family: Helvetica; margin: 0px; font-stretch: normal; font-size: 12px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"></div></div><div class=""><span class="">Zero-arg Ruby methods are a mixture of property-like things that would certainly&nbsp;</span><i class="">not</i><span class="">&nbsp;</span><span class="">use parens in Swift, and function-like things that certainly</span><span class="">&nbsp;</span><i class="">would</i><span class="">:</span></div><div class=""><div class=""><br class=""></div><div class=""><div class="" style="font-family: Menlo; margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; color: rgb(102, 139, 73); background-color: rgb(255, 255, 255);"><span class="">&nbsp; &nbsp;&nbsp;</span>// Idiomatic Swift:</div><div class="" style="font-family: Menlo; margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; post.author.name.reversed()</div><div class="" style="font-family: Helvetica; margin: 0px; font-stretch: normal; font-size: 12px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><br class=""></div><div class="" style="font-family: Menlo; margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; color: rgb(102, 139, 73); background-color: rgb(255, 255, 255);"><span class="">&nbsp; &nbsp;&nbsp;</span>// Swift bridging to Ruby…</div><div class="" style="font-family: Helvetica; margin: 0px; font-stretch: normal; font-size: 12px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><br class=""></div><div class="" style="font-family: Menlo; margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; color: rgb(102, 139, 73); background-color: rgb(255, 255, 255);"><span class="">&nbsp; &nbsp;&nbsp;</span>// …if no-args methods •must• use parens:</div><div class="" style="font-family: Menlo; margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; background-color: rgb(255, 255, 255);">&nbsp; &nbsp;&nbsp;post.author().name().reverse()</div><div class="" style="font-family: Helvetica; margin: 0px; font-stretch: normal; font-size: 12px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><br class=""></div><div class="" style="font-family: Menlo; margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; color: rgb(102, 139, 73); background-color: rgb(255, 255, 255);"><span class="">&nbsp; &nbsp;&nbsp;</span>// …if no-args methods •can’t• use parens:</div><div class="" style="font-family: Menlo; margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; background-color: rgb(255, 255, 255);">&nbsp; &nbsp;&nbsp;post.author.name.reverse</div><div class="" style="font-family: Helvetica; margin: 0px; font-stretch: normal; font-size: 12px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><br class=""></div><div class="" style="font-family: Helvetica; margin: 0px; font-stretch: normal; font-size: 12px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><span class="" style="font-family: &quot;Helvetica Neue&quot;; font-size: 13px;">If the goal is to make Swift mostly feel like Swift even when bridging to Ruby, then the bridge needs to support both access&nbsp;forms.</span></div></div></div></div></div></blockquote><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Ok, that can certainly be implemented by the two proposals I have in flight. &nbsp;No obvious problem there.</div></blockquote></div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">Chris, can you elaborate? I think the proposal precludes this; I must be missing something!</div></div></div></blockquote><div><br class=""></div><div>There are two proposals in flight: one that allows specifying runtime behavior for “a.b” syntax and one that allows specifying runtime behavior for “a(x)” and “a.b(x)” syntax (“DynamicCallableWithKeywordsToo”, which needs to be renamed obviously).</div><div><br class=""></div><div>For your use case, you’d implement both of them. &nbsp;If someone wrote</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>a.b().c</div><div><br class=""></div><div>Then you’d look up and call a zero-argument method named “b” on the a object. &nbsp;However if someone wrote:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>a.b.c</div><div><br class=""></div><div>Then you’d do the same thing (in the implementation of the DynamicMemberLookupProtocol). &nbsp;This approach allows the human writing code at your bridge to use whatever syntax “feels best” to them given the specific API in question that they are using.</div><div><br class=""></div><div>You could even have “a.b” syntax fall back to finding Ruby ivars as well, though I don’t know if that is actually a good idea in practice for a Ruby bridge.</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 style="font-family: HelveticaNeue;" class="">As I read the proposal, the dynamic member subscript for&nbsp;<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">post.author</span>&nbsp;returns either a property value or a DynamicCallable, depending on whether the thing is a property or a method — but&nbsp;<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">post.author</span>&nbsp;and&nbsp;<span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">post.author()</span>&nbsp;would both look identical to that subscript implementation, and there’s no distinction on the Ruby side, so the subscript can’t know which one to return.</div></div></div></blockquote><div><br class=""></div><div>“post.author" always invokes the DynamicMemberLookupProtocol proposal.</div><div>“post.author()” would invoke the “DynamicCallableWithKeywordsToo” hook in the dynamic callable proposal:</div><div><a href="https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d" class="">https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d</a></div><div><br class=""></div></div><div class="">-Chris</div><div class=""><br class=""></div></body></html>