Hey Ilija,

On 14.3.2025 17:09:40, 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.

I'd consider this a very internals perspective. Yes, internally it will include its separator and the reported name includes the separator.

From a user perspective, the class is fetched (an operation!) from its defining class.

Similarly, static::Foo (if it is going to be re-introduced) and parent::Foo, are definitely *fetches* of the class.

And as such, it should also have the :: operator.

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.

use Foo\Bar; to reference to an inner-class sounds very much like a bad idea to me.

Inner classes are supposed to be intrinsically tied to their containing class, and making it work like a namespace reduces the association a lot.

I desire explicitness, which a different symbol can give you. Using namespace-syntax makes the autoloading and human resolution more complex for no gain.

Removing the self:: seems enticing, but it breaks at the moment you add inheritance. Then you'll have to either make it a binding-time decision whether it's a namespace access or a parent inner class access.

class Foo { class Bar {} } class Baz extends Foo { public Bar $bar; // ??? parent::Bar would be obvious. }

Certainly you could opt for only removing self:: in classes they are declared in, but what's then the syntax when referring to an inner class up the inheritance chain? parent\Foo? That's plain weird. Or explicitly requiring the concrete class name the inner class is implemented on? Then this becomes the only weird case which cannot be accessed through the scope resolution. Why would one want that?

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.

I don't care much about static resolution for this, but self:: and parent:: are relevant.

Bob

Reply via email to