<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 28, 2017, at 10:54 PM, Chris Lattner &lt;<a href="mailto:clattner@nondot.org" class="">clattner@nondot.org</a>&gt; 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; -webkit-line-break: after-white-space;" class=""><div class=""><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 class=""><br class=""></div><div class="">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></div></div></blockquote><div><br class=""></div><div>Yes, I’m aware of the two proposals in flight, but apparently missed the updated DynamicCallable proposal.</div><div><br class=""></div><div>You must be talking about DynamicCallableKeywordedMethod, not DynamicCallableWithKeywordsToo? Yes, that third protocol would solve the problem!</div><div><br class=""></div><div>Is&nbsp;DynamicCallableKeywordedMethod&nbsp;an official part of the callable proposal? I was thrown by the fact that the “<span style="white-space: pre-wrap;" class="">Smalltalk Family Languages” section is not nested under “Proposed Solution,” and thought it was meant as a separate/alternative idea. But reading the text, I see that it does seem to be part of that proposal.</span></div><div><br class=""></div><div>If that’s correct, then that “Smalltalk family” section ought to clarify that DynamicCallableKeywordedMethod takes precedence over&nbsp;DynamicMemberLookupProtocol. In other words, if `a` implements both protocols, then this:</div><div><br class=""></div><div><div>&nbsp; &nbsp; a.b(x)</div><div><br class=""></div><div>…expands to this:</div><div><br class=""></div><div>&nbsp; &nbsp; a.dynamicCall(method: "b", arguments: [("", x)])</div><div><br class=""></div><div>…and not this:</div><div><br class=""></div><div>&nbsp; &nbsp; a[dynamicMember: "b"].dynamicCall(arguments: [("", x)])</div><div class=""><br class=""></div><div class="">…while this:</div><div class=""><br class=""></div><div class=""><div>&nbsp; &nbsp; a.b</div></div><div class=""><br class=""></div><div class="">…still expands to:</div></div><div><br class=""></div>&nbsp; &nbsp; a[dynamicMember: "b”]</div><div><br class=""></div><div>Cheers, P<br class=""><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">For your use case, you’d implement both of them. &nbsp;If someone wrote</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>a.b().c</div><div class=""><br class=""></div><div class="">Then you’d look up and call a zero-argument method named “b” on the a object. &nbsp;However if someone wrote:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>a.b.c</div><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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></div></blockquote><div><br class=""></div><div>It’s certainly not the behavior you’d want, no. Ruby devs make a clear distinction between attr readers (Ruby’s name for properties) and ivars (which are same-instance-private).</div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><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 class=""><br class=""></div><div class="">“post.author" always invokes the DynamicMemberLookupProtocol proposal.</div><div class="">“post.author()” would invoke the “DynamicCallableWithKeywordsToo” hook in the dynamic callable proposal:</div><div class=""><a href="https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d" class="">https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d</a></div><div class=""><br class=""></div></div><div class="">-Chris</div><div class=""><br class=""></div></div></blockquote></div><br class=""></body></html>