On Tue, Mar 21, 2017 at 8:31 PM, Matthew Johnson <[email protected]> wrote:
> > > Sent from my iPad > > On Mar 21, 2017, at 7:40 PM, Xiaodi Wu via swift-evolution < > [email protected]> wrote: > > On Tue, Mar 21, 2017 at 6:44 PM, Drew Crawford <[email protected]> > wrote: > >> I am confused by this response. An argument in _support_ of new `private` >> was that it is more in line with expectations of users coming from other >> languages. In other some cases, such an argument might have its place. >> However, as others have pointed out on this list, those other languages >> don't have facilities like Swift's extensions, and therefore it was not a >> very strong argument for new `private` to say that it better aligns with >> user expectations coming from other languages. >> >> The underlying issue here (which I have now identified, thanks!) is what >> motivates the use of extensions. That question predates proposals, but the >> Swift book provides the following motivation, which I have numbered for >> ease of reference: >> >> 1. Extensions add new functionality to an existing class, structure, >> enumeration, or protocol type. >> >> 2. This includes the ability to extend types for which you do not have >> access to the original source code (known as retroactive modeling). >> >> 3. Extensions are similar to categories in Objective-C. >> >> It seems to me this motivation contemplates use “at some distance”, that >> is we intend to create some semantically meaningful separation between the >> declaration and the extension(s). If we did not we could use MARK or some >> other comment-based scheme to organize our class. >> >> 2 is explicitly at great distance, so we know the distance motivation is >> well within scope. 1 refers to “an existing” type which implies a certain >> level of functionality in the unextended type, and not merely a partial >> implementation in the unextended type. The record on 3 is more mixed (ObjC >> programmers do occasionally use categories “closely-held” to group a few >> methods together). However ObjC also has the “distance” tradition: >> categories cannot introduce new storage even when this is technically >> trivial (within the same compilation unit for example), and this tradition >> was continued under Swift with the new ABI. >> >> What I am suggesting is that the primary design purpose of an extension >> is to create semantic distance between a declaration and the functionality >> being added. >> > > I'm not sure it is necessary for extensions to have a "primary design > purpose." They serve many purposes. One use I have for them is as follows: > > ``` > struct A { > // Stuff here constitutes the "raison d'etre" for A. > } > > extension A : B { > // In the course of implementing `A`, I have discovered that > // `A` can fulfill the semantic guarantees of `B`, and in fact > // fulfills most of them already. > // > // So, I conform to B, as in so doing there are some practical > // advantages, such as gaining some default implementations. > // > // But, to conform, I may need to implement some methods > // not really essential for a functional `A`, but required nonetheless > // to conform to `B`. > // > // I implement them here in an extension; in so doing, I express > // the idea that I have, after implementing `A`, discovered its > // conformance to `B`, and I am here supplying the remaining > // implementations necessary for that conformance. > // > // That is, if `B` did not exist, neither would these functions here. > // But there may be some requirements of `B` that would be > // implemented in `A` whether or not `B` exists. > // Those are implemented above, in `struct A { ... }`. > } > ``` > > I find this to be an eloquent way to separate concerns. It is a common > pattern encouraged by code I admire written by others more skilled than me > in Swift. > > A mechanism to hide variables from extensions is something that *furthers* >> this design goal of extensions, rather than contradicts it. >> > > This, I suppose, is an argument for you to take up with Charles. > > >> I understand that some people use extensions as sort of an imitation >> “partial class” but they simply aren’t (no storage) and we should introduce >> a new feature if we want to have them. >> >> A core team member (I'm blanking on who) has pointed out that, in the >> end, the only necessary access modifiers are public and not public (spelled >> "internal" in Swift). >> >> >> It is not clear to me how this squares with the decision in SE-0025 that >> other access modifiers were necessary. Can you clarify? >> > > Why do you think SE-0025 decided that other access modifiers are > necessary? It merely decided that having four was deemed, on balance, > superior to having three. But the minimum number of access modifiers is, by > definition, two. In the case of Swift those essentially have to be at the > module boundary. Anything more finely diced than that and you are balancing > expressivity and complexity. I would not be opposed, incidentally, to > stripping back access modifiers to two: `internal` (or maybe eliminate that > explicit annotation altogether) and `public`. > > When new `private` and `fileprivate` were shipped, there were numerous >> questions asked by users on forums such as Stack Overflow >> >> >> And before they were shipped, there were people asking for a scoped >> modifier. >> > > No, I'm not talking about "asking for"; I'm talking about "asking"--as in, > "I don't get it, please explain." The point is that the distinction between > `private` and `fileprivate` is not an intuitive one. > > >> And when we change them again, what questions will that generate? So I >> don’t see what we are accomplishing with this line of inquiry. >> >> You see the new access modifiers described, for example, as something >> that "take[s] some getting used to." Rather damning as a euphemism, don't >> you think? >> >> Not at all. We could describe strong typing, or optionals, enums, >> pattern matching, etc., in this way. ARC in particular is “difficult to >> teach” but we should not get rid of it, it solves a safety problem. A >> scoped access modifier is similar. >> > > Again, the argument is not that scoped access modifiers have _no_ merits > or that it solves _no_ problems; it is that its merits are greatly > outweighed by its drawbacks, or that the problems solved are not more > pressing than the problems introduced, which include problems in learning > and teaching Swift. > > Swift promises only one type of safety by default: memory safety. ("Swift > is a high-performance system programming language. It has a clean and > modern syntax, offers seamless access to existing C and Objective-C code > and frameworks, and is memory safe by default.") > > Since ARC helps to deliver two indispensable promises ("seamless access > to...Objective-C" and "memory safe by default"), that weighs heavily in its > favor despite difficulty of learning and teaching. `fileprivate` is, I > think you'll agree, certainly not a clean and modern syntax, and its > presence or absence has little to do with the other tentpole promises of > Swift. > > When the Swift core team approved the proposal, they expressed the belief >> that `fileprivate` would be rarely used. This has turned out plainly and >> indisputably not to be true. It is clear that they expected Swift to have, >> after SE-0025 (and before `open`), three commonly used access modifiers and >> one vestigial one. Instead we have four/five commonly used access >> modifiers. Thus, the complexity of the current system is _not_ what was >> envisioned at the time of approval for SE-0025, and the resulting system >> should be re-evaluated in light of this real-world data. >> >> The only citation I can find on this topic is the cryptic “fileprivate >> is rarely needed >> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160328/013829.html>” >> in the context of “rare enough to be explicit”. I submit that according >> to previously-presented data, I do use it rarely, less often than the other >> modifiers, certainly in a manner consistent with being explicit. I do not >> see how we jump from that fact pattern to “plainly and indisputably… _not_ >> what was envisioned at the time”. It is not plain and I do dispute it. >> > > *You* may indeed write in a style that uses it rarely. I think you see > from even this conversation that others do not code in such a style. There > are 183,000 results for `fileprivate` on Google, which is in the same > ballpark as results for `associatedtype`. Compare with 60,800 for > `precedencegroup` and 1430 for `ExpressibleByStringInterpolation`. > > The code above should compile and does not. >> >> It is not clear to me how this is especially relevant. The point of a >> scoped access modifier is to prevent programs from compiling when they >> should not. Here is a program that does not compile when it should; that’s >> a bug, but it doesn’t go to whether the scoped people are caught with their >> pants down or working from bad safety assumptions. It’s just a complier >> crasher. >> > > It is relevant because this is not some corner case; it's not some fuzzed > nonsense like `{{<<var;;` that happens to crash the parser. It is a > tentpole feature of `private` proposed in SE-0025 that shipped broken in > 3.0 and will ship broken in 3.1. In other words, SE-0025 has not been > completely implemented, and if ABI stability is declared before it is > fixed, it may not even be completely implementable. > > >> (a) even proponents of new `private` disagree on one of two key goals >> stated for new `private`; >> >> I suspect that not everyone will agree on the three stated goals for >> extensions either, but I do not with to remove them. >> > TSPL is not the document of record for goals for extensions, it's a > pedagogical tool. By contrast, SE-0025 is the document of record for goals > for the new `private`. They may not be *your* goals for `private`, but they > are *the Swift community's* goals for `private`, and they have not been met. > >> I wish to improve them, and a scoped access modifier is one of the tools >> we have to do that. >> >> As far as I can see, in that example, you can rename `private func prune` >> to `private func _prune` and have no further problems. That is to say, the >> workaround is a single character at each use site, which by your metric >> makes this proposal half as onerous as removing `++`. >> >> The problems are described in SE-0025: >> >> > Another, less reliable, way is to prefix APIs that are meant to be >> hidden with a _ or do something similar. That works, but it’s not enforced >> by the compiler, and those APIs show up in tools like code completion, so >> the programmer has to filter out the noise — although these tools could >> quite easily support hiding methods with the _ prefix standard. Also, there >> is a greater danger of using private APIs if they do something similar to >> public APIs but are somehow more optimized (because they make additional >> assumptions about the internal state). >> >> In any case, this workaround is not “semantically equivalent” and so >> regardless of the number of characters it is different than ++ or var. >> > I'm not sure how the quotation describes a semantic issue; it describes a > practical drawback with respect to code completion. And it's correct. > Again, I'm not saying that there are no merits to a scoped access level. > I'm just saying that a tidier code completion menu and not writing `_` > aren't in themselves compelling. The workaround after removal is totally > transparent to the end user, and all uses of a non-public API in the same > file can be trivially audited to prove that they aren't called at > unintended places, so I'm not sure why you think some bar of "semantic > equivalence" needs to be met. > > > Uses in a single file at a single point in time can be audited trivially. > Ensuring correct use all (scope)private variables in all files of a large > project over a span of years is not so trivial. This kind of mistake can > slip through code review even on diligent team. The compiler guarantee has > significant value in these contexts. > Certainly, I'm not arguing that it doesn't have its benefits. But if it slips through code review, what goes wrong? And couldn't this be enforced by a linter feature that warns if a private member beginning with _ is accessed outside of scope? > >> On March 21, 2017 at 5:26:47 PM, Xiaodi Wu ([email protected]) wrote: >> >> On Tue, Mar 21, 2017 at 3:59 PM, Drew Crawford via swift-evolution < >> [email protected]> wrote: >> >>> The arguments for the revert are in the proposal and in the discussions >>> in this thread. >>> >>> >>> What is in the proposal and this thread are a set of opinions, e.g. >>> >>> * "the access level change of SE-0025 was met with dissatisfaction by a >>> substantial proportion of the general Swift community." >>> * "Those changes can be viewed as actively harmful,” >>> * "it is extremely common to use several extensions within a file.” >>> * “[existing regime] encourages overuse of scoped access control” >>> * “[fileprivate is the] more reasonable default” >>> >>> I am asking for the arguments or evidence that led you or others to >>> these opinions. I understand that you and others believe them, but you >>> understand that they are now a matter of debate. We are not going to reach >>> any mutual understanding just asserting things we believe. The underlying >>> evidence is what would be necessary to convince others to our point of >>> view. I am trying to ascertain what that evidence is. >>> >>> > It has pointed quite a few times by core team members that comparison >>> to languages is not a very strong arguments, >>> >>> >>> The context here is that you presented an argument that Swift’s >>> “private” was confusing to users of other languages: >>> >>> > In most languages, that keyword is “private” so its valid to say that >>> newcomers to the language will “default” to using that one. >>> >>> If you no longer think that argument is strong because it relies on a >>> comparison to other languages, then we agree :-) But in that case we lose >>> an argument for this proposal. The reason we are talking about other >>> languages is because that was an argument advanced to support the proposal. >>> >>> >> I am confused by this response. An argument in _support_ of new `private` >> was that it is more in line with expectations of users coming from other >> languages. In other some cases, such an argument might have its place. >> However, as others have pointed out on this list, those other languages >> don't have facilities like Swift's extensions, and therefore it was not a >> very strong argument for new `private` to say that it better aligns with >> user expectations coming from other languages. >> >> >>> > Some people used the for(;;) loop, the ++ operator, var parameters. >>> >>> >>> In those cases, there was extensive discussion of how to achieve the >>> things people were achieving with those features with alternative patterns. >>> var parameters for example have a 1LOC workaround to achieve the previous >>> semantics, ++ had two characters, for(;;) was slightly trickier but we had >>> a clear concept of the scope of the impact. So far as I’m aware, the only >>> suggestion to people who currently use a scoped access modifier is to stop >>> having their problems. >>> >> >> You've given one example of code that takes advantage of new `private`. >> As far as I can see, in that example, you can rename `private func prune` >> to `private func _prune` and have no further problems. That is to say, the >> workaround is a single character at each use site, which by your metric >> makes this proposal half as onerous as removing `++`. >> >> So the circumstances of earlier removals and this one are very different. >>> >>> > • either a programmer ... will use private as often as possible >>> > • or a programmer will … use fileprivate all the time >>> >>> There is also the possibility that a programmer considers which modifier >>> is appropriate for the code they are writing. You "argue that... is very >>> rare” but I still am not sure what this argument is or what led you or >>> others to this conclusion. >>> >> >> I'm not enamored of the argumentation in the proposal set out above. But >> since you are saying that you're not sure how anybody came to support this >> proposal, here's how I arrived at supporting it: >> >> A core team member (I'm blanking on who) has pointed out that, in the >> end, the only necessary access modifiers are public and not public (spelled >> "internal" in Swift). It has been my understanding that supporting all >> possible ways of hiding a member from arbitrary other code within the same >> module is a _non-goal_. There have been numerous attempts at designing >> elaborate access modifier schemes that make this possible with friends, >> protected, shared, what-have-you, and I try to bring up this point each >> time. >> >> Beyond the two absolutely essential access modifiers, anything else does >> not add to safety as the term is understood in Swift, but rather improves >> developer experience. But what is gained in terms of developer experience >> with each additional access modifier (due to increased expressiveness) is >> offset by what is lost due to complexity. So then the question is: what is >> the ideal number of access modifiers? is it two? three? four? five? six? >> eight? ten? twelve? >> >> When new `private` and `fileprivate` were shipped, there were numerous >> questions asked by users on forums such as Stack Overflow (easily googled; >> just as a single example: http://stackoverflow. >> com/questions/39027250/what-is-a-good-example-to-differentia >> te-between-fileprivate-and-private-in-swift), on blogs (again, easily >> googled; as a single example: https://useyourloaf.c >> om/blog/swift-3-access-controls/), and messages to this list (including >> from people not part of the original discussion but who, on using the >> feature, found it irksome enough to join the list and make their voice >> heard). >> >> You see the new access modifiers described, for example, as something >> that "take[s] some getting used to." Rather damning as a euphemism, don't >> you think? Certainly not a ringing endorsement-- >> >> "How do you like my new haircut?" >> "It, um, takes some getting used to." >> >> Others also wrote to say that they were finding it difficult to *teach* >> this new scheme to students; you can find such messages in the list >> archives. I take this to mean that having four/five access modifiers >> (depending on whether you consider `open` to be an access modifier) to be >> one too many. >> >> When the Swift core team approved the proposal, they expressed the belief >> that `fileprivate` would be rarely used. This has turned out plainly and >> indisputably not to be true. It is clear that they expected Swift to have, >> after SE-0025 (and before `open`), three commonly used access modifiers and >> one vestigial one. Instead we have four/five commonly used access >> modifiers. Thus, the complexity of the current system is _not_ what was >> envisioned at the time of approval for SE-0025, and the resulting system >> should be re-evaluated in light of this real-world data. >> >> So, if four/five access modifiers are too many, which one is carrying the >> least weight? Which one could be removed to simplify the scheme while >> maintaining the most expressiveness? Which one doesn't fulfill even its own >> stated goals? Well, one of the key goals of `private` was to allow members >> to be encapsulated within an extension, hidden even from the type being >> extended (and vice versa for members defined in the type). It says so in >> the first sentence of SE-0025. As seen above in my discussion with Charles >> Srstka, even supporters of `private` disagree with that motivation to begin >> with. The kicker is, _it also doesn't work_. Try, for instance: >> >> ``` >> >> struct Foo { >> >> private var bar: Int { return 42 } >> >> } >> >> >> extension Foo { >> >> private var bar: Int { return 43 } >> >> } >> ``` >> >> The code above should compile and does not. If I understood correctly the >> explanation from a core team member on this list, it's unclear if it can be >> made to work without changing how mangling works, which I believe impacts >> ABI and is not trivial at all. Thus, (a) even proponents of new `private` >> disagree on one of two key goals stated for new `private`; (b) that goal >> was never accomplished, and making it work is not trivial; (c) no one even >> complained about it, suggesting that it was a low-yield goal in the first >> place. >> >> So, I conclude that new `private` needs re-evaluation in light of >> real-world implementation and usage experience. I haven't even mentioned >> the nuances of `private` in one scope being different from `private` in the >> containing scope, requiring distinguishing of effective access levels from >> nominal ones--just one more wrinkle in this whole scheme. I feel that >> allowing someone to write `private var foo` instead of `private var _foo // >> don't call this outside the type`, when that member isn't vended and can't >> be seen outside the file anyway, is a tiny win in comparison to the huge >> complexity both of implementation (it's still not correctly implemented and >> may not be in time for Swift 4!!!) and of usage. >> >> >> On March 21, 2017 at 1:41:48 PM, David Hart ([email protected]) wrote: >>> >>> >>> >>> >>> >>> Sent from my iPhone >>> On 21 Mar 2017, at 16:57, Drew Crawford <[email protected]> wrote: >>> >>> >>> >>> > I’m not arguing that it is less or more than a majority. I’m just >>> saying that we’ve seen a lot of talk against the original change. >>> >>> This proposal asks us to balance the convenience of one group >>> (extension-writers) against the existence of another (scoped-access >>> users). To do that, we need a clear idea of the composition of both groups. >>> >>> “A lot of talk” is not the evidentiary standard to remove a feature. It >>> was not good enough when we introduced the feature, that required argument >>> and clear use-cases. >>> >>> "A lot of talk" is not the evidence supporting the proposal: it's just a >>> warning that something may be very controversial among the community. The >>> arguments for the revert are in the proposal and in the discussions in this >>> thread. >>> >>> > By default, I did not mean the syntactic default of the language but >>> the access modifier users will use “by default” when trying to restrict >>> visibility. In most languages, that keyword is “private” so its valid to >>> say that newcomers to the language will “default” to using that one. >>> >>> Apologies, but I do not understand the argument: >>> >>> 1. A user wants to restrict visibility (e.g. they are dissatisfied >>> with “internal”) >>> 2. The user *chooses* private because of familiarity from another >>> language >>> 3. The user is then surprised that their choice of private indeed >>> restricted the visibility, thus achieving their goal? >>> >>> What language does the user come from in which “private” is >>> file-visible? It isn’t Java, C++, or PHP. C#’s “partial” is the closest I >>> can think of, and it isn’t at all close. >>> >>> >>> It has pointed quite a few times by core team members that comparison to >>> languages is not a very strong arguments, especially when Swift does things >>> differently for a good reason. I can't stop from quoting Xiaodi from a >>> month back: >>> >>> «The beauty of Swift 2's access modifiers was that they were based >>> around files and modules, explicitly rejecting types and scopes as units >>> for determining visibility.» -- Xiaodi >>> >>> A user who wants a middle-ground visibility would “default” to >>> “protected”, “friend”, “partial”, or similar. After that does not compile, >>> they will use google to find a middle-road visibility keyword, for which >>> the only candidate is “fileprivate”. But they will not choose “private”, >>> it’s just not a reasonable expectation of what the keyword means to a new >>> Swift developer. >>> >>> The popularity of private “as a default” is simply because many users >>> prefer to hide their implementation details as a matter of routine code >>> hygiene. Redefining private in order to thwart their code hygiene goal >>> seems extreme. >>> >>> >>> The point is that keeping both private and fileprivate feels like an >>> un-necessary complication: >>> >>> • either a programmer falls on your side of the fence and will use >>> private as often as possible and relegate to fileprivate when the design >>> leaves no other choice. At that point it feels like a language wart. >>> • or a programmer will fall on my side of the fence and use fileprivate >>> all the time and the language feels like it has an unnecessary access >>> modifier. >>> >>> I'd argue that the cases when a programmer will use both meaningfully is >>> very rare. As a consequence, we should try to only keep one. Removing >>> fileprivate is a no-go with extensions so that leaves us with removing >>> private. >>> >>> I agree with several here (as I did in SE-0025) that our access >>> modifiers are not well-named. However, that’s not the proposal in front of >>> us. >>> >>> > My own statistics in my projects show the contrary. At best, this >>> shows how divisive this feature is. >>> >>> This *may* show that, if contrary statistics were presented, but that >>> hasn’t occurred. >>> >>> I can generate statistics from my projects if you want. But it's >>> unnecessary: I haven't used private once since it's introduction in Swift >>> 3. I don't see the advantages it brings worth the trouble. >>> >>> >>> - In old code, statistics could be biased by the migrator having >>> replaced all previous instances of private by fileprivate. >>> >>> If the migrator migrated code to private, and it *worked* (e.g. did not >>> introduce visibility errors) this is not bias, this is a correct use of the >>> feature. >>> >>> The migrator migrated to fileprivate everywhere, not private, >>> disagreeing with your use of fileprivate. >>> >>> > I'm just arguing that the additional scope-based access modifier does >>> not provide enough differentiation to be worth that complexity. >>> >>> The only argument I have seen so far around “complexity” boils down to: >>> “some people do not use it”. But some people *do* use it, and anyway if we >>> are going to remove all the features “not enough people” use then we are in >>> for a ride. >>> >>> Some people used the for(;;) loop, the ++ operator, var parameters. Many >>> other features were removed from Swift to simplify he language, make it >>> more consistent. Those are worthwhile goals. Yes, we are past Swift 3 now, >>> but that doesn't mean we shouldn't be able to propose a few rare breaking >>> proposals. The implementation of access modifiers came so late in the Swift >>> 3 timeframe that we had little time to play around with them before Swift 3 >>> was released. Now that we have, we have a short window of time to fix >>> mistakes that were made. I'm just arguing that the proposal was one of >>> those mistakes. But you have a right to disagree. >>> >>> Swift 3 shipped, so what we are discussing now is yanking a keyword >>> without replacement. There is code written that uses private to enforce >>> its threading or security invariants. There is code written that uses >>> private in order to shadow another declaration. There is code that will >>> not compile after migration. We need more than a vague fear of complexity >>> generally to throw a brick through all those windows. That brick will >>> introduce quite a bit of complexity itself. >>> >>> Concerning the one-class-per-file argument, I would suggest this >>> counter-argument: when working in large projects, I believe it's a good >>> thing if the language encourages (forces is too strong a word for my taste) >>> a one class per file structure, it's good practice. >>> >>> >>> The form of the argument is invalid. Suppose I argued: "it’s a good >>> thing for the language to encourage one definition per class (no >>> extensions), it’s good practice. So we do not need fileprivate.” That >>> would be very silly (although it has already been advanced as a straw-man >>> position elsewhere in this thread). The argument that we do not need >>> private because nobody should put multiple classes in a file is equally >>> silly. There are reasons to do so, in fact one motivation was given in >>> SE-0025: >>> >>> > 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. >>> >>> >>> These concerns are not resolved by arguments of the form “just don’t do >>> that”. >>> >>> I empathize with the Swift2 programmer who got through two releases >>> without a scoped access modifier and is annoyed by change. However, >>> removing the feature now is more change, not less, so it makes their >>> problem worse, not better. >>> >>> >>> On March 21, 2017 at 2:17:40 AM, David Hart ([email protected]) wrote: >>> >>> Perhaps it was a mistake, but I purposefully did not go into too much >>> detail in the proposal because I think this debate is purely a question of >>> philosophy on Swift and its language features. I did not want to add >>> un-necessary bloat that would have added little rationalisation. Let me try >>> to explain the holes in the proposal by answering your review: >>> >>> On 21 Mar 2017, at 02:26, Drew Crawford via swift-evolution < >>> [email protected]> wrote: >>> >>> I disagree quite strongly with the proposal. >>> >>> First, the document draws conclusions without apparent supporting >>> evidence, e.g. >>> >>> > Since the release of Swift 3, the access level change of SE–0025 was >>> met with dissatisfaction by a substantial proportion of the general Swift >>> community. Those changes can be viewed as actively harmful, the new >>> requirement for syntax/API changes. >>> >>> >>> - What is “dissatisfaction by a substantial proportion of the >>> general Swift community”? How was this measured/determined? >>> >>> It’s not feasible to measure precisely the feeling of a whole community. >>> But we get a feeling for it by following the mailing-list, by talking to >>> colleagues, by reading twitter, etc… And it think we all agree that the >>> debate is highly divisive and that a “substantial proportion” of the >>> community was dissatisfied: I’m not arguing that it is less or more than a >>> majority. I’m just saying that we’ve seen a lot of talk against the >>> original change. >>> >>> >>> - What was done to control for the population happy with SE-0025 who >>> would e.g. not be likely to take up pitchforks? >>> >>> That’s why its important we have this debate now. >>> >>> >>> - Who argues these changes are “actively harmful” and where were >>> they during SE-0025? >>> >>> The proposal makes the argument that the changes are actively harmful. >>> It’s now up to debate. By the way, even if several people (including me) >>> were already against this proposal during the review, I don’t see why >>> anybody would not have the right to change his mind, especially after >>> several months of production usage and argue differently now. >>> >>> > subtly encourages overuse of scoped access control and discourages the >>> more reasonable default >>> >>> >>> - Who claims that scoped access is “overused” and what is their >>> argument for doing so? >>> - Why is “fileprivate” the “more reasonable default”? In fact >>> neither fileprivate **nor** private are default (reasonable or >>> not!). Internal is the default. Nor does this proposal suggest we change >>> that. So this seems a very strange statement. >>> >>> By default, I did not mean the syntactic default of the language but the >>> access modifier users will use “by default” when trying to restrict >>> visibility. In most languages, that keyword is “private” so its valid to >>> say that newcomers to the language will “default” to using that one. If the >>> proposal is accepted, file-scoped private will regain that status. >>> >>> > But is that distinction between private and fileprivate actively used >>> by the larger community of Swift developers? >>> >>> Yes. To cite some evidence, here are codebases I actively maintain: >>> >>> | codebase | private # | >>> fileprivate # | ratio | >>> >>> |--------------------------------------------------------|-- >>> ---------|---------------|-------| >>> >>> | "M" (proprietary) | 486 | >>> 249 | 2x | >>> >>> | "N"(proprietary) | 179 | >>> 59 | 3x | >>> >>> | NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | >>> 1 | 15x | >>> >>> | atbuild https://github.com/AnarchyTools/atbuild | 54 | >>> 5 | 11x | >>> >>> So from my chair, not only is the distinction useful, but scoped access >>> control (private) is overwhelmingly (2-15x) more useful than fileprivate. >>> >>> My own statistics in my projects show the contrary. At best, this shows >>> how divisive this feature is. During the discussion of this proposal, it >>> was argued that making decisions based upon project statistics would be >>> dangerous: >>> >>> >>> - In old code, statistics could be biased by the migrator having >>> replaced all previous instances of private by fileprivate. >>> - In new code, satistics could be biased by people using private >>> because of it being the “soft-default”, regardless of proper semantics. >>> >>> > And if it were used pervasively, would it be worth the cognitive load >>> and complexity of keeping two very similar access levels in the language? >>> This proposal argues that answer to both questions is no >>> >>> This proposal does not make any later argument about “cognitive load” or >>> “complexity” I can identify. Did the proposal get truncated? >>> >>> Sorry if I did not state it explicitly, but I see any feature/keyword >>> added to the language as “additional complexity”. And that complexity is >>> completely worth it when the feature adds significant expressivity. I'm >>> just arguing that the additional scope-based access modifier does not >>> provide enough differentiation to be worth that complexity. >>> >>> What is stated (without evidence) is that "it is extremely common to use >>> several extensions within a file” and that use of “private” is annoying in >>> that case. I now extend the above table >>> >>> | codebase | private # | >>> fileprivate # | ratio | # of extensions (>=3 extensions in file) | >>> >>> |--------------------------------------------------------|-- >>> ---------|---------------|-------|-------------------------- >>> ----------------| >>> >>> | "M" (proprietary) | 486 | >>> 249 | 2x | 48 | >>> >>> | "N"(proprietary) | 179 | >>> 59 | 3x | 84 | >>> >>> | NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | >>> 1 | 15x | 3 | >>> >>> | atbuild https://github.com/AnarchyTools/atbuild | 54 | >>> 5 | 11x | 6 | >>> >>> in order to demonstrate in my corner of Swift this is not “extremely >>> common”, and is actually less popular than language features the proposal >>> alleges aren’t used. >>> >>> My point here is that ***different people in different corners of the >>> community program Swift differently and use different styles***. I can >>> definitely empathize with folks like the author who use extensions to group >>> functions and are annoyed that their favorite visibility modifier grew four >>> extra characters. Perhaps we can come up with a keyword that is more >>> succint. >>> >>> I agree that different people in different corners use different styles. >>> But you could use that argument to validate many features which would make >>> a group of users happy; but all those feature together would just add bloat >>> to the language. Swift has been known to be a very opinionated language, to >>> keep the language simple yet expressive. >>> >>> However, that is no reason to take away features from working >>> codebases. A scoped access modifier is perhaps my favorite feature in >>> Swift 3. Let’s not throw stuff away because it adds extra characters to >>> one programming style. >>> >>> Finally, SE-0025 establishes clear motivation for the scoped access >>> modifier: >>> >>> > Currently, the only reliable way to hide implementation details of a >>> class is to put the code in a separate file and mark it as private. This is >>> not ideal for the following reasons: >>> >>> > It is not clear whether the implementation details are meant to be >>> completely hidden or can be shared with some related code without the >>> danger of misusing the APIs marked as private. If a file already has >>> multiple classes, it is not clear if a particular API is meant to be hidden >>> completely or can be shared with the other classes. >>> >>> > 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 such >>> sharability with the current access levels. >>> >>> As far as I can see, the proposal does not actually address or >>> acknowledge these problems at all, but cheerfully returns us to them. It >>> would be a mistake to deprecate this feature without examining at all why >>> we introduced it. And realistically we need new solutions to those >>> problems before removing the existing one. >>> >>> Drew >>> >>> On March 20, 2017 at 6:54:55 PM, Douglas Gregor ([email protected]) >>> wrote: >>> >>> Hello Swift community, >>> >>> The review of SE–0159 “Fix Private Access Levels” begins now and runs >>> through March 27, 2017. The proposal is available here: >>> >>> https://github.com/apple/swift-evolution/blob/master/proposa >>> ls/0159-fix-private-access-levels.md Reviews are an important part of >>> the Swift evolution process. All reviews should be sent to the >>> swift-evolution mailing list at >>> >>> https://lists.swift.org/mailman/listinfo/swift-evolution or, if you >>> would like to keep your feedback private, directly to the review manager. >>> When replying, please try to keep the proposal link at the top of the >>> message: >>> >>> Proposal link: >>> >>> https://github.com/apple/swift-evolution/blob/master/proposa >>> ls/0159-fix-private-access-levels.md Reply text Other replies What goes >>> into a review? >>> >>> The goal of the review process is to improve the proposal under review >>> through constructive criticism and, eventually, determine the direction of >>> Swift. When writing your review, here are some questions you might want to >>> answer in your review: >>> >>> What is your evaluation of the proposal? Is the problem being addressed >>> significant enough to warrant a change to Swift? Does this proposal fit >>> well with the feel and direction of Swift? If you have used other languages >>> or libraries with a similar feature, how do you feel that this proposal >>> compares to those? How much effort did you put into your review? A glance, >>> a quick reading, or an in-depth study? More information about the Swift >>> evolution process is available at >>> >>> https://github.com/apple/swift-evolution/blob/master/process.md Thank >>> you, >>> >>> -Doug >>> >>> Review Manager >>> ------------------------------ >>> >>> swift-evolution-announce mailing list [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution-announce >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >>> >> > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
