<div dir="ltr">Code organization of having most methods in extensions would not work for extensions that need access to internal state marked with &quot;scoped&quot;. For this specific use case, one class per file + &quot;private&quot; works perfectly. This code organization makes sense for very large classes but not for smaller and related classes.<div><br></div><div>That said, I think that even in this case, &quot;scoped&quot; would help with hiding helper methods that are necessary to implement protocols but are useless in other places in the same file.</div><div><br></div><div>I do think that the name &quot;private&quot; is an unfortunate choice because it means something else in other mainstream languages, but the access level that it provides is very useful and a much better alternative than &quot;friend&quot; in C++. However, we still need &quot;scoped&quot; (private in C++) to declare and enforce encapsulation at the scope (class or extension) level.</div><div><br><div class="gmail_quote"><div dir="ltr">On Sat, Feb 27, 2016 at 10:27 AM plx via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div><div style="word-wrap:break-word"><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li>What is your evaluation of the proposal?</li></ul></div></div></blockquote></div></div><div style="word-wrap:break-word"><div><div>Short form: the problem addressed is very real and IMHO very significant; the proposed solution is *useful* but on reflection seems to illustrate this isn’t a problem that can be *entirely* addressed just by adding another scope (or scope(s)). I think I agree with what I think Drew has been saying that the visibility model itself may be not quite ideal (it isn’t broken or anything). </div><div><br></div><div>I’m also a little unsure how useful `local` will be in the context of the rest of the language at this time; it seems like to really come into its own we’d also want e.g. to be able to split up the definition of a type across multiple extensions within the same module.</div><div><br></div><div>Longer form: within Swift’s existing access-control approach, if you want to keep things private—as opposed to merely internal—it’s easy to wind up with numerous closely-related types, all living in the same file. The only sensible visibility for most of the aspects of most of the types is `private`, but because these are all living in the same file we don’t actually get any effective &quot;cross-type” access-protection within that file.</div><div><br></div><div>So e.g. for a custom type implementing `CollectionType`, you can have the type itself, an associated index type, and perhaps also an associated generator type; if instead of “is-a `CollectionType`” you instead opt for “has-multiple `CollectionType` views”, then you can wind up with the base type + 2-3 closely-related types per such view (the collection type, its index, and perhaps also the generator).</div><div><br></div><div>The standard-library `String` is an example, where it’s not itself a collection but has 4 “views”, each of which defines an index, and one of which also adds a custom generator.</div><div><br></div><div>I don’t have a short example I can share, but I can describe one: at one point I wrote an “accelerated 2D point array”, which was effectively an array of `CGPoint`, but in struct-of-arrays style (e.g. separate arrays of `x` and `y` coordinates). The tricky part is it had a delicate internal state, since the actual storage looked like this (many details elided here) :</div><div><br></div><div>@implementation PointArray {</div><div>  float *_bufferA;</div><div>  float *_bufferB;</div><div>  float *_bufferC;</div><div>}</div><div><br></div><div>@property(nonatomic, assign) PointArrayState state;</div><div><br></div><div>@end</div><div><br></div><div>…wherein *which* buffer was for `x` or `y` varied over time (and was tracked via that `state` field). The reason for this design is many of the array-level operations were implemented using functions from Accelerate, which in turn often benefit from being done “out-of-place” (and thus e.g. to translate each point by dx,dy, if you started out with `bufferA` having the x-coordinates and `bufferB` having the y-coordinates, you might wind up with `bufferC` holding the updated x-coordinates and `bufferA` holding the updated y-coordinates, along with `state` updated to reflect that updated arrangement).</div><div><br></div><div>This is code that would arguably benefit from being migrated to Swift at some point. As it is in Objective-C, it’s implemented as part of a larger family of classes, and it’s easy to tightly control visibility: there’s public headers, there’s private headers imported by subclasses, and there’s methods defined in .m files that are difficult to call accidentally from anywhere else. </div><div><br></div><div>In Swift the design would change a bit — a lot of methods that in Objective-C are effectively “sort if necessary, then call this block on each point” would get migrated to “view structs” that implement `CollectionType` — but I get nervous thinking through the implementation because it seems at least a little awkward to structure the internal API in a robust way, while also having so many types all defined in the same file.</div><div><br></div><div>I’m not entirely sold that `local` is the ideal solution, but it’s definitely addressing an IMHO significant problem.</div><div><br></div><div>What does concern me about `local` is that, at present, it would seemingly force an unnatural code organization at times; the norm is typically to put each adopted protocol into its own extension, but this means that any stored fields must either be `private` — and thus not protected by `local` — or you have to implement a lot of things from within the main definition (not idiomatic).</div><div><br></div><div>Even then, consider a simple case like this:</div><div><br></div><div>public struct SomeCustomIndex&lt;T&gt; {</div><div>  local let position: Position</div><div>}</div><div><br></div><div>public func ==&lt;T&gt;(lhs: SomeViewIndex&lt;T&gt;, rhs: SomeViewIndex&lt;T&gt;) -&gt; Bool {</div><div>  return lhs.position == rhs.position // oops!</div><div>}</div><div><br></div><div>…(in this case it’s hard to see what harm you could do with `private let position`, but it illustrates a general limit to the utility of `local` declarations).</div></div></div><div style="word-wrap:break-word"><div><div><br></div><blockquote type="cite"><div><div style="word-wrap:break-word"><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li>Is the problem being addressed significant enough to warrant a change to Swift?</li></ul></div></div></blockquote></div></div><div style="word-wrap:break-word"><div><div>Yes, VERY MUCH SO.</div></div></div><div style="word-wrap:break-word"><div><div><br></div><blockquote type="cite"><div><div style="word-wrap:break-word"><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li>Does this proposal fit well with the feel and direction of Swift?</li></ul></div></div></blockquote></div></div><div style="word-wrap:break-word"><div><div>I’m not sure. I feel like there should be some better approach to visibility that solves this problem and is overall more “Swift”, but I don’t know what it is.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li>If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?</li></ul></div></div></blockquote></div></div><div style="word-wrap:break-word"><div><div>I think the closest analogy here is that &quot;private + local&quot; are trying to get Swift to the same place that, say, “protected + friend” would get it, but along a different route.</div><div><br></div><div>The general problem being solved is that Swift’s somewhat-unique approach to `private` is unsatisfactory for some cases—IMHO in particular for the “family of related types” scenario—and `local` adds another tool to solve it.</div><div><br></div><div>Although I’m well aware of the arguments against “protected (+ friend)”, I’d point out that those constructs are IMHO the *usual* approach to solving these same issues.</div></div></div><div style="word-wrap:break-word"><div><div><br></div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li>How much effort did you put into your review? A glance, a quick reading, or an in-depth study?</li></ul></div></div></blockquote></div></div><div style="word-wrap:break-word"><div></div><div>Read the proposal, participated in original discussion, read the current discussion.</div><br></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">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>
</blockquote></div></div></div>