<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 20, 2017, at 6:06 PM, 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=""><blockquote type="cite" class=""><div class=""><br class="">I think you’re missing the idea here: the idea isn’t to provide exactly syntax mapping of Ruby (or Python) into Swift, it is to expose the underlying semantic concepts in terms of Swift’s syntax. &nbsp;In the case of Python, there is a lot of direct overlap, but there is also some places where Swift and Python differs (e.g. Python slicing syntax vs Swift ranges). &nbsp;In my opinion, Swift syntax wins here, we shouldn’t try to ape a non-native syntax in Swift.<br class=""><br class=""><blockquote type="cite" class="">For mapping to Swift, I would say that parens are needed; we can’t guess whether a `foo.bar` is meant to be asking for the value of attribute bar or a reference to method bar.<br class=""></blockquote><br class="">+1<br class=""></div></blockquote><div class=""><br class=""></div><div class="">Chris, did you follow at all the earlier chain of emails where Brent, Jean-Daniel and I hashed this out at length? You may not have got to it yet….</div></div></div></div></blockquote><div><br class=""></div>Perhaps not, I’m just catching up on this thread now. &nbsp;Keep in mind I know almost nothing about Ruby :-)</div><div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><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 style="font-family: HelveticaNeue;" class="">Zero-arg Ruby methods are a mixture of property-like things that would certainly&nbsp;</span><i class="" style="font-family: HelveticaNeue;">not</i><span style="font-family: HelveticaNeue;" class="">&nbsp;</span><span style="font-family: HelveticaNeue;" class="">use parens in Swift, and function-like things that certainly</span><span style="font-family: HelveticaNeue;" class="">&nbsp;</span><i class="" style="font-family: HelveticaNeue;">would</i><span style="font-family: HelveticaNeue;" class="">:</span></div><div class=""><div class="" style="font-family: HelveticaNeue;"><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="" style="">&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="" style="">&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="" style="">&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="" style="">&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 style="font-family: &quot;Helvetica Neue&quot;; font-size: 13px;" class="">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><br class=""></div><div>Ok, that can certainly be implemented by the two proposals I have in flight. &nbsp;No obvious problem there.</div><div><br class=""></div><div><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class=""><div class=""><div class="" style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><div class="" style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;"><b class="">Separating method calls from property accesses solves the problem</b></div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class="">Brent wrote:</div></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;"><div class=""><blockquote type="cite" class="" style="font-family: HelveticaNeue; font-size: 13px;"><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div dir="auto" class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><div class="">If we had separate subscripts for methods and properties, then the property subscript could immediately call the appropriate getters and setters, while the method subscript could return a ready-to-call `Method` object.</div></div></div></div></div></blockquote></div></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></div><div style="font-family: HelveticaNeue;" class="">Better yet, why bother with the ready-to-call Method-like object? Just call it! A Ruby binding with separate property and method handling would then look like this:</div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class=""><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(88, 126, 168); background-color: rgb(255, 255, 255);"><span class="" style="">&nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(50, 62, 125);">extension</span><span class="" style="">&nbsp;</span>RubyObj<span class="" style="">:&nbsp;</span>DynamicMemberLookupProtocol<span class="" style="">&nbsp;{</span></div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(50, 62, 125);">func</span>&nbsp;callDynamicMethod(dynamicMethod method:&nbsp;<span class="" style="color: rgb(88, 126, 168);">String</span>, args: [<span class="" style="color: rgb(88, 126, 168);">RubyObject</span>]) -&gt;&nbsp;<span class="" style="color: rgb(88, 126, 168);">RubyObj</span>&nbsp;{</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; get {</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(50, 62, 125);">return</span>&nbsp;RubyObject_send(rubyObject, method: member, args: args)</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; }</div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class="">&nbsp;&nbsp; &nbsp; &nbsp;<br class="webkit-block-placeholder"></div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(50, 62, 125);">subscript</span>(dynamicMember member:&nbsp;<span class="" style="color: rgb(88, 126, 168);">String</span>) -&gt;&nbsp;<span class="" style="color: rgb(88, 126, 168);">RubyObj</span>&nbsp;{</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(50, 62, 125);">get</span>&nbsp;{</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(50, 62, 125);">return</span>&nbsp;RubyObject_send(rubyObject, method: member, args: [])</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(50, 62, 125);">set</span>&nbsp;{</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RubyObject_send(rubyObject, method:&nbsp;<span class="" style="color: rgb(133, 62, 100);">"</span>\<span class="" style="color: rgb(133, 62, 100);">(</span>member<span class="" style="color: rgb(133, 62, 100);">)="</span>, args: [newValue])</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; &nbsp; }</div><div class="" style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);">&nbsp; &nbsp; }</div></div><div style="font-family: HelveticaNeue;" class=""><br class=""></div><div style="font-family: HelveticaNeue;" class="">When Swift sees myObj.name, it uses the getter subscript. When Swift sees myObj.name(), it uses the method invocation. Both work in Swift just as they do in Ruby — and more importantly, Ruby APIs wouldn’t feel so very awkward when used from Swift.</div></div></div></blockquote><br class=""></div><div>Right, that should work directly!</div><div><br class=""></div><div>-Chris</div><div><br class=""></div><br class=""></body></html>