Re: Re: RFC: short and inner classes

From: Date: Thu, 13 Mar 2025 23:26:03 +0000
Subject: Re: Re: RFC: short and inner classes
References: 1 2 3 4 5  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message


On Thu, Mar 13, 2025, at 23:26, Bob Weinand wrote:
> Hey Rob,
> 
> On 13.3.2025 21:46:49, Rob Landers wrote:
>> On Thu, Mar 13, 2025, at 12:01, Tim Düsterhus wrote:
>>> Hi
>>> 
>>> Am 2025-03-12 11:10, schrieb Rob Landers:
>>> > - Accessing inner classes is done via a new token: ":>" instead of 
>>> > "::".
>>> 
>>> I don't particularly like that. It is “invented syntax” and I don't 
>>> think that inner classes are sufficiently valuable to dedicate an entire 
>>> operator to them that could serve a more useful purpose in the future. 
>>> It also got 4 negative points in the rating back when the namespace 
>>> separator was decided: https://wiki.php.net/rfc/namespaceseparator
>>> 
>>> Would \\ (i.e. two backslashes) work? The outer class for inner 
>>> classes effectively act as a namespace, so it makes sense to me to use 
>>> syntax that is similar to namespaces.
>>> 
>>> I'll look into the rest when there is a new implementation, since I 
>>> assume some details will still be clarified and fixed as part of 
>>> implementing the proposal.
>>> 
>>> Best regards
>>> Tim Düsterhus
>>> 
>> 
>> I am not particularly attached to the separator. I specifically chose it due to being a
>> mixture of :: and -> and -: seemed like a bad idea. In other words, an inner class felt natural
>> to use :> -- however, I have some issues with it myself. Particularly, it is too much like |>
>> and as shown in the namespace RFC, way too easy to typo. Personally, after using it for a few days,
>> I'd almost rather go back to :: ...
>> 
>> I will give \\ a try, but it has to be typed quite a bit when referencing inner classes, so
>> keeping it easy to type is a must. I feel like \\ requires a large movement to type, at least on a
>> qwerty non-english keyboard. Maybe people using other keyboards can chime in.
> Please go back to ::. The double colon was perfectly fine, the only thing which was weird was
> the implicit constant. It's fine for constants and inner classes to share the same name scoping
> (i.e. a constant must not share a name with an inner class). But an inner class should not be an
> actual constant.
> 
> But otherwise, this was perfectly fine.
> 

My biggest issue with :: is that it gets weird:

class Foo {
  public class Bar {}
  public const Bar = "";
  public static function Bar() {}
}

echo Foo::Bar; // this is the constant
new Foo::Bar(); // this is the class
Foo::Bar(); // this is the method
new (Foo::Bar()); // this is the method
new (Foo::Bar); // this is constant

I can now differentiate between these all in the AST, but it seems weird to me. If we go this route,
I'd personally have the preference to allow them all and let people's code-style dictate
what is acceptable or not -- assuming I can ensure there is no ambiguity in the grammar. At least
with :> (or something else) we don't have to even have that discussion.. :)

>>> I don't think that inner classes are sufficiently valuable
>> 
>> I'm curious why some people feel this way and why some other people are saying the
>> opposite (emphatically). I'll nudge the private emails I've received to speak up publicly
>> on the list as well. But, why do you feel this way?
> 
> I don't know why some people feel this way, but at least with the autoloading mechanisms
> we have in PHP there are definite limitations to multiple classes in one file:
> - If you deserialize your data structure and it contains another class, whose name does not
> match the file name, you better hope to god that it has been autoloaded already. Surprising failures
> in production follow. (e.g.: the amphp\parallel process runner will try to serialize your exception.
> That's fine. But as soon as it's accidentally bubbling up and as it's not
> autoloadable, the hell breaks loose.)
> - Enums or Data Transfer objects specific to one or multiple functions of only this specific
> class would naturally fit into the same file. But you can't do it ... because the autoloading
> might try to load the enum first, before the class whose constructor or function you want to call is
> actually loaded.
> - Now, if you actually stuff multiple classes / enums into a single file, it's non-trivial
> to figure out (as the human reader, but obviously for the autoloader too) which file to access to
> read up the definition of a specific enum (short of using dedicated tooling for it).
> 
> 
> Certainly, one may say - yeah, just religiously use different files for ... every ... single
> ... class.
> But what's the point of that dogma?
> It definitely doesn't help the organization of dedicated helper structures tied to a
> single class.
> It's a tool for organization. It's not complex to understand.
> 
> Outside of very puristic arguments I don't see any reason why one would not want inner
> classes.
> 
> 
> Further, with short classes, should they hopefully be introduced as well, it will become
> trivial to write shapes for any internal datastructures - simply using a "class Point(int $x,
> int $y); private Point $pos;" rather than "/** @var list{int, int} */ private array
> $pos;".
> This will be a very ergonomic way to reduce ad-hoc arrays which are only typehinted by phpdoc,
> giving proper typing and also safe access to structures via named accessors rather than [0] and [1]
> etc.
> 
> Further Questions on the (original) RFC:
> 
> - Why is there a conflict in static properties and the inner class name? The former always has
> a leading $ sigil.
> 

Funny enough, this was due to me messing up the AST such that it was trying to access a property
instead of a constant. Once I fixed that, the conflict went away.

> - Any particular reason to disallow abstract inner classes? Feels arbitrary.
> 

This went away as well, once I started cleaning up the grammar. Basically, I couldn't work out
how to allow :: in extends. I eventually figured it out once I implemented
:>. Replacing :> with virtually anything else is quite possible --
including going back to :: (I think).

> And a note: I consider the inheritance example misguided as "static constructors"
> (static methods which invoke new()) would be a better pattern here. Could you maybe come up with
> another example here?
> 
> 
> 
> Bob
> 

That was a pretty bad example! It illustrated the point but would probably be a bad practice. 

— Rob


Thread (102 messages)

« previous php.internals (#126745) next »