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