On Fri, Mar 14, 2025, at 17:09, Ilija Tovilo wrote:
> Hi Bob
> 
> On Thu, Mar 13, 2025 at 11:36 PM Bob Weinand <bobw...@hotmail.com> wrote:
> >
> > On 6.3.2025 23:20:37, Ilija Tovilo wrote:
> >
> > > I would also like to echo what has been said about the :: operator,
> > > which feels out of place. I understand that \ comes with additional
> > > autoloading challenges, namely requiring a fallback autoloading
> > > strategy that currently does not conform to PSR-4.
> >
> > Could you please elaborate on why the :: operator feels out of place?
> >
> > \ is a namespace separator.
> >
> > :: is a class scoping separator.
> >
> >
> > You, yourself did decide to use nested :: for property hook scoping, like 
> > parent::$x::set() - a property scoped within a class, having methods.
> > The same applies here - it's a class scoped within a class, having methods.
> >
> > Breaking from these patterns seems very surprising to me.
> 
> :: is an operation performed on the class. E.g. fetch a static
> property, fetch a constant, call a static method, while \ is part of
> the class name. The way I see it, the outer class can simply add an
> additional namespace component to the inner class.
> 
> class Foo {
>     class Bar {} // Called Foo\Bar
> 
>     public Bar $bar;
> }
> 
> This is dead simple, it doesn't change any assumptions about class
> names by embedding new symbols, it doesn't need a new operator, you
> can refer to the class with its short name from inside the outer class
> without `self:>`, which is shorter and more straight forward, `use
> Foo\Bar;` will just work in other classes, etc.
> 
> One thing this approach breaks is that it doesn't allow for
> polymorphic inner class resolution, i.e. static:>Bar. But given this
> was removed anyway, that point no longer applies. This can also easily
> be replicated by a simple method:
> 
> class Foo {
>     class Bar {}
> 
>     public function createBar(): Bar {
>         return new Bar();
>     }
> }
> 
> Except this is actually type-safe, because the return value of
> createBar() must stay compatible with Foo\Bar.
> 
> Ilija
> 

Hi Ilija,

What about a hybrid approach? Maybe something like `\\` that Tim suggested? But 
hear me out. Instead of it being between all inner parts, it is only between 
the outermost and inner parts of the class, otherwise just use `\`. This also 
solves a problem where:

- we don't need to change anything with autoloading
- we can differentiate between different types with the same name

So

namespace Foo;

class Outer {
  class Middle {
    class Inner {}
  }
}

namespace Foo\Outer;

class Middle {
}

can be differentiated from each other (Foo\Outer\Middle vs. 
Foo\Outer\\Middle\Inner).

I also like the idea of just using the name instead of having Foo:>Bar... I 
think that is possible now that I have all the machinery in place for 
visibility. I may have the implementation ready today/tomorrow (as per the 
currently written RFC). 🤞

— Rob

Reply via email to