On Fri, Aug 23, 2024, at 1:38 PM, Rob Landers wrote:
> On Fri, Aug 23, 2024, at 20:27, Bruce Weirdan wrote:
>> On Fri, Aug 23, 2024 at 4:27 PM Larry Garfield <la...@garfieldtech.com> 
>> wrote:
>>> Moving those definitions to attributes is certainly possible, though AFAIK 
>>> both the PHPStan and Psalm devs have expressed zero interest in it.
>>> Part of the challenge is that such an approach will either still involve 
>>> string parsing,
>> 
>> That's not really a challenge and would help somewhat with the current 
>> status quo where we have to guess where the type ends and the textual part 
>> of the comment begins. But it gets ugly for any type that has to include 
>> quotes (literal strings, array keys, etc). Technically one can use nowdocs, 
>> but it's not much better:  https://3v4l.org/4hpte
>>  
>>> or will involve a lot of deeply nested attribute classes. 
>> 
>> Yeah, that would look like Lisp's S-exprs, but much worse - which, in my 
>> opinion, would harm adoption.
>> 
>> All in all, in my opinion attribute-based solutions are less ergonomic than 
>> what we already have now in docblocks.
>> 
>> --
>>   Best regards,
>>       Bruce Weirdan                                     
>> mailto:weir...@gmail.com
>
> Thank you Larry for expressing some of the problems. Is there any 
> reason nesting has to be supported out of the gate? Think about type 
> hints. It started with some basic functionality and then grew over 
> time. There is no reason we have to have a new kitchen sink, oven, 
> dishwasher and stove when all we want is a new refrigerator. 
>
> — Rob

While I understand the temptation to "just do part of it", which comes up very 
often, I must reiterate once again that can backfire badly.  That is only 
sensible when:

1. There's a very clear picture to get from A->Z.
2. The implementation of C and D cannot interfere with the design or 
implementation of J or K.
3. The steps along the way offer clear self-contained benefits, such that if 
nothing else happens, it's still a "complete" system and a win.
4. The part being put off to later isn't just putting off the "hard part".

In practice, the level at which you get all four is quite coarse, much coarser 
than it seems most people on this list think.

Examples of where we have done that:

* Enums.  The initial Enum RFC is part one of at least 3 steps.  Step 2 is 
pattern matching, Step 3 is ADTs/tagged unions.  Those are still coming, but 
all three were spec'ed out in advance (1), we're fairly confident that the enum 
design will play nice with tagged unions (2), and enums step 1 has very clearly 
been hugely positive for the language (3, 4).

* Property hooks and aviz.  These were designed together.  They were originally 
a single planning document, way back in Nikita's original RFC.  After 
effectively doing all the design work of both together, we split up the 
implementations to make them easier.  Hooks was still a large RFC, but that was 
after we split things up.  That meant we had a clear picture of how the two 
would fit together (1, 2), either RFC on its own would have been beneficial to 
the language even if they're better together (2, 3), and both were substantial 
tasks in themselves (4).

* Gina's ongoing campaign to make PHP's type juggling have some passing 
resemblance to logic.

With generics, the syntax isn't the hard part.  The hard part is type 
inference, or accepting that generic-using code will just be extraordinarily 
verbose and clumsy.  There is (as I understand from Arnaud, who again can 
correct me if I'm wrong) not a huge amount of difference in effort between 
supporting only Foo<Bar> and supporting Foo<Bar<Baz>>.  The nesting isn't the 
hard part.  The hard part is not having to type Foo<Bar> 4 times across 2 files 
every time you do something with generics.  If that can be resolved 
satisfactorily (and performantly), then the road map to reified generics is 
reasonably visible.

So for any intermediate generics implementation, it would need to have a very 
clear picture to get from that initial state to the final state (without the 
landmines that something like readonly gave us), we'd need to be confident 
we're not adding any landmines, each step would need to be useful in its own 
right, and it would have to be breaking up the "hard work" into reasonable 
chunks, not just punting the hard work for later.

Leaving out nested generics doesn't achieve those.

This is also why the dedicated collections work that Derick and I were looking 
into has been on pause, because adding a dedicated collections syntax, and then 
getting full reified generics later, would lead to a very ugly mess of 
inconsistency.  Better to wait and try to get full generics first, or confirm 
once and for all that it's impossible.

Strategies that MIGHT make sense in that framework, and the ones on which we 
are specifically requesting feedback, include:

* Type-erased generics, with the expectation that they would become enforced at 
some point in the future.  (Though this could lead to lots of "working" code 
suddenly not working once the enforcement was turned on.)
* No type inference.  Generics are just very verbose, deal with it.  Type 
inference could, potentially, be added later.  (Maybe; it's not guaranteed that 
it could be done effectively, as the writeup discusses).
* Only allow generics over simple types, not union/intersection types.  Unlike 
nested generics, union types do increase the cost of determining compatibility 
considerably, so making them performant is a much bigger challenge.  Maybe that 
challenge could be punted for later?  (And if later turns into never, or 10 
years from now, is that still an acceptable end-state?)

The acceptability of each of these strategies is what we were hoping to 
determine in feedback to the writeup.

--Larry Garfield

Reply via email to