On Tue, Mar 25, 2025, at 23:20, Rowan Tommins [IMSoP] wrote: > > > On 25 March 2025 21:23:48 GMT, Rob Landers <rob@bottled.codes> wrote: > > > >> If we didn't have "protected", would you ask the same about "protected > >> private"? "fileprivate" would be just another access level, not something > >> you'd combine with existing ones. > > > >Actually, probably yes :) Mostly just to ask for clarification. In this case > >though, we have private(set) and protected(set); would we also want > >fileprivate(set)? That's what I was getting at. How do we mix/match up all > >these things? > > > I don't see what needs deciding - private(set) isn't a new access level, it's > basically sugar for a setter that's marked private. > > Try replacing "private" with "level1", and "protected" with "level2": > > level1(set) level2(get) int $foo; > > And then add "level1a"; can you use it in the same places? Of course: > > level1a(set) level2(get) int $foo; > > So why would there be any ambiguity about writing this? > > fileprivate(set) protected(get) int $foo; > > > > >> > maybe `fileprivate` on a property means `public` in the file, but > >> > `private` outside the file. But then how would that intersect with > >> > inheritance? > > > Just to call back to this: it's like saying "protected means public inside > the class and its descendants, but private everywhere else". It's an > unnecessarily confusing way of describing it, because you then have to define > "public" and "private" without the definitions being recursive. > > A more straightforward description is "protected means accessible inside the > class and its descendants, and nowhere else". > > Maybe having "private" in the name is putting you off, and this is clearer: > > samefile(set) samemodule(get) int $foo; > > No "private" or "public" involved anywhere, just descriptions of where the > property can be accessed. >
To be clear, I'm not trying to be difficult. As you mentioned, these were all things I had to think about for nested classes too. I know how nested classes work and why. How file-private would work, on the other hand, I have put little thought into. You say it is obvious (to paraphrase), but the devil is in the details, and there isn't much prior-art to draw from here either. The only prior art I can think of is Swift's `fileprivate` and C's `static`. Beyond that, I am not aware of any other language to offer this feature. That being said, we can certainly define it any way we want to, but asking 'dumb questions' and challenging assumptions will help us find the rough edges and things we didn't consider before. > >> I see no reason for inheritance to be involved at all. If we want an > >> access level that means "accessible from any code in this file, or any > >> subclass of the current type", we can make up a keyword for that as well - > >> "fileprotected", or "fileprivate_or_protected", or whatever. > > > >Inheritance gets involved in traits. Traits do "inherit" private access > >properties (currently): https://3v4l.org/89I7A > > > Traits don't inherit anything, and they don't restrict anything either. They > paste code in, and once pasted it acts like it was written in the new > location. You can even change access levels while pasting, with the syntax > "use Foo { bar as public }". > > The "private" keyword in your example is pasted into class Foo, and means > "accessible within class Foo". It never applies any restriction relative to > trait Bar, because running code never belongs to the trait. > > A "fileprivate"/"samefile" keyword would be pasted into the file it was used > in, and mean accessible within that file; it wouldn't matter what file the > trait was defined in. It would probably be useless, but lots of useless code > is possible in any language. I agree, but these are all things we'd have to consider. I, personally, would consider it working the other way around. A trait declaring fileprivate would only be accessible in the trait; otherwise you would have to explain how fileprivate works without saying "the file it is written in" and in a way that is easy to understand -- for the RFC + docs. I don't know if it would be useless or useful though. Personally, I'd probably implement both ways and see how useful each one is when implementing a toy project and then weigh the pros/cons. It might even be a "why not both?" type of situation. It's easier to explain if it is both (your description above works perfectly for that), but then would allow for some odd behaviors. — Rob