On Tue, Mar 25, 2025, at 23:20, Rowan Tommins [IMSoP] wrote:
>
>
> On 25 March 2025 21:23:48 GMT, Rob Landers <[email protected]> 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