<div dir="ltr">Scala has a sophisticated and interesting access level that might well be good fit to Swift (since the two languages are very similar), e.g Swiftizing some Scala:<div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">class society {<br><br></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">class professional {<br><br></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">class Executive {<br><br></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">private(society) var friends = ...</blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">private(professional) var workDetails = ...</blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">private var secrets = ...</blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><br>func executive() {</blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">print(friends) // OK inside society</blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">print(workDetails) // OK inside professional</blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">print(secrets) // OK inside Executive</blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">}<br><br></blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">}<br><br></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">func professional() {</blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">           print(friends) // OK inside society</blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">           print(workDetails) // OK inside professional</blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">           print(secrets) // ERROR outside Executive</blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">}<br><br></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">}<br><br></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">func society() {</blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">           print(friends) // OK inside society</blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">           print(workDetails) // ERROR outside professional</blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">           print(secrets) // ERROR outside Executive</blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">}<br><br></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">}<br><br>var exec = society.professional.Executive()</blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><br>print(exec.friends) // ERROR outside society<br>print(exec.workDetails) // ERROR outside professional<br>print(exec.secrets) // ERROR outside Executive</blockquote><div><br></div>In Scala access is:<br><div><ol><li>public, private, or private(S); plus protected for abstract classes and private(self) for generic classes with generic variance - neither relevant to this discussion</li><li>public behaves as expected</li><li>The default is public, therefore in the example above society, professional, Executive, and the functions are all public</li><li>private is scoped so that is only visible within its enclosing scope, hence secrets is only visible inside Executive<br></li><li>private(S) extends the visibility to the named enclosing scope S, hence workDetails is visible inside professional&#39;s scope because it is declared private(professional)</li></ol>If Scala style access modifiers were adopted for Swift then a private(file) modifier would also be necessary to give the current private functionality.<br></div><div><br></div><div>Note Scala has modules, called packages, and in the Scala example I copied and converted to Swift above the society and professional classes were packages and hence there lower-case spelling. Class was the nearest substitute in Swift for a scala package. The original Scala is from: <a href="http://www.tutorialspoint.com/scala/scala_access_modifiers.htm">http://www.tutorialspoint.com/scala/scala_access_modifiers.htm</a></div></div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature">  -- Howard.<br></div></div>
<br><div class="gmail_quote">On 29 March 2016 at 07:30, Jordan Rose via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><blockquote type="cite"><div>On Mar 28, 2016, at 11:40, Ilya Belenkiy &lt;<a href="mailto:ilya.belenkiy@gmail.com" target="_blank">ilya.belenkiy@gmail.com</a>&gt; wrote:</div><br><div><div dir="ltr"><span><span>&gt; I </span><i>still</i><span> don&#39;t understand your reasoning here. If a private member can be used in a member function, and in closures inside that member function, why can&#39;t it be used in a member type?</span></span><div><br></div><div>The simplest answer is that it&#39;s the most private access level, and also one that doesn&#39;t create any confusion. We already discussed several times here whether inner should have access to outer or the other way around. With this design, the answer is neither.</div><div><br></div><div>A longer answer is that if you move a function into a type and make it a member function, you change the semantics. It&#39;s no longer the same function. If you move the type inside another type, the semantics is the same. The only difference is that we get shorter names. Also, if you move a function to be a member function, that changes the class API. If you move a class to become a nested class, that does not change the outer class API. Both classes can be used the same way but with different spelling of the name of the inner class.</div><div><br></div><div>Also, I think that the terminology of access level really comes from OOP. The problem with the current state of things is that it mixes this terminology with export levels. This proposal makes &quot;private&quot; mean what it means in OOP and extends it so that it makes sense with Swift extensions.</div><div><br></div><div>If we were talking about &quot;scoped&quot; level access, the immediate scope addition would be wrong. But if we are talking about &quot;private&quot;, it&#39;s a different matter.</div></div></div></blockquote><br></div><div>I don&#39;t buy this argument. Before Swift, there have been plenty of OO languages with extensions and plenty with access control, but no major ones with both except Ruby (discounting Objective-C&#39;s @private instance variables). And, ignoring extensions, the behavior of &#39;private&#39; in all of these languages is to include access from member types:</div><div><br></div><div>- C++: yes</div><div>- Java: yes</div><div>- C#: yes</div><div><br></div><div>- Ruby: no, but even the outer class can&#39;t invoke private methods on a different instance of itself</div><div>- D: yes, but D&#39;s &quot;private&quot; is closer to Swift&#39;s current &quot;private&quot; than anything else</div><div><br></div><div>- Kotlin: yes</div><div>- Scala, Python, Go, Rust, Objective-C, Smalltalk: either no access control or no nested types, AFAICT</div><div><br></div><div>So &quot;private&quot; in these languages doesn&#39;t seem to mean &quot;restricted to this type&quot;, and that shouldn&#39;t be considered the &quot;obvious&quot; meaning when several of us have considered it decidedly non-obvious.</div><div><br></div><div>Best,</div><div>Jordan</div><div><br></div><div>P.S. &quot;If you move the type inside another type, the semantics is the same.&quot; This already isn&#39;t true if the new member type is used to satisfy a protocol requirement (which, because of retroactive modeling, counts as &quot;changing the class&#39;s API&quot;), but it especially won&#39;t be true if/when we start allowing member types inside generic types. In that case, the inner type now has extra generic parameterization that it wouldn&#39;t have had before.</div><div><br></div><div>P.S. Extensions do make things a little more complicated, but again, there&#39;s almost no precedent here, and pretty much everyone agrees that this new scope-private access level shouldn&#39;t give access to extensions. That also means there&#39;s an option to keep yourself from accidentally accessing scope-private members in a member type: put the member type in an extension.</div></div><br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>