On Fri, Aug 23, 2024, at 23:06, Larry Garfield wrote: > 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.
I wasn't intending to just say "just do it," but rather, is it "good enough." As I mentioned in another email on this topic, right now there is only one person in the world who can work on the problem. Sure, we can leave drive-by comments and our own experiences/opinions here and on github, but ultimately, the knowledge of how it works and how it can be improved exists solely within one (or thereabouts) person's brain; on the entire planet. This is sort-of how when we write software, we try to keep small PRs. Small PRs can be reviewed quickly and merged. Other developers on the team can start interacting with the code, even if the feature that it pertains to is incomplete. From that point forward, other developers can improve that code, separately from the person who is working on the feature. The knowledge of how it works is shared and people with different perspectives and experiences can make it better. > > 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. Ok. But wasn't there something about nesting causing super-linear performance issues? So, disable nesting and don't worry about inference. Obviously, people will want these things. I do remember a time in PHP where you had to type out function() use (stuff) {} for every little anonymous function call. It was super annoying. However, I don't think PHP would have ever even existed if someone didn't say "it is good enough for now." Maybe Arnaud can solve inference, all by themselves with whatever resources can be thrown at them, but what if it comes to people actually using it ... and they hate inference? PHP is a verbose language, so it isn't that unthinkable. But seriously, that would be quite a waste of time and effort. Instead of striving for perfection from the beginning, strive for getting something working that people are actually asking for (generics—nobody is asking for inference) and gather feedback. Maybe nobody actually wants inference, or they want a type of inference that only makes sense once you start using it that you can't even guess about right now. > > 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. See above. But if the actual issue is inference, then leave that out. > > 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.) Personally, this would be interesting because you'd have go-like semantics. It wouldn't actually have to implement the interface, just have the same methods/properties. It also leads to interesting thoughts in that you don't even need to do type-checking at function/method boundaries, only when/if it is used. But that would probably require some pretty big changes to zvals/type juggling. I don't work here, so all I can give is advice and a little bit of time. But, I suspect that if someone wanted to, type checking/juggling could be 5-10x faster than it currently is. > * 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). IIRC, typescript didn't have proper inference until years later. For example, initially, it could only infer primitive types (similar to PHP, really). > * 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?) Ah, this is what I was thinking of. Thank you. Yeah, instead of "nesting" prior, I was referring to union types. > > The acceptability of each of these strategies is what we were hoping to > determine in feedback to the writeup. > > --Larry Garfield > — Rob