<div dir="ltr">&gt; I believe that view is mistaken. Swift has a very opinionated view of how code should be organized into files; <div><br></div><div>If that is true, Swift should enforce it. Right now it doesn&#39;t, so this is open to interpretation.</div><div><br></div><div>&gt; they are as semantically meaningful as declaration blocks.<br></div><div><br></div><div>Agreed. Which is why some people may want to group related code into the same file but still want to hide implementation details at the scope level.</div><div><br></div><div>&gt; The purpose of a file is to implement one concern—essentially, one logical piece of the module&#39;s functionality with its own self-contained implementation details. A concern is not necessarily fully represented by a single type; a type may include several concerns, and several types may implement one concern. (It&#39;s not a coincidence that a file can contain several types and a type can be split across several files.) The precise boundaries of a concern are a little nebulous, especially when you build convenience APIs which don&#39;t depend on anything private, but it&#39;s usually roughly clear what they are.<br></div><div><br></div><div>&quot;concern&quot; is a very vague term. Implementation details of a type and hiding of its internal state and internal helper functions is much more concrete. The model that you describe is very good about sharing implementation details of several classes and hiding them as a whole. It&#39;s a good alternative to C++ &quot;friend&quot;. However, this model doesn&#39;t work well for hiding implementation details and protecting invariants of a single type. Most types and their extensions are small, and creating files for every single one of them only to hide implementation details is very impractical. For example, most people just put all extensions of one type in one file for convenience. Carefully separating every scope and protecting its implementation details in a separate file is very tedious. It&#39;s like putting every paragraph of a chapter in a separate file. I haven&#39;t seen anyone do it. Instead, people just forgo access control altogether or, at best, provide much more access than they really mean to.</div><div><br></div><div>&gt; When you want to use `local`, that usually means you&#39;re not organizing your code the way Swift thinks you should. It&#39;s no wonder Swift seems to not be expressive enough: You&#39;re fighting the language.<br></div><div><br></div><div>Or maybe the language is fighting me :–) If this was C, and the issue was to protect internal global variables, this reasoning would be true. But with types, most of the time, invariants and internal state exist at the type level, and right now there is no direct way of protecting them. Using files for this purpose is very indirect, and the meaning is open to interpretation. For example, another review compares access levels with exports. Semantically they are not the same, even if the end result is hidden APIs. Scoped level access is very clear, direct, and natural for anyone new to the language and expresses a very important concept.</div><div><br></div><div>&gt; The first: Sometimes Swift will not allow you to move certain things to separate files; for instance, only one file can declare stored properties on a type, and so stored properties must either be made more visible than they should be, or several concerns must be mixed into a single file. I think this is best handled by allowing extensions to declare stored properties and other such one-file-only constructs, rather than by complicating access control.</div><div><br></div><div>I think that stored properties in extensions would be a great addition to the language, but it has nothing to do with access level. If / when Swift gains this feature, hiding these stored properties in the scope of the extension would be just as important as it is now for stored properties. Exactly the same logic applies to extensions.</div><div><br></div><div><span>&gt; The second: Sometimes a particular concern has an especially complicated, self-contained &quot;sub-concern&quot; which has implementation details of its own. You would like to keep the sub-concerns implementation details private from the containing concern, but the sub-concern is *itself* an implementation detail of the containing concern, so you *also* want to keep the sub-concern private from other, unrelated concerns. In these cases, some sort of more nuanced access control would be better—but even then, I don&#39;t think `local` is actually a very good way to do it.<br></span></div><div><br></div><div>I am surprised by this -- it&#39;s exactly the kind of problem that &quot;scoped&quot; solves, and very directly. Why wouldn&#39;t it be a good way to do it?</div><div><br></div><div>&gt; There&#39;s nothing about a declaration block that makes it a natural choice for scoping declarations. `local` hides the declaration from containing and sibling declaration blocks and exposes it to nested declaration blocks. But if concerns often transcend type boundaries, surely sub-concerns do as well, so `local` will often be either too limiting or not limiting enough.<br></div><div><br></div><div>&quot;concern&quot; is a very vague term, but I think that most of the time, &quot;concern&quot; spans one type -- it protects internal state and internal APIs that may manipulate that state in an unsafe way or make some assumptions that are generally not true. &quot;scoped&quot; provides a very clear expression of intent for this very common case. Most of the time, &quot;friend&quot; in C++ is not needed. Similarly, most of the time, &quot;private&quot; could be replaced by &quot;scoped&quot;. Internal APIs that span several types are exceptions, not the rule.</div><div><br></div><div><span>&gt;       • Does this proposal fit well with the feel and direction of Swift?<br><br>&gt; I don&#39;t think so. Swift has strong, opinionated ideas about how code should be organized; this proposal doesn&#39;t follow that pattern.<br></span><br></div><div>It actually does:</div><div>public -- visible outside of module</div><div>internal -- visible in all files</div><div>private -- visible in one file</div><div>scoped -- visible in part of a file</div><div>for the sake of the argument, we could add</div><div>micro -- visible on one line</div><div><br><div class="gmail_quote"><div dir="ltr">On Mon, Feb 29, 2016 at 5:45 AM Brent Royal-Gordon 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">&gt; <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md" rel="noreferrer" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md</a><br>
<br>
&gt;       • What is your evaluation of the proposal?<br>
<br>
I don&#39;t think it&#39;s a good idea.<br>
<br>
I think the source of our disagreement is expressed in this paragraph from the proposal:<br>
<br>
&gt; It forces a one class per file structure, which is very limiting. Putting related APIs and/or related implementations in the same file helps ensure consistency and reduces the time to find a particular API or implementation. This does not mean that the classes in the same file need to share otherwise hidden APIs, but there is no way to express it with the current access levels.<br>
<br>
This reflects a view that grouping APIs into files is a purely stylistic choice. You can move APIs around freely and organize them however you like. If Swift gets in the way of your preferred arrangement, Swift should be changed to allow it. The most important thing is that you be free to express yourself artistically through the medium of the file system.<br>
<br>
I believe that view is mistaken. Swift has a very opinionated view of how code should be organized into files; they are as semantically meaningful as declaration blocks.<br>
<br>
The purpose of a file is to implement one concern—essentially, one logical piece of the module&#39;s functionality with its own self-contained implementation details. A concern is not necessarily fully represented by a single type; a type may include several concerns, and several types may implement one concern. (It&#39;s not a coincidence that a file can contain several types and a type can be split across several files.) The precise boundaries of a concern are a little nebulous, especially when you build convenience APIs which don&#39;t depend on anything private, but it&#39;s usually roughly clear what they are.<br>
<br>
When you want to use `local`, that usually means you&#39;re not organizing your code the way Swift thinks you should. It&#39;s no wonder Swift seems to not be expressive enough: You&#39;re fighting the language.<br>
<br>
Now, there are two exceptions to this general rule, but I think they&#39;re both best handled in other ways.<br>
<br>
The first: Sometimes Swift will not allow you to move certain things to separate files; for instance, only one file can declare stored properties on a type, and so stored properties must either be made more visible than they should be, or several concerns must be mixed into a single file. I think this is best handled by allowing extensions to declare stored properties and other such one-file-only constructs, rather than by complicating access control.<br>
<br>
The second: Sometimes a particular concern has an especially complicated, self-contained &quot;sub-concern&quot; which has implementation details of its own. You would like to keep the sub-concerns implementation details private from the containing concern, but the sub-concern is *itself* an implementation detail of the containing concern, so you *also* want to keep the sub-concern private from other, unrelated concerns. In these cases, some sort of more nuanced access control would be better—but even then, I don&#39;t think `local` is actually a very good way to do it.<br>
<br>
There&#39;s nothing about a declaration block that makes it a natural choice for scoping declarations. `local` hides the declaration from containing and sibling declaration blocks and exposes it to nested declaration blocks. But if concerns often transcend type boundaries, surely sub-concerns do as well, so `local` will often be either too limiting or not limiting enough.<br>
<br>
To properly handle this problem, we would be better off coming up with some way to limit the scope of `internal` to only particular files which need to interface with that file&#39;s concern. `internal` would expose the API to your file&#39;s &quot;clients&quot;—by default all files in the module, but potentially narrowed down to a particular subset—while `private` would remain as something truly limited to a single file.<br>
<br>
However, that approach is rather complicated, bordering on the horror of C++ `friend` declarations. Ultimately, I just don&#39;t think it&#39;s too large of a burden to say, &quot;You have a three-level namespace, and anything that crosses files goes into `internal`; if something in `internal` is only meant to be used in a particular file, show some discipline.&quot;<br>
<br>
&gt;       • Is the problem being addressed significant enough to warrant a change to Swift?<br>
<br>
As I often say, the problem is arguably significant enough, but I don&#39;t think the solution is the right one.<br>
<br>
&gt;       • Does this proposal fit well with the feel and direction of Swift?<br>
<br>
I don&#39;t think so. Swift has strong, opinionated ideas about how code should be organized; this proposal doesn&#39;t follow that pattern.<br>
<br>
&gt;       • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?<br>
<br>
I&#39;ve used languages with file-based scoping, and languages with arbitrary lexical scoping, but not languages with both.<br>
<br>
&gt;       • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?<br>
<br>
In addition to reading the present proposal, I also participated fairly extensively in discussions about it and read previously-posted reviews.<br>
<br>
--<br>
Brent Royal-Gordon<br>
Architechies<br>
<br>
_______________________________________________<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>