<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 class=""><blockquote type="cite" class=""><div class="">On Nov 20, 2017, at 7:47 PM, Chris Lattner via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><br class=""><blockquote type="cite" class="">On Nov 20, 2017, at 1:41 PM, David Waite &lt;<a href="mailto:david@alkaline-solutions.com" class="">david@alkaline-solutions.com</a>&gt; wrote:<br class=""><br class="">In ruby, parens are optional. So,<br class=""><br class="">v = foo.value<br class=""><br class="">and<br class=""><br class="">v = foo.value()<br class=""><br class="">are identical.<br class=""></blockquote><br class="">Ok, I wasn’t aware of that. &nbsp;It isn’t clear that we’d want to carry that into a “Ruby APIs when used in Swift” though! &nbsp;One could definitely argue against the former calling a method, even if that is possible in Ruby APIs.<br class=""><br class=""><blockquote type="cite" class="">There dot syntax is only used for method invocation, so there is no external access to instance variables without some twiddling; similarly getting access to a Proc/lambda/Method requires twiddling in Ruby (although there are shortcuts in normal use, like Symbol#to_proc)<br class=""></blockquote><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><br class=""></div><div>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><br class=""></div><div>Key excerpts:</div><div><br class=""></div><div>–––––––––––––––––––––––––</div><div><br class=""></div><div><div class="" style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><b class="">An “always use parens” bridge to Ruby has bad ergonomics</b></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></div><div><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><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="color: rgb(0, 0, 0);">&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="color: rgb(0, 0, 0);">&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="color: rgb(0, 0, 0);">&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="color: rgb(0, 0, 0);">&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 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="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;"><div>–––––––––––––––––––––––––</div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><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="color: rgb(0, 0, 0);">&nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(50, 62, 125);">extension</span><span class="" style="color: rgb(0, 0, 0);">&nbsp;</span>RubyObj<span class="" style="color: rgb(0, 0, 0);">:&nbsp;</span>DynamicMemberLookupProtocol<span class="" style="color: rgb(0, 0, 0);">&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 class=""><br class=""></div><div class=""><br class=""></div><blockquote type="cite" class=""><br class=""><blockquote type="cite" class="">More difficult would be the use of ‘=‘, ‘!’, and ‘?’ - all legal in Ruby method names as suffixes.<br class=""></blockquote><br class="">Using those would require backquotes:<br class=""><br class="">x.`what?`()&nbsp;<br class=""><br class=""><br class="">-Chris<br class=""><br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote></div><div class=""><br class=""></div></body></html>