<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 <<a href="mailto:clattner@nondot.org" class="">clattner@nondot.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; -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 <<a href="mailto:cantrell@pobox.com" class="">cantrell@pobox.com</a>> 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 </span><i class="">not</i><span class=""> </span><span class="">use parens in Swift, and function-like things that certainly</span><span class=""> </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=""> </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);"> 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=""> </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=""> </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);"> 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=""> </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);"> 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: "Helvetica Neue"; 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 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. 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 DynamicCallableKeywordedMethod 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 DynamicMemberLookupProtocol. In other words, if `a` implements both protocols, then this:</div><div><br class=""></div><div><div> a.b(x)</div><div><br class=""></div><div>…expands to this:</div><div><br class=""></div><div> a.dynamicCall(method: "b", arguments: [("", x)])</div><div><br class=""></div><div>…and not this:</div><div><br class=""></div><div> 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> a.b</div></div><div class=""><br class=""></div><div class="">…still expands to:</div></div><div><br class=""></div> 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. 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. 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). 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 <span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">post.author</span> returns either a property value or a DynamicCallable, depending on whether the thing is a property or a method — but <span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">post.author</span> and <span style="font-family: Menlo; font-size: 11px; background-color: rgb(255, 255, 255);" class="">post.author()</span> 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>