Re: [PHP-DEV] RFC: Support Closures in constant expressions
On Mon, Nov 4, 2024, at 6:57 PM, Gina P. Banyard wrote: > On Monday, 4 November 2024 at 20:32, Larry Garfield > wrote: > >> On Mon, Nov 4, 2024, at 6:06 AM, Tim Düsterhus wrote: >> > >> > Here's another brainteaser: >> > >> > function foo( >> > string $bar, >> > Closure $baz = static fn () => $bar, >> > ) { >> > var_dump($baz()); >> > } >> > >> > foo('captured'); >> > >> > What would you expect the semantics of that script to be? >> >> >> My expectation is that it's confusing, and therefore we should simply >> disallow it. Which roughly translates to detecting if a closure tries to use >> an unbound variable statically. Which is probably more difficult than I make >> it sound. :-) > > Which is why short closures are being disallowed. > The value of it *is* limited, and the semantics of it are confusing. > I am struggling to see why this is such a big deal. I suspect, since several people have asked about it, it's because most of the use cases for having a default Closure value are going to be short; the sort of short cases that short-closures and FCC are designed for. If it's long, then you're probably better off moving it to a private method and making a FCC reference to that private method the default value instead. So if most of the use cases align with where one would use short-closures and FCC, not being able to is disappointing, even if the reasons for it are valid. >> > > If it cannot reasonably be done now, but is possible, that should be >> > > listed in future scope with roughly what it would take for a follow-up >> > > to do. (And then we can argue if it should just be done now, with more >> > > information as to how much work that is.) >> > >> > I have added an entry to the “Future Scope” section. See also my reply >> > to Alex. > >> Thanks. Can you include what the implementation challenges are for the >> future-scope items, to explain why they're being punted to later rather than >> addressed now? (As there seems clear interest in having all of them.) >> > > I have never seen a future scope section which describes these > challenges, and this feels just giving more work to people for no > benefit? I'm not asking for a detailed description of the engine nuances of detecting unbound variables. Just something along the lines of "this would require detecting unbound variables, that's hard, so we'll save that for later." Which is a level of detail I frequently do provide in my RFC future-scopes. --Larry Garfield
Re: [PHP-DEV] [RFC] PHP.net analytics
On Fri, Nov 1, 2024, at 6:10 PM, Bob Weinand wrote: > On 1.11.2024 22:41:29, Larry Garfield wrote: >> In a similar vein to approving the use of software, Roman Pronskiy asked for >> my help putting together an RFC on collecting analytics for PHP.net. >> >> https://wiki.php.net/rfc/phpnet-analytics >> >> Of particular note: >> >> * This is self-hosted, first-party only. No third parties get data, so no >> third parties can do evil things with it. >> * There is no plan to collect any PII. >> * The goal is to figure how how to most efficiently spend Foundation money >> improving php.net, something that is sorely needed. >> >> Ideally we'd have this in place by the 8.4 release or shortly thereafter, >> though I realize that's a little tight on the timeline. > > Hey Larry, > > I have a couple concerns and questions: > > Is there a way to track analytics with only transient data? As in, data > actually stored is always already anonymized enough that it would be > unproblematic to share it with everyone? > Or possibly, is there a retention period for the raw data after which > only anonymized data remains? The plan is to configure Matomo to not collect anything non-anonymous to begin with, to the extent possible. We're absolutely not talking about user-stalking like ad companies do, or anything even remotely close to that. I'm not convinced that publishing raw, even anonymized data, is valuable or responsible. I don't know of any other sites off hand that publish their raw analytics, and I don't know what purpose that would serve other than just a principled "radical transparency" stance, which I generally don't agree with. However, having an automated aggregate dashboard similar to https://analytics.bookstackapp.com/bookstackapp.com (made by a different tool, but same idea) that we could make public is the goal, but we don't want to do that until it's been running a while and we're sure that nothing personally identifiable could leak through that way. > Do you actually have a plan what to use that data for? The RFC mostly > talks about "high traffic". But does that mean anything? I do look at a > documentation page, because I need to look something specific up (what > was the order of arguments of strpos again?). I may only look shortly at > it. Maybe even often. But it has absolutely zero signal on whether the > documentation page is good enough. In that case I don't look at the > comments either. Comments are something you rarely look at, mostly the > first time you want to even use a function. Right now, the key problem is that there's a lot of "we don't know what we don't know." We want to improve the site and docs, the Foundation wants to spend money on doing so, but other than "fill in the empty pages" we have no definition of "improve" to work from. The intent is that better data will give us a better sense of what "improve" even means. It would also be useful for marketing campaigns, even on-site. Eg, if we spend the time to write a "How to convince your boss to use PHP" page... how useful is it? From logs, all we could get is page count. That's it. Or the PHP-new-release landing page that we've put up for the last several releases. Do people actually get value of that? Do they bother to scroll down through each section or do they just look at the first one or two and leave, meaning the time we spent on any other items is wasted? Right now, we have no idea if the time spent on those is even useful. Another example off the top of my head: Right now, the enum documentation is spread across a dozen sub-pages. I don't know why I did that exactly in the first place rather than one huge page, other than "huge pages bad." But are they bad? Would it be better to combine enums back into fewer pages, or to split the visibility long-page up into smaller ones? I have no idea. We need data to answer that. It's also absolutely true that analytics are not the end of data collection. User surveys, usability tests, etc. are also highly valuable, and can get you a different kind of data. We should likely do those at some point, but that doesn't make automated analytics not useful. Another concern with just using raw logs is that it would be more work to setup, and have more moving parts to break. Let's be honest, PHP has an absolutely terrible track record when it comes to keeping our moving parts working, and the Infra Team right now is tiny. The bus factor there is a concern. Using a client-side tracker is the more-supported and fewer-custom-scripts approach, which makes it easier for someone new to pick it up w
Re: [PHP-DEV] RFC: Support Closures in constant expressions
On Mon, Nov 4, 2024, at 6:06 AM, Tim Düsterhus wrote: > Hi > > Am 2024-10-31 07:16, schrieb Larry Garfield: >> Hm. It would never occur to me to use a function for a non-class >> constant in the first place, so I don't know. :-) Frankly I can't >> recall the last time I used a non-class constant period. :-) >> >> That said, PHP consts are already a bit squishy, and auto-capture is >> always by value. That wouldn't give us a loophole? > > Here's another brainteaser: > > function foo( > string $bar, > Closure $baz = static fn () => $bar, > ) { > var_dump($baz()); > } > > foo('captured'); > > What would you expect the semantics of that script to be? My expectation is that it's confusing, and therefore we should simply disallow it. Which roughly translates to detecting if a closure tries to use an unbound variable statically. Which is probably more difficult than I make it sound. :-) >> If it cannot reasonably be done now, but is possible, that should be >> listed in future scope with roughly what it would take for a follow-up >> to do. (And then we can argue if it should just be done now, with more >> information as to how much work that is.) > > I have added an entry to the “Future Scope” section. See also my reply > to Alex. > > Best regards > Tim Düsterhus Thanks. Can you include what the implementation challenges are for the future-scope items, to explain why they're being punted to later rather than addressed now? (As there seems clear interest in having all of them.) --Larry Garfield
[PHP-DEV] [RFC] PHP.net analytics
In a similar vein to approving the use of software, Roman Pronskiy asked for my help putting together an RFC on collecting analytics for PHP.net. https://wiki.php.net/rfc/phpnet-analytics Of particular note: * This is self-hosted, first-party only. No third parties get data, so no third parties can do evil things with it. * There is no plan to collect any PII. * The goal is to figure how how to most efficiently spend Foundation money improving php.net, something that is sorely needed. Ideally we'd have this in place by the 8.4 release or shortly thereafter, though I realize that's a little tight on the timeline. -- Larry Garfield la...@garfieldtech.com
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Sat, Oct 26, 2024, at 3:24 PM, Jim Winstead wrote: > There were more existing 3rd-party dependencies that should probably be > added to the policy text: > > https://news-web.php.net/php.internals/125769 > > Two I missed were JpGraph and Parsedown which are used by web-doc. > (Currently by side-loading JpGraph and having an old copy of Parsedown > committed to web-doc, I would hope to move those out as Composer > dependencies if we decide to allow that.) > > Jim I have updated the pre-approved list to include everything we're currently using for PHP Tooling, and added a few of them to the other lists as well. (List both Psalm and PHPStan, list both CS-Fixer and CodeSniffer, etc.) For JPGraph, it looks like the original is abandoned and there's a zillion forks, so I listed the one that is by far most popular on Packagist. Since folks may have opinions on these lists, I'll give it a few more days before calling the vote in case someone wants to weigh in. The link again is: https://github.com/php/policies/pull/10 --Larry Garfield
Re: [PHP-DEV] RFC: Support Closures in constant expressions
On Wed, Oct 30, 2024, at 3:01 AM, Tim Düsterhus wrote: > Hi > > Am 2024-10-30 05:25, schrieb Larry Garfield: >> This seems like a good idea to me. My only real question is why we >> need to forbid short-closures. I fully agree that capturing variables >> for such functions doesn't work. What I don't understand is why that >> precludes short-closures. Is it not possible to "just" say "there's >> nothing to even capture in this context, don't try"? (There may be >> technical reasons for that, but I do not know what they are and the RFC >> doesn't say.) > > It would indeed require some special handling to disable the > auto-capturing in the code. This would be solvable of course, but > there's also semantic ambiguity, because users reasonably expect short > closures to perform auto-capturing: > > > $foo = 'foo'; > > const Closure = static fn (array $bar): array => [$foo, $bar]; > > var_dump((Closure)('bar')); > > If this would be legal syntax: What would you expect to be printed? > > Best regards > Tim Düsterhus Hm. It would never occur to me to use a function for a non-class constant in the first place, so I don't know. :-) Frankly I can't recall the last time I used a non-class constant period. :-) That said, PHP consts are already a bit squishy, and auto-capture is always by value. That wouldn't give us a loophole? If it cannot reasonably be done now, but is possible, that should be listed in future scope with roughly what it would take for a follow-up to do. (And then we can argue if it should just be done now, with more information as to how much work that is.) --Larry Garfield
Re: [PHP-DEV] RFC: Support Closures in constant expressions
On Tue, Oct 29, 2024, at 10:11 AM, Tim Düsterhus wrote: > Hi > > Volker and I would like to start discussion on our RFC to "Support > Closures in constant expressions". > > Please find the following resources for your reference: > > - RFC: https://wiki.php.net/rfc/closures_in_const_expr > - Implementation: https://github.com/php/php-src/pull/16458 > > Best regards > Tim Düsterhus This seems like a good idea to me. My only real question is why we need to forbid short-closures. I fully agree that capturing variables for such functions doesn't work. What I don't understand is why that precludes short-closures. Is it not possible to "just" say "there's nothing to even capture in this context, don't try"? (There may be technical reasons for that, but I do not know what they are and the RFC doesn't say.) --Larry Garfield
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Wed, Oct 2, 2024, at 1:36 PM, Larry Garfield wrote: > Since Jim's RFC proposal was criticized for being too vague, I hereby > offer a somewhat more prescriptive policy proposal on using 3rd party > code. (With JIm's blessing.) It's still more heuristics than rules, > but I think that's the right approach generally. It also includes a > voting mechanism to resolve edge cases when they come up. > > I'm sure we'll bikeshed it to death, but please keep an open mind about > the concept in the first place. PHP is more than just php-src, and > that's a good thing. We need to catch up with that reality, while at > the same time maintaining a reasonable neutrality about projects > Internals doesn't manage directly. > > https://wiki.php.net/rfc/third-party-code > > *Puts on trusty flame-retardant suit* An update here. I have converted the RFC into a PR against the policies repo. (Thanks to Derick for his help in dealing with RST format.) https://github.com/php/policies/pull/10 It's essentially the same as the last RFC text, though I split up the approved lists to make it easier to add to in the future. I also added an exceptions mechanism for Dokuwiki. The RFC itself has been updated to be basically just a placeholder stub for the PR. The vote will be basically "merge this PR? Y/N." Absent any more feedback, I will call a vote on it in a week or so. --Larry Garfield
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Wed, Oct 23, 2024, at 6:57 PM, fennic log wrote: > I remember a while ago a discussion about bundling composer with PHP by > default (and possibly dropping pear). > What ever happened with that? > As the first thing any dev does after setting up PHP, is install > composer. As this RFC points out, almost every project modern uses > composer to manage dependencies, and every Library, SDK and framework > requires composer. > So i'd change this line in the RFC >> We should use it, we should document it, we should promote it. > To >> We should use it, we should document it, we should promote it, we should >> bundle it! > > As I mentioned, it is basically a requirement nowadays to work in PHP > unless you are doing something custom that doesnt require any > dependencies, but then, is that person planning to release it to the > public? > I am of no opinion of weather php devs internally should use composer, > i have no skin in that game. But Documentation - Yes, Promotion - Yes, > but does it really need it? Bundle it - Yes! Bundling Composer with PHP is an entirely different question with a host of additional concerns to consider, like whether the Composer maintainers would even want that. Let's please stay focused on the topic at hand. --Larry Garfield
Re: [PHP-DEV] Asymmetric visibility is a BC break
On Wed, Oct 23, 2024, at 11:04 AM, ericm...@php.net wrote: > On 10/22/24 22:39, Calvin Buckley wrote: >> After discussing it and thinking about it for a few days, I agree it's >> not a BC break. Existing code should be fine, and larger frameworks >> that tend to rely on reflection trickery and such also tend to need >> updates for newer PHP. The expectations don't really change. >> >> I don't think we need to rush a solution in for 8.4 as long as we can >> implement one with the existing APIs in userland. As Larry mentioned, >> readonly (and hooks) already made the previous assumptions invalid by >> 8.1. As long as we can provide a polyfill and documentation (which >> should also cover the readonly case in 8.1 too), I'm OK with deferring >> isReadable/isWritable to 8.5. > Chiming in briefly to second Calvin's statement above. > > ~Eric Thanks for the confirmation. We'll work on a small RFC to propose for 8.5. No rush on it. --Larry Garfield
Re: [PHP-DEV] [RFC] Change behaviour of array sort functions to return a copy of the sorted array
On Sun, Oct 20, 2024, at 4:39 PM, Bob Weinand wrote: > On 20.10.2024 23:23:21, Ilija Tovilo wrote: >> Hi Bilge >> >> On Sun, Oct 20, 2024 at 10:30 PM Bilge wrote: >>> I fail to see the logic of present tense = mutate, past tense = copy. At >>> least there is a pattern to it, but I would have to look it up several >>> times before it sunk in since it is not intuitive at all. >> It's sorted, the adjective. As in, "give me a _sorted_ array", >> compared to "_sort_ this array". It's a common convention and I always >> found it intuitive. >> >> Ilija > > Hey Ilija, > > yes, I agree it's intuitive. > > However, I consider it bad to add extra functions for this behaviour. > There's very little gain in extra functions, sort(), sorted(), > shuffle(), shuffled(), etc.. > > So yeah, I'd agree on the naming *if* these were the only variation of > sorting/shuffling etc. functions. But that's not the case here. > > > I, for my part, very much like the RFC, for that it gives functionality, > which I've been missing quite some times already and is minimally invasive. > > Bob I am confused by this statement. How is "adding more functions that do exactly what they say on the tin and act in a predictable fashion" bad? It's not like we're running out of space for functions. Small, purpose-built, highly-predictable APIs that fully address a problem space are the ideal goal; the number of them is largely irrelevant. I wouldn't mind array_sorted() instead of sorted(), since it wouldn't work on iterables. But array_sort() vs sort() is just horribly confusing for no good reason, and the API itself does nothing to tell you which is which. --Larry Garfield
Re: [PHP-DEV] [RFC] Change behaviour of array sort functions to return a copy of the sorted array
On Sun, Oct 20, 2024, at 12:42 PM, Gina P. Banyard wrote: > Hello internals, > > I would like to propose a short RFC to make the return value of the > sort() and similar functions more useful: > https://wiki.php.net/rfc/array-sort-return-array > > I intend for the discussion to last 2 weeks and then open the vote. > > Best regards, > > Gina P. Banyard Like others, I'm skeptical of the behavior here not being all that clear. What several other languages do, and what I have in the plan for collections if/when they ever happen, is sort() sorts in place, while sorted() returns a new value. There's similarly reverse() (in place) and reversed() (new value returned). *sorted($arr) seems like it would be a lot less confusing, and consistent with what other languages (and hopefully future PHP) do. (I don't know what that means for array_walk(), but I don't know what that would even return anyway.) --Larry Garfield
Re: [PHP-DEV] Asymmetric visibility is a BC break
On Mon, Oct 14, 2024, at 10:27 PM, Pierre Joye wrote: > Hello, > > On Mon, Oct 14, 2024, 8:07 AM Bilge wrote: >> On 14/10/2024 01:02, Valentin Udaltsov wrote: >> > The problem is that in practice most of the PHP libraries consider >> > themselves to be compatible with newer PHP versions. >> > >> > For instance, Symfony PropertyInfo uses `"php": ">=8.2"` constraint in >> > its `composer.json`. >> >> That seems like a problem they have created for themselves. It seems an >> error to me to declare software forward-compatible with PHP versions >> that do not yet exist and thus have clearly not been tested against. >> Being as it is an error, we shouldn't consider it impinges on PHP's >> definition of a BC break. > > > As much as I like this new feature and I am more than thankful for the > work behind it, if a test in codes using a x.y version of php works but > fails in x.y+1, it is a BC break, no matter how we look at it. A php > dependency targeting x.* is very common. While it tends to be used less > frequently as the amount of issues increase, that's not necessarly a > good thing. > > In some cases it is a necessary evil (extension deprecated adding > warnings, security fix requiring a bc break, f.e.). > > However, I am very doubtful here. And I do not know if it can be > avoided while keeping the new behaviors. > > All in all, it would be great to at least agree that there is a BC > break issue, so it can be addressed according, whatever the final > decision is. > > best, > Pierre I think folks are operating with different definitions of "BC Break". Consider: // Foreign.php class Foreign { public function __construct(public string $name) {} } // My code: $f = new Foreign('beep'); $rProp = (new ReflectionObject($f))->getProperty('name'); if ($rProp->isPublic()) { $f->name = 'boop'; } Under PHP 8.0, this code works. Upgrading to PHP 8.1, this code *still works* exactly the same. Therefore, there is no BC break. Upgrading to PHP 8.4, this code *still works* exactly the same. Therefore, there is no BC break. Now, someone edits Foreign.php in 8.1 to read: class Foreign { public function __construct(public readonly string $name) {} } Now, my code will fail, because isPublic() does not guarantee "is writeable" anymore. Is this a BC break in PHP? I can see the argument either way, personally, but I tend toward no. One PHP version to the next should always be safe to upgrade an *existing* code base. Just swap out the PHP binary and it should still work the same. We want that. However, once you start modifying any part of the code (including dependencies), all bets are off. Suppose some library switched from using annotations to using attributes. Any other code that was looking for those annotations is now broken, but it would be ridiculous to accuse attributes of having broken BC in PHP. Or ancient PHP 4 code that just assumed all properties were public (which they were in PHP 4), now confronted with PHP 5 code that has private properties. Is that a PHP BC break? Not at all. And again, the relevant change here happened in PHP 8.1. This is only tangentially related to 8.4 at all, because isPublic() has not implicitly meant is-writeable anymore for three years. --Larry Garfield
Re: [PHP-DEV] Asymmetric visibility is a BC break
On Sun, Oct 13, 2024, at 9:37 PM, Valentin Udaltsov wrote: > First of all, I have already agreed above that PHP does not have a BC > break here. Now we are discussing the potential problems in the PHP > ecosystem and how they could be mitigated. Ilija and I have discussed this issue a bit. The first issue is that isPublic() technically means "does this property have the public flag set," and nothing more. Prior to 8.1, that implicitly also meant "can the property be read and written to from public scope," because of how properties worked. (And same for isProtected().) That implicit assumption became invalid in 8.1 with readonly, which stealth introduced limited and not fully designed asymmetric visibility as well as properties that could not be set multiple times from any scope. Full aviz in 8.4 doesn't change that. It just makes the previous assumption change more apparent. The fact that no one seems to have reported it as an issue until now suggests it's not a particularly widespread problem. In practice, if someone is using reflection to determine the visibility of a property, they'll be writing to it through reflection as well if at all. The best solution here is probably to just clarify the docs, which I will do as part of the aviz docs that I have already been working on. cf: https://github.com/php/doc-en/pull/3828 The second issue is that the behavior of isProtectedSet() / isPrivateSet() was not as clearly defined in the RFC as it should have been. That's on us for not being clearer, as we apologize for the oversight. Those methods follow the low level pattern of isPublic() , that is, they just report of a given flag is set, not what the implications of that flag in various contexts are. That is consistent with the rest of the reflection API, so we feel that is best left as-is. That still means the "so can I read/write this property or not?" question has no simple operation for it. Again: it never did, we just kinda sorta had it indirectly and implicitly. For that we feel the best answer, as well as least disruptive given we're in RCs, is dedicated methods as Ilija has already described that take all property behavior and context into account. (isReadable and isWriteable.) As a reminder, the concept is: $rProp->isReadable($obj); // Can this property on $obj be read from the calling scope? $rProp->isReadable($obj, 'static'); // Same as previous. $rProp->isReadable($obj, null); // Can this property on $obj be read from global scope? $rProp->isReadable($obj, Foo::class); // Can this property on $obj be read from code inside class Foo? $rProp->isWriteable($obj); // Can this property on object $obj be written from the calling scope? $rProp->isWriteable($obj, 'static'); // Same as previous. $rProp->isWriteable($obj, null); // Can this property on object $obj be written from global scope? $rProp->isWriteable($obj, Foo::class); // Can this property on object $obj be written from code inside class Foo? cf: https://github.com/php/php-src/pull/16209 (The use of null to indicate global scope is borrowed from Closure::bind(), which does the same.) These methods do runtime analysis to see if a property should be readable/writeable. Specifically: isReadable() * Checks that the property is readable from the passed scope * Checks that the property is initialized (i.e. not typed and never written to) * Checks that the property is not virtual or has a get hook isWritable() * Checks that the property is writable (respecting symmetric and asymmetric properties) from the passed scope * Checks that the property is not readonly, is not yet initialized, or is reinitializable (__clone) * Checks that the property is not virtual or has a set hook Of note, this does not absolutely guarantee that a read/write will succeed. There's at least two exceptions: One, some PHP built-in classes have effectively immutable properties but do not use `readonly` or `private(set)`. Those would not be detected here, until and unless they are updated to use the now-available mechanisms. (See, eg: https://github.com/php/php-src/issues/15309) The other is that a get or set hook may throw an exception under various circumstances. There is no way to evaluate that via reflection, so it's a gap that will necessarily always be there. Whether those methods are OK to add in the RC phase or if they should be left to early 8.5, and if they would need a formal RFC, is up to the RMs to decide. RMs, what is your preference? --Larry Garfield
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Tue, Oct 8, 2024, at 8:48 PM, Mike Schinkel wrote: >> On Oct 7, 2024, at 7:31 PM, Jim Winstead wrote: >> >> What is currently blocking content that at least one unpaid volunteer* wants >> to contribute in a way that leverages the existing technical infrastructure >> is that there is vague, unwritten policy that we don't mention third-party >> tools in the PHP documentation, except for all of the third-party tools that >> we already mention in the PHP documentation. > > I am totally with you on this, and I apologize on my part if anything > about what I said made people view it as an either-or proposition. > > Instead, I intended comments were intended to be viewed as "Yes, and..." *snip* At this time, we're not looking for yes-ands in this thread. Please stop dragging it off topic into your own pet ideas. If you really want to push them, start new threads for them and leave this one alone. --Larry Garfield
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Sun, Oct 6, 2024, at 2:33 PM, Mike Schinkel wrote: >> On Oct 5, 2024, at 10:25 PM, Larry Garfield wrote: >> >> A number of people are concerned that if we use any of the "Big Names", it >> would be interpreted as an endorsement of that project. Eg, if we rebuilt >> the main website using Laravel, the Symfony folks would feel slighted. If >> we used Symfony, the Laravel folks would get rather cross. If we used Yii, >> the Slim folks would get upset. If we used Drupal, we'd get constant "well >> why not Wordpress?" questions. Etc. > > OR, we could change the current model and consider and another approach. > > Instead of maintaining a website based on 1980s[1] technology which can > give newer developers who are interested in modern developer tools the > opinion that PHP is not for them, PHP could move to a model for its > website where it embraces "Big names" and does so on merit. *snip* While I am sympathetic to the idea of "if you want professional work done, just hire a professional," that is also vastly off topic for what we're discussing right now. The scope at the moment is much more "can we *please* tell people to use Composer? Can we *please* use PHPUnit for writing PhD and not feel guilty about it?" It's much more pedestrian and practical for the time being. --Larry Garfield
Re: [PHP-DEV] [RFC] [Discussion] Add get_declared_enums() function
On Sun, Oct 6, 2024, at 2:25 AM, Juliette Reinders Folmer wrote: > I can imagine combining the alternative approach via > get_declared_symbols() with a new symbol_exists() function like you > suggest above (with a similar slow path to deprecate and remove the old > functions). > > On the plus side, the alternative approach makes for much more > versatile functionality. In a number of the cases I looked at, the > results from various get_declared_*() functions are combined before > further processing, so having a `get-declared_symbols()` function would > allow for simplifying that code. The same can be said for the > *_exists() functions. FWIW, I'd love to have get_declared_symbols() and symbol_exists() functions, regardless of what we do with enums in particular. That's arguably a topic for another RFC, though. (And debatable if functions would count as symbols, but again, topic for another time.) --Larry Garfield
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Sat, Oct 5, 2024, at 11:27 PM, Stephen Reay wrote: >> A number of people are concerned that if we use any of the "Big Names", it >> would be interpreted as an endorsement of that project. Eg, if we rebuilt >> the main website using Laravel, the Symfony folks would feel slighted. If >> we used Symfony, the Laravel folks would get rather cross. If we used Yii, >> the Slim folks would get upset. If we used Drupal, we'd get constant "well >> why not Wordpress?" questions. Etc. >> >> While I feel that concern is sometimes over-blown, I do believe it is valid. >> Notably, the "big name communities" tend to also be complete, integrated >> solutions, and those also tend to be where there's more active competition. >> Eg, there's only one meaningful Yaml implementation the market, and two UUID >> libraries worth mentioning. But there's literally dozens of "frameworks" or >> "CMSes" to get mad at us. >> >> So banning "full" frameworks is my attempt at steering clear of the >> appearance of that kind of favoritism. Showing favoritism for Composer or >> Xdebug is, well, there's no competition to complain. PHPUnit is technically >> not the only testing framework on the market, but it has north of 90% share >> (and is used internally by some of the few others). But showing favoritism >> between Drupal, Wordpress, TYPO3, Concrete5, and Joomla gets a lot dicier. >> >> A full framework also makes maintenance potentially more challenging, as we >> it's a much larger external moving target than a UUID library that we could >> easily fork in a worst case scenario. >> >> So... I don't really have a solid, clear definition of what constitutes a >> "full framework", because in the market, there isn't one. I'm sure someone >> could make a compelling argument that Slim isn't a full framework, for >> instance, although I don't think I'd agree with it. >> >> It is inherently squishy, which is why these are intended as heuristics, not >> strict rules, and when it's unclear we can bring it to a vote via RFC, case >> by case. >> >> I'm open to better ways to define what "full" means here if anyone has >> suggestions. >> >> --Larry Garfield >> > > Hi Larry, > > Right I understand the motivation, it's just the phrasing that I think > needs to be clarified. > > From what you've said (which is kind of what I imagined you probably > meant) I think it just needs to be clarified that the "full > application" exclusion is about *web* applications, and doesn't > applying to command line tooling/utilities. > > Cheers > > Stephen Valid point. I've added another definition, and used it throughout: Libraries refers to existing third party code packages or tools, either C extensions or PHP code, maintained by someone other than the PHP Internals team. It also includes command line utilities used primarily by a developer. It may also refer to non-profit PHP ecosystem organizations, such as the PHP Foundation or PHP-FIG. Web Application refers to a “full” web framework that provides end-to-end web application capabilities, or an installable complete application. It does not refer to command line utilities used primarily by developers building applications. (Libraries are OK, Web Applications are mostly not, except in marketing where we can mention them as long as we don't play favorites.) --Larry Garfield
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Sat, Oct 5, 2024, at 12:30 PM, Stephen Reay wrote: >> On 3 Oct 2024, at 01:48, Larry Garfield wrote: >> >> Since Jim's RFC proposal was criticized for being too vague, I hereby offer >> a somewhat more prescriptive policy proposal on using 3rd party code. (With >> JIm's blessing.) It's still more heuristics than rules, but I think that's >> the right approach generally. It also includes a voting mechanism to >> resolve edge cases when they come up. >> >> I'm sure we'll bikeshed it to death, but please keep an open mind about the >> concept in the first place. PHP is more than just php-src, and that's a >> good thing. We need to catch up with that reality, while at the same time >> maintaining a reasonable neutrality about projects Internals doesn't manage >> directly. >> >> https://wiki.php.net/rfc/third-party-code >> >> *Puts on trusty flame-retardant suit* >> >> -- >> Larry Garfield >> la...@garfieldtech.com >> > > Hi Larry, > > Can you expand a bit more on this item from the exclusion list? > >> The library is a “full” application or framework. > To me that would mean anything that can be executed itself (be it a web > app, a command like tool or daemon, etc. > > But then you specifically say Composer and PHPUnit and Psalm and > PHPstan are explicitly allowed... aren't all of them "full" > applications, because they can be executed in and of themselves. > > So, can you perhaps define what you mean by "full application" a little > more clearly? > > Cheers > > Stephen A number of people are concerned that if we use any of the "Big Names", it would be interpreted as an endorsement of that project. Eg, if we rebuilt the main website using Laravel, the Symfony folks would feel slighted. If we used Symfony, the Laravel folks would get rather cross. If we used Yii, the Slim folks would get upset. If we used Drupal, we'd get constant "well why not Wordpress?" questions. Etc. While I feel that concern is sometimes over-blown, I do believe it is valid. Notably, the "big name communities" tend to also be complete, integrated solutions, and those also tend to be where there's more active competition. Eg, there's only one meaningful Yaml implementation the market, and two UUID libraries worth mentioning. But there's literally dozens of "frameworks" or "CMSes" to get mad at us. So banning "full" frameworks is my attempt at steering clear of the appearance of that kind of favoritism. Showing favoritism for Composer or Xdebug is, well, there's no competition to complain. PHPUnit is technically not the only testing framework on the market, but it has north of 90% share (and is used internally by some of the few others). But showing favoritism between Drupal, Wordpress, TYPO3, Concrete5, and Joomla gets a lot dicier. A full framework also makes maintenance potentially more challenging, as we it's a much larger external moving target than a UUID library that we could easily fork in a worst case scenario. So... I don't really have a solid, clear definition of what constitutes a "full framework", because in the market, there isn't one. I'm sure someone could make a compelling argument that Slim isn't a full framework, for instance, although I don't think I'd agree with it. It is inherently squishy, which is why these are intended as heuristics, not strict rules, and when it's unclear we can bring it to a vote via RFC, case by case. I'm open to better ways to define what "full" means here if anyone has suggestions. --Larry Garfield
Re: [PHP-DEV] [RFC] Policy on 3rd party code
On Fri, Oct 4, 2024, at 6:22 AM, Derick Rethans wrote: > On Wed, 2 Oct 2024, Larry Garfield wrote: > >> Since Jim's RFC proposal was criticized for being too vague, I hereby >> offer a somewhat more prescriptive policy proposal on using 3rd party >> code. (With JIm's blessing.) It's still more heuristics than rules, >> but I think that's the right approach generally. It also includes a >> voting mechanism to resolve edge cases when they come up. >> >> I'm sure we'll bikeshed it to death, but please keep an open mind >> about the concept in the first place. PHP is more than just php-src, >> and that's a good thing. We need to catch up with that reality, while >> at the same time maintaining a reasonable neutrality about projects >> Internals doesn't manage directly. >> >> https://wiki.php.net/rfc/third-party-code >> >> *Puts on trusty flame-retardant suit* > > | The following packages are explicitly approved for use by this RFC, as > | they meet all of the criteria above. > | > | - Xdebug > > That's not strictly true, as it doesn't have an "Approved License". It's > a nitpick, but Xdebug has "The Xdebug License" > (https://github.com/xdebug/xdebug/blob/master/LICENSE), which is the PHP > License 3.01, but with s/PHP/Xdebug. > > I've been wanting to change that for ages, but it requires approval from > all contributors, and that's not going to happen easily. > > cheers, > Derick Drat. I suppose we could list that as an exception, like Docuwiki? The design is "RFC wins over heuristic", so if people vote to approve its mention, subtleties in the license don't matter. --Larry Garfield
[PHP-DEV] [RFC] Policy on 3rd party code
Since Jim's RFC proposal was criticized for being too vague, I hereby offer a somewhat more prescriptive policy proposal on using 3rd party code. (With JIm's blessing.) It's still more heuristics than rules, but I think that's the right approach generally. It also includes a voting mechanism to resolve edge cases when they come up. I'm sure we'll bikeshed it to death, but please keep an open mind about the concept in the first place. PHP is more than just php-src, and that's a good thing. We need to catch up with that reality, while at the same time maintaining a reasonable neutrality about projects Internals doesn't manage directly. https://wiki.php.net/rfc/third-party-code *Puts on trusty flame-retardant suit* -- Larry Garfield la...@garfieldtech.com
Re: [PHP-DEV] [RFC] [Discussion] Add get_declared_enums() function
On Wed, Oct 2, 2024, at 7:27 AM, Alexandru Pătrănescu wrote: > I think my view comes from when I initially dug (15+ years ago) into > what an enum in Java is, and learned that it is just a syntactic sugar, > and a final class would be generated implementing `Comparable` and > extending an abstract class `Enum`. > > And I think in PHP that could be a similar view. And most of the > limitations we have are not impossible to create with a standard class. That is roughly the way enums are implemented in several languages, including PHP. > I think in time we might get to remove some limitations. > I, personally, don't agree with the `Stringable` related limitation. This has been discussed numerous times already. Please don't bring it up here, it's not relevant to this thread. > And also with the limitation on no state. In Java this is the simple > way to create a singleton: an enum with one case; and we can't have > this in PHP. That is what we mean by ADTs or Tagged Unions (various names for the same thing), and it's something Ilija and I have on the roadmap. It's been on the roadmap since the first enum release, but we deliberately punted it for later to keep the initial RFC manageable. It's also dependent on the pattern matching RFC, which hopefully we'll be able to bring up for discussion for 8.5. > If we remove the limitations, should we reclassify at that point enums > as classes? Enums already are classes. I don't know what reclassification you're talking about. The RFC is about adding a "get me a list of only those classes that are enums" function to PHP. Changing how Enums behave or are implemented is wildly out of scope. --Larry Garfield
Re: [PHP-DEV] Protected destructors
On Tue, Oct 1, 2024, at 2:06 PM, Rowan Tommins [IMSoP] wrote: > On Tue, 1 Oct 2024, at 19:29, Larry Garfield wrote: >> I would have said with() would be neat in PHP. :-) > > I have been considering for a while proposing Context Managers > [Python's with(), not to be confused with VisualBasic & JavaScript > unrelated feature with the same keyword]. > > My primary example use case is safe database transactions, which I've > seen implemented in PHP in two ways: > > 1) Callback style, where the code to run in a transaction has to be > wrapped in a function, usually an anonymous closure. This is often > cited as a use case for implicit capture in closures, but even with > that it adds a layer of indirection, and changes the meaning of > "return" and "yield" inside the wrapped block. > > 2) "Resource Acquisition Is Initialization" style, where the destructor > rolls back the transaction if it hasn't been committed or rolled back > manually. This requires fewer changes to the wrapped code, but as > Arnaud points out, it's not 100% reliable / predictable in PHP, due to > details of the GC. > > Context Managers present a third option, where the code in the > transaction remains a normal sequence of statements, but there is a > more explicit guarantee about what will happen when the with{} block is > exited. The Python design document has interesting background on what > they included and excluded: https://peps.python.org/pep-0343/ > > C#'s "using statement" is similar, but explicitly designed for ensuring > the correct "disposal" of an object rather than hooking entry to and > exit from a "context": > https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using > > Regards, > -- > Rowan Tommins > [IMSoP] I would support having Python-esque context managers in PHP, and would be happy to help make it happen (if research and English writing would be useful to whoever is doing the implementation). --Larry Garfield
Re: [PHP-DEV] [RFC] Change Directory class to behave like an opaque object
On Tue, Oct 1, 2024, at 4:02 PM, Nick Lockheart wrote: >> >> Hey Nick, >> >> Is this actually an issue though? \Directory would be a weird thing >> to autoload. Most people tend to autoload specific namespaces. I >> think it would be weird to autoload into the global namespace. >> >> Maybe I am wrong, and that is why I ask. >> >> — Rob > > > In a situation where people aren't using namespaces at all, it would be > normal to create your own class with a conflicting name, not knowing > there was a built-in. Which is why anyone creating a global namespace class, especially with a generic name like that, in 2024 is Doing PHP Wrong(tm). The top-level namespace has been considered "reserved" (at least de facto, if perhaps not sung from the rooftops) for... 15 years? Maybe not as long as there have been namespaces, but close to. I have no strong opinions on this RFC as I've not paid close attention to it, but "we can't introduce an unnamespaced class, that's a BC break" is simply not true, and not consistent with how Internals and the stdlib are and have been developed. --Larry Garfield
Re: [PHP-DEV] Protected destructors
On Tue, Oct 1, 2024, at 10:39 AM, K Sandvik wrote: >> On Oct 1, 2024, at 5:12 AM, Arnaud Le Blanc wrote: >> >> Some use-cases of destructors could be replaced with patterns like >> Python's with() [3], Java's try-with [4], or Go's defer [5]. > > defer would be neat in PHP. --Kent I would have said with() would be neat in PHP. :-) --Larry Garfield
Re: [PHP-DEV] Zephir, and other tangents
On Mon, Sep 23, 2024, at 1:14 AM, Mike Schinkel wrote: > I absolutely love that Larry called the question if it were technically > possible. Maybe Larry will read this and can answer the question — > since he was heavily involved with Drupal — "Would Drupal be willing to > require or at least recommend a 3rd party WASM extension vs. a bundled > one here? > https://www.drupal.org/docs/getting-started/system-requirements/php-requirements#extensions"; To clarify since I was called out by name: I have had no involvement in Drupal in 7 years, have no interest in being involved in Drupal, would be perfectly happy to see the Drupal project fail and its leadership go bankrupt (for reasons that are entirely personal/social, not technical), and thus have no insight into what Drupal would or would not be willing to require. --Larry Garfield
Re: [PHP-DEV] Zephir, and other tangents
On Fri, Sep 20, 2024, at 12:28 PM, Dennis Snell wrote: > I’m not sure why you’re singling out Automattic, since nobody from > Automattic started this thread or requested other people provide > unfunded volunteer work, or why you’re expecting a single corporate > entity to fully fund long-term planned features in the language. Is > that how PHP normally grows? I’m not familiar with the process. > > My goal in sharing here is to help better represent my own perspective > of WordPress’ needs based on what I’ve seen. It’s long been on my list > to propose a WASM RFC, but because I personally haven’t had the > priority available to get an implementation working I haven’t done so. > It’s my impression from the documentation that the purpose of these > email threads w.r.t. RFCs is to gather interest and input before any > RFC would be put together, to hold these discussions before anyone > commits any major time to it. FWIW, I feel that an embedded Wasm bridge, with a good API, would be an excellent addition and way more useful than the crappy experience of FFI. Logistical question, for those with more stdlib expertise: Since we have other extensions in php-src that only work if you install some other library as well (eg, curl), which distros pretty much take care of for us, would a small in-php-src extension that is just a thin wrapper for Wasmtime or similar be viable? Not embedding Wasmtime into the php-src code, just the extension, and it's up to the user/distro to install both so that they work. (Note: I'm not asking if you think it's a good idea, just if it's physically possible/worth discussing.) --Larry Garfield
Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)
return $new; } public function __invoke(mixed $arg): mixed { foreach ($this->steps as $step) { $arg = $step($arg); } return $arg; } operator +(\Closure $other, OperandPosition $pos): self { return match ($pos) { OperandPosition::LeftSide => self::fromArray([...$this->steps, $other]), OperandPosition::RightSide => self::fromArray([$other, ...$this->steps]), }; } } $fun = new Composed() + someFunc(...) + $obj->someMethod(...) + fn(string $a) => $a . ' (archived)' + strlen(...); $fun($input); // Calls each closure in turn. Note that there are a half-dozen libraries in the wild that do something akin to this, just much more clumsily, including in Laravel. The code above would be vastly simpler and easier to maintain and debug. ## Units Others have mentioned this before, but to make clear what it could look like: abstract readonly class MetricDistance implements MetricDistance { protected int $factor = 1; public function __construct(private int $length) {} public function +(MetricDistance $other, OperandPos $pos): self { return new self(floor(($this->length * $this->factor + $other->length * $other->factor)/$this->factor)); } public function -(MetricDistance $other, OperandPos $pos): self { return match ($pos) { OperandPosition::LeftSide => new self(floor(($this->length * $this->factor - $other->length * $other->factor)/$this->factor)), OperandPosition::RightSide => new self(floor($other->length * $other->factor - $this->length * $this->factor)/$this->factor)), }; } public function __toString(): string { return $this->length; } } readonly class Meters extends MetricDistance { protected int $factor = 1; } readonly class Kilometers extends MetricDistance { protected int $factor = 1000; } $m1 = new Meters(500); $k1 = new Kilometers(3); $m1 += $k1; print $m1; // prints 3500 $m1 + 12; // Error. 12 what? There's likely a bug in the above somewhere, but it's late and it still gets the point across for now. (Side note: The previous RFC supported abstract operator declarations, but not declarations on interfaces. That seems necessary for completeness.) ## Date and time DateTimeImmutable and DateInterval already do this, and they're not "fancy math." I consider all of the above to be reasonable, viable, and useful applications of operator overloading, none of which are fancy or esoteric math cases. Others may dislike them, stylistically. That's a subjective question, so opinions can differ. But the viability of the above cases is not disputable, so the claim that operator overloading is too niche to be worth it is, I would argue, demonstrably false. --Larry Garfield
Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)
On Tue, Sep 17, 2024, at 3:14 PM, Jordan LeDoux wrote: >> I think it's absolutely possible - and desirable - to choose a philosophical >> position on that spectrum, and use it to drive design decisions. The choice >> of "__add" vs "operator+" is one such decision. >> > > Ah, I see. I suppose I never really entertained an idea like this > because in my mind it can't even handle non-trivial math, let alone the > sorts of things that people might want to use overloads for. Once you > get past arithmetic with real numbers into almost any other kind of > math, which operators are meaningful, and what they mean exactly, > begins to depend a lot on context. This is why I felt like even if we > were limiting the use cases to math projects, things like commutativity > should not necessarily be enforced. > > The line `$a + $b` and `$b + $a` are SUPPOSED to give different results > for certain types of math objects, for instance. The line `$a - $b` and > `$b - $a` more obviously give different results to most people, because > subtraction is not commutative even for real numbers. > > My personal opinion is that the RFC should not assume the overloads are > used in a particular domain (like real number arithmetic), and thus > should not attempt to enforce these kinds of behaviors. But, opinions > like this are actually what I was hoping to receive from this thread. > This could be the way forward that voters are more interested in, even > if it wouldn't be my own first preference as it will be highly limiting > to the applicable domains. I'm not sure where exactly in this thread to put this, so I'm putting it here... Rowan makes an interesting point regarding operators vs operations. In particular, the way the <=> logic is defined, it is defining an operation: comparison. Using it for anything other than ordering comparison is simply not viable, nor useful. It's defining a custom implementation if a specific pre-existing action. For all the other operators, the logic seems to be defined for an operator, the behavior of which is "whatever makes sense in your use case, idk." That is, to use Rowan's distinction, a philosophically different approach. Not a bad one, necessarily. In fact, I think it's a very good one. But, as they are different, perhaps that suggests that comparison should instead not be implemented as an operator overload per se, but as a named magic method. The existing logic for it is, I think, fine, but it's a fair criticism that you're not defining "what happens for a method-ish named <=>", you're defining "how do objects compare." So I think it would make sense to replace the <=> override with a `__compare(mixed $other): int`, which any class could implement to opt-in to ordering comparisons, and thus work with <, >, ==, <=>, etc. (And, importantly, still keep the "specify the type(s) you want to be able to compare against" logic, already defined.) A similar argument could probably be made for ==, though I've not fully thought through if I agree or not. Again, I think the previously defined logic is fine. It would be just changing the spelling from `operator ==(mixed $other): bool` to `public function __equals(mixed $other): bool`. But that again better communicates that it is a core language behavior that is being overridden, rather than an arbitrarily defined symbol-function-thing with domain-specific meaning. There was an RFC for a Comparable interface back in the stone age (2010), but it looks like it never went to a vote: https://wiki.php.net/rfc/comparable Arguably, this would then make more sense as a stand-alone RFC that happens to reuse a lot of the existing code and logic defined for operator overloads, which are all still just as valid. That does not apply to the arithmetic, bitwise, or logic operators. Overriding + or / for a specific domain is not the same, as you're not hooking into engine behavior the way <=> or == are. For those, I'd prefer to stick to the current/previous implementation, with the `operator` keyword, for reasons I explained before. Jordan, does that distinction make sense to you? --Larry Garfield
Re: [PHP-DEV] Re: Which IDE do you recommend for php-src development?
On Mon, Sep 16, 2024, at 7:06 PM, Hans Henrik Bergan wrote: > +1 for VSCode, I use it practically everywhere these days, > HTML/Javascript/TypeScript/PHP/C/C++/Python/Lua, all on VSCode. > > On Mon, 16 Sept 2024 at 13:07, Barel wrote: >> >> On Sat, 14 Sept 2024 at 23:44, Barel wrote: >>> >>> Hi >>> >>> For C/C++ development I usually use CLion from Jetbrains but I tried to use >>> it with php-src and was unable to get it to work properly. CLion really >>> insists on using CMake and has only quite limited support for makefiles. >>> After trying to get it to work unsuccessfully I am ready to try something >>> else. >>> >>> So which IDE would you recommend for php-src development? I understand that >>> people probably have many different preferences but I wondered if there was >>> something that most php internals developers used. One important feature >>> would be to easily work with the project running on a docker container >>> >>> Thanks in advance! >>> >>> Carlos >> >> >> Answering myself in case someone finds this useful in the future. >> >> Several people recommended VSCode so decided to give it a try. I found this >> guide which describes very well what you need to do to get VSCode working >> for a php-src project hosted in a docker container. Works brilliantly, I am >> able to work with the code in the container using all VSCode features, >> including debugging with GDB. Nice! >> >> https://bogomolov.tech/php-extension-development/ Please please someone capture the details of this thread somewhere on the wiki or php.net, or maybe even in the php-src repo itself. We really need to have good "how to get from git clone to a working C debugger" instructions. --Larry Garfield
Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)
On Mon, Sep 16, 2024, at 2:47 AM, Jordan LeDoux wrote: > On Sun, Sep 15, 2024 at 9:12 PM Larry Garfield wrote: >> >> The "multiply by -1 for <=>" bit I don't fully understand the point of. The >> RFC tries to explain, but I don't quite grok it. >> > > I will perhaps respond with more detail to the rest of your message > later, but I wanted to address this specifically, because I also feel > that the original RFC I wrote didn't explain that well. The situation > this bit was referring to is as follows: > > You have an object Foo that implements an overload for the `<=>` > operator. The proposed signature for `<=>` was simply: > > `operator <=>($other): int` > > This operator did not have an `OperandPosition` argument. The reason > for this was to prevent developers from creating situations where `5 > > $foo` is true and `5 < $foo` is true. Instead, internally it did the > same sort of reordering that the engine currently does. It calls the > implementation the developer defined, and then checks if the object > that the implementation was called from was on the right side of the > operator. If it was, then it multiplies the result of the user defined > overload by -1. Multiplying the result of the overload ONLY when the > overload is called for the right side is equivalent to flipping the > order. So `5 > $foo` is multiplied by -1 and then evaluated as if it > were `$foo < 5`. This is an edge case, but it was an important one in > my mind. > > It would be entirely unnecessary if we allowed the `<=>` overload to > know what position it was in, but that would enable lots of developer > mistakes in my mind for no real gain. Instead, developers should just > implement the overload as if the object assumes it will always be > called from the left side of the comparison. > > Jordan OK, that makes a lot more sense. Reading through the text of the RFC, I didn't catch that it only multiplied by -1 if the comparing object was on the right. The implementation is fine, but if you do for a second round, making that a bit clearer would be helpful. --Larry Garfield
Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)
feel that there is ANY design, version, or implementation of > operator overloads possible that you would support and be in favor of, > regardless of whether it matches the approach taken previously? If so, > can you describe any of the core ideas you feel are most important? I was fairly happy with the previous version, so proposing that as-is would have my vote. I would probably oppose including arbitrary symbol overloading at this time. To me, the most important factors are: 1. It's type-safe, and leverages the type system to "make invalid states unrepresentable" as much as possible. (I'd put the rules around <=> into this category.) 2. It allows me to opt-in piecemeal to just those operators that make sense. 3. The performance overhead compared to using a method is minimal. 4. It is future-compatible with further language evolution, to the extent possible. (The `operator` keyword helps here.) I'd love to see this brought up again, and hope there is sufficient interest to do so. --Larry Garfield
Re: [PHP-DEV] bikeshed: Typed Aliases
On Mon, Sep 9, 2024, at 4:35 PM, Rowan Tommins [IMSoP] wrote: > On 09/09/2024 19:41, Mike Schinkel wrote: > >> Referencing prior art (e.g. Go) PHP could allow int literals — e.g. `1`, >> `47`, etc. — to be passed to typedefs derived from ints but require int >> variables to be typecast to the required type. Same for string literals. > > That's an interesting compromise, worth considering. I have concerns about this. Mainly, it depends on what we would want a typeef to *do*. Eg, if it's just an alternate name, then maybe. If, however, typedefs allow other functionality -- such as validation, additional methods, etc. -- then primitive -> typeef is not a guaranteed total function. Eg; typedef UserId: string is /\s{3}-\s{4}/ { public function groupId(): string { return substr($this, 3); } } Maybe that particular functionality makes sense to do, maybe not, that's a separate discussion. My point for now is just that there are typedef approaches where auto-up-casting would be frequently invalid, and probably also designs where auto-down-casting would be invalid (or possibly valid). For now, we should keep all options on the table until we decide which options we want to make impossible. >> In Go you cannot add or subtract on a typedef without casting to the >> underlying type. I would definitely prefer that to be relaxed, but only >> if it is relaxed via an explicit opt-in, e.g. something maybe like >> this: >> >> typedef UserId: int operations: +, -, *, /; >> typedef UserName: string operations: .; Not to go further down this rabbit hole than is necessary, but I would much rather see operator overloads adopted, along the lines of Jordan's previous RFC, and let typedefs implement that if them if sensible. There's probably yet another research project to do here. I'd volunteer, but I now have a newborn taking up most of my time. :-) --Larry Garfield
Re: [PHP-DEV] bikeshed: Typed Aliases
On Sat, Sep 7, 2024, at 12:07 PM, Rowan Tommins [IMSoP] wrote: > On 7 September 2024 17:23:13 BST, Davey Shafik wrote: >> >>My point is that if you talk about type DEFs, you now have this feature where >>you can input one type and get something that encapsulates it, and it seems >>weird that enums would LOOK similar In type hint usage and function >>differently. > > Personally, I would prefer to go the other way: make typedefs, like > enums, something you explicitly construct / cast to, rather than > something that implicitly coerces any compatible value. > > Like enums, I would want to use typedefs to prevent accidental mixing > of values (e.g. a name where a reference number was expected, or a size > in pixels where a size in centimetres was expected). That use is > compromised if every scalar value is silently accepted for any matching > typedef. > > Regards, > Rowan Tommins > [IMSoP] There's a couple of different use cases floating around close to each other here. One is a type *alias*, which is just "a way to type less." The other is a type *def*, which creates a new for-reals type that you can check at runtime. They are closely related, but serve different purposes. While an alias could make sense file-local or app-wide, in practice a def only makes sense app-wide. Whether we want to have one or the other or both is a subjective question. Personally I'd be fine with both, as I see them serving different purposes. eg: typealias Foo: Bar|Baz; Foo is now a compile time copy-paste for Bar|Baz, meaning this is totally valid: class A { public Foo $a; } class B { public Bar|Baz $a; } The other direction is: typedef UserId: int; UserID is now an object that consists of just an int, but can be type checked against. What's unclear is if you can do other int-y things to them (add, subtract, etc.), or if it's really just a shorthand for readonly class UserId { public function __construct(public int $value) {} } I could see an argument for either. If we had operator overloads, I would absolutely go for the latter; make all of those other int-y things opt-in. Once we get pattern matching, as noted a few months ago, it could be quite powerful to allow patterns as a validation on a typedef of that sort. typedef UserId: int is >0; Though that opens up all kinds of interesting questions about a typedef based on another typedef, if that's a form of inheritance or not, etc. Again, I'm not sure if Rob wants to go there or not, but it's a place my brain has gone before. :-) We may want to focus just on aliases for now, but design them in such a way that they do not cause an issue for typedefs in the future. (Eg, using the `typealias` keyword instead of just `type`.) --Larry Garfield
Re: [PHP-DEV] bikeshed: Typed Aliases
On Fri, Sep 6, 2024, at 7:46 PM, Davey Shafik wrote: > My main struggle with this is readability. As much as I want custom > types (and type aliases is a good chunk of the way there), the main > issue I have is understanding what the valid inputs are: > > function foo(Status $string): void { } > > How do I know that Status is a) not a class, b) that I can fulfill the > requirement with a string, and/or maybe any object with __toString(), > or maybe it’s ints? Or objects or enums? > > Even with file-local aliases (which I would definitely prefer to avoid) > we will most likely rely on developer tooling (e.g. IDEs and static > analyzers) to inform the developer what the right input types are. > > I would very much prefer to either go all in with an Enum-like (which > means that we can hang methods on to the value) or we need to > distinguish between type hints for class-likes and type hints for > not-class-likes (*Bar anyone?). > > Expanding on type-class-likes: within the type methods, $this->value > would refer to the original value, any operators would follow the > _same_ rules as either the original values type (e.g. $int = 4; $string > = “foo”; $int . $string == “4foo", or call __toString() in all the > normal places for strings if defined). > > > type Stringable: string|int { > public function __toString(): string > { > return (string) $this->value; // original value > } > > // Add Stringable methods here > }. Methods on typedefs was the sort of "other stuff classes do" that I was trying to avoid getting into right now. :-) Mainly because I can totally see how it's tempting, but also have no idea what it would mean from a type-theoretic perspective. It would only make sense if we're talking type DEFs, not type ALIASes. I'm not against that, and it could be fun to try and think through the type theoretical implications, but I don't think that's what Rob was going for so I didn't want to take that side quest just yet. (Though if he's OK with it, I'm OK with it.) > So, with that in mind… I’d also like to open up the ability for Enums > to be fulfilled by the backed value, that is: This is 1. Off topic for type aliases. 2. Has been discussed numerous times before. Enums are not equivalent to their backing value. The backing value is a standardized-serialization value. Nothing more. A string-backed enum is not a string, and a string is not a string-backed enum. Trying to use an enum as transparently equivalent to its backing value is a categorical error and belies a misunderstanding of what Enums are. cf: https://peakd.com/hive-168588/@crell/on-the-use-of-enums --Larry Garfield
Re: [PHP-DEV] bikeshed: Typed Aliases
On Sat, Sep 7, 2024, at 7:42 AM, Mike Schinkel wrote: >> On Sep 6, 2024, at 4:45 PM, Larry Garfield wrote: >> Aliases can then be used only in parameter, return, property, and instanceof >> types. Extends and implements are out of scope entirely. > > Is there a strong technical reason why extends and implements should be > out of scope? > > There is definite utility for this, to create a local alias in a > namespace that can be used throughout the namespace rather than having > to refer to the external namespace in many different places. Because it quickly can produce nonsensical syntax. class A {} class B {} typealias AB: A|B; // This is logically nonsensical. class C extends AB {} While there are edge cases where that might be logical (if A and B are interfaces and &-ed together, then it's kinda sorta the same as C implements A, B), separating those out and allowing just that subset sounds like a lot of work for dubious gain, and introducing surprise inconsistency. Better to just avoid that entirely. --Larry Garfield
Re: [PHP-DEV] bikeshed: Typed Aliases
On Fri, Sep 6, 2024, at 6:27 PM, Rob Landers wrote: >> I suspect there's also other edge case bits to worry about, particularly if >> trying to combine a complex alias with a complex type, which could lead to >> violating the DNF rule. For example: > > Oh, DNF is the bane of my existence with this RFC—I don't want to mess > this up. I'll see you at the end of the example, though. > >> >> typealias Foo: (Bar&Baz)|Beep; >> >> use (Bar&Baz)|Beep as Foo; >> >> function narf(Foo&Stringable $s) {} >> >> With the compile time approach, that would expand to >> `(Bar&Baz)|Beep&Stringable`, which is not a valid type def. > > I can see how you arrived at this, but I think you may have missed a > step, since the entirety of Foo will be &'d with Stringable. > > Foo = (Bar & Baz) | Beep > > want: (Foo) & Stringable > > expand Foo: ((Bar & Baz) | Beep) & Stringable > > Which can be reduced to the following in proper DNF (at least, it > compiles—https://3v4l.org/0bMlP): > > (Beep & Stringable) | (Bar & Baz & Stringable) > > It's probably a good idea to update the RFC explaining how expansion works. Woof. We're not "fixingup" anyone's DNF elsewhere. I cannot speak for everyone, but I'd be perfectly fine not doing any magic fixing for now, and then debating separately if we should do it more generally. Just doing it for aliases doesn't seem like the best plan. --Larry Garfield
Re: [PHP-DEV] bikeshed: Typed Aliases
s have all sorts of other things they do, but that is probably too complex scope creepy to get into here so I will not go further than that mention. I suspect there's also other edge case bits to worry about, particularly if trying to combine a complex alias with a complex type, which could lead to violating the DNF rule. For example: typealias Foo: (Bar&Baz)|Beep; use (Bar&Baz)|Beep as Foo; function narf(Foo&Stringable $s) {} With the compile time approach, that would expand to `(Bar&Baz)|Beep&Stringable`, which is not a valid type def. With the runtime approach, I don't know if that could be handled gracefully or if it would still cause an error. I'm not sure what the right solution is on this one, just pointing it out as a thing to resolve. --Larry Garfield
Re: [PHP-DEV] [RFC] [Discussion] Add WHATWG compliant URL parsing API
On Mon, Aug 26, 2024, at 2:40 AM, Máté Kocsis wrote: > Hi Ignace, Niels, > > Sorry for being silent for so long, I was working hard on the > implementation besides some summer activities :) I can say that I had > really good progress in the last month and now I think (hope) that I > managed to address most of the concerns/suggestions people mentioned > in this thread. To summarize the most important changes: I'm not fluent enough in the different parsing styles to comment on the difference there. I do have concerns about the class design, though. Given the improvements to the language, the accessor methods offer zero benefit at all. Public-read properties (readonly or otherwise) would be faster and offer no less of a guarantee. If you want to allow someone to extend the class and provide some custom logic, use aviz instead of readonly and extenders can use hooks instead of the methods. The getters don't offer any value anymore. It took me a while to realize that, I think, the fromWhatWg() method is using an in/out parameter for error handling. That is an insta-no on my part. in/out reference parameters make sense in C, maybe C++, and basically nowhere else. I view them as a code smell everywhere they're used in PHP. Better alternatives include exceptions or union returns. It looks like you've removed the with*() methods. Why? That means it cannot be used as a builder mechanism, which is plenty valuable. (Though could be an issue with query as a string vs array.) The WhatWgError looks to me like it's begging to be an Enum. I am confused by the new ini value. It's for use in cases where you're NOT parsing the URL yourself, but relying on some other extension that does URL parsing internally as a side effect? As usual, I am not a fan of an ini setting, but I cannot think of a different alternative off hand. --Larry Garfield
Re: [PHP-DEV] [Discussion] Implementing interfaces via traits
experience, it also introduces > complexity in how interfaces are used. To alleviate this, the `default` > keyword could be explicitly used to mark default methods, making it > easier for developers to understand and manage. For example: > > interface I1 { > `default public function foo(): int { > return \PHP_INT_MAX; > } > } > ` > This explicit marking not only clarifies the intention behind the > method but also aids in distinguishing between regular and default > methods, simplifying the mental model required to work with interfaces. How? All I see here is another keyword I have to use. It doesn't do anything extra for me as a consumer of that interface. It doesn't add disambiguation to the language, either for the engine or human readers (as the presence of the body does that already). It just gives me 8 more characters to type. > Just thinking out loud here - looking forward to hearing some thoughts. My thought is we should just pass Default Interface Methods and be done with it. :-) --Larry Garfield
Re: [PHP-DEV] [RFC] [Discussion] Using and Mentioning Third-party Packages in PHP Documentation and Web Projects
On Wed, Aug 28, 2024, at 2:51 AM, John Coggeshall wrote: >> And that is how you will find that the "new" languages will "win". If we >> don't promote how modern PHP Development works, then there will be more >> "PHP, a fractal of bad design" articles to come for decades. >> >> We *must* do better than this. It probably doesn't all need to be in the >> documentation (doc-en), but it absolutely belongs on our website. >> > > Hear Hear Derick!! > > I am not advocating that php.net put its finger on the scale in favor > of Laravel over others with this comment, but why php.net does not have > a documentation analog similar to how Laravel's documentation is set up > is beyond me. Useful installation instructions, sections on "How do I > do database stuff", "Security", "Filtering Data", "Installing third > party packages" etc... there are too many people who have embedded in > their brains that PHP is a badly designed language because we don't > teach or even advertise to people how to write good PHP code... as > others have mentioned as an example, the lack of even a mention of > composer on php.net is mind-blowing. > > As Derick said, back 20+ years ago PHP had amazing documentation for > the times -- miles ahead IMO than most open source projects. But the > world has moved on, developers want and need higher level documentation > that is more opinionated on not just the dry APIs available you might > use to connect to a database (for example), but how to properly connect > to a database. Back 20 years ago we had companies like Zend around who > devoted considerable resources to filling that gap for the community > (along with O'Reilly, etc.) but those entities are gone now and it is > up to the project to pick up the slack. > > I also think it's a mistake to get too caught up with the concept of > "endorsements" and people worrying that "oh gosh if php.net talks about > Laravel and Zend Framework then that means something bad for XYZ > framework" (pick your favoriate techs here). It's easily solved by > having a section on "Popular PHP Frameworks" that explains the concept > that PHP as a language doesn't embrace any particular framework, the > importance that you do generally want to embrace a framework to do > anything serious, and provide a list of popular ones that people > commonly turn to when building their apps. As for using a framework or > any other PHP-related tech in the project's codebases... I think we're > grossly overestimating how much weight that decision would carry with > the PHP community at large. Short of the PHP Project stating "X is the > official framework of PHP" (and especially if we say "We don't have an > official framework but here are good options that are very popular" > instead), the concern over the appearance of endorsements at this point > is really an invented issue rooted at least in part by historic > concerns that simply don't exist anymore. > > Coogle What a couple of people have touched on is that that all we have right now is a Reference, which is only one kind of documentation. The common zeitgeist these days says there's 4: https://diataxis.fr/ * Tutorials * How-to guides * Explanation * Reference We have a reference with gaps, and that's about it. In practice, it will be functionally impossible to write a meaningful tutorial or how-to guide that never mentions anything but php-src-provided code. Or at least the result would be sub-standard and doing the reader a disservice. I don't think I'd support a list of "popular" frameworks, but mentioning Composer, Xdebug, and PHPUnit seems a requirement for a useful modern tutorial. Admittedly, the docs team is very under-resourced right now and even the reference section has not-small holes, making maintaining even more types of documentation a potential challenge. That's something the Foundation could possibly help with. But that's not the topic at hand: The topic at hand is just "look, we should be able to mention Composer, Xdebug, and PHPUnit, OK?" On which I very much am in agreement. --Larry Garfield
Re: [PHP-DEV] [RFC] [Discussion] Using and Mentioning Third-party Packages in PHP Documentation and Web Projects
On Mon, Aug 26, 2024, at 1:06 PM, Bob Weinand wrote: > Hey Jim, > > On 26.8.2024 19:44:18, Jim Winstead wrote: >> Hi, >> >> Another RFC around process: >> https://wiki.php.net/rfc/web-and-doc-use-not-endorsement >> >> Feedback would be appreciated. My intention is to start voting on September >> 9th unless there is still ongoing discussion. >> >> Thanks. >> >> Jim > > > Thanks for bringing this up - I also suggest that we make this a binary > choice - either we adopt the proposed language or its opposite. > > I.e. a rejection of this should codify that statement in the negative. > > > > I do in particular reject the notion that we should document > third-party projects (usage for our infra is fine). > > The point of the PHP documentation is to describe the PHP runtime and > PECL extensions, which are both officially distributed through php.net. > > Anything not related to these does not belong into the manual, much > less into core documentation (like language/oop5 autoload.xml, to take > the example from https://github.com/php/doc-en/pull/3677/files). > > > > Changing this current unwritten rule is an invitation to implicitly > promote specific projects. The question is really where does it end? > Would we for example also mention PSRs as "widely followed guidelines > for interoperability" or something? It's a strong invitation for some > scope creep. > > As such I strongly condemn the idea of inclusion of this guideline. > > > > There are, ultimately, enough ways for people to learn about the PHP > ecosystem, the php.net documentation is none of them. If I go to > php.net, it's because I want to learn about the runtime, not its > ecosystem. There's two separate questions here, I think, which should probably be addressed separately. One is whether PHP.net code can *use* third party libraries (and be open about it). Eg, would it be OK if Phd (the documentation compiler) used Composer for autoloading? Used symfony/serializer or crell/serde in some way? Used ramsey/uuid as an internal implementation detail? Right now, the answer is de facto no, with some unclear exceptions. I very firmly believe the answer should be a strong YES, or at least a "mostly", because doing otherwise hamstrings our ability to actually do the much-needed work of keeping the infra going. The other is whether the documentation should recognize the rest of the ecosystem, or be "just" "things in the php org on Github." I can definitely see the potential for scope creep here, and we should be mindful of that, but at the same time, having an official first-party "where to start with the ecosystem" place is extremely valuable! Sending someone into PHP without recognizing the existence of Composer, which has basically no competition, is doing them a gross disservice. Telling them about PHPUnit, which is overwhelmingly the most popular testing system but there are others (mostly built on top of it), I would lean yes but I can see the argument against. Recommending a template engine and listing just Twig and Blade but not Latte, for example, I can totally see where that becomes an issue and why we wouldn't want to do that. My recommendation on the GitHub thread was, and still is, to make it a one-off vote in each case. We had a one-off vote to recognize the Foundation on php.net and direct people to it. I'd favor a one-off vote to allow talking about Composer/Packagist in the docs, and I would vote yes on it. I'd probably vote no for a one-off vote to mention Twig. PHP.net is the starting point for people in the PHP ecosystem, good or bad. We don't need to take ownership of the whole ecosystem or documentation therein, but at least providing jumping off points to obvious sources (Composer/Packagist, phptherightway.com, etc.) would be doing a good service for our users. --Larry Garfield
Re: [PHP-DEV] [RFC] Default expression
On Mon, Aug 26, 2024, at 6:36 AM, Jakob Givoni wrote: > On Mon, Aug 26, 2024 at 12:49 PM Rowan Tommins [IMSoP] > wrote: >> On Mon, 26 Aug 2024, at 10:14, Bilge wrote: >> > You're absolutely right, I would be interested to see any viable patch >> > that effectively implements a set of restrictions on how `default` may >> > be used. Requesting it be done at the parser level was not meant as a >> > gotcha, that's just how I (with my lack of experience) would have >> > approached it, but certainly trapping cases in the compiler is equally, >> > if not more valid and/or practical. >> >> Another approach that occurred to me was in the executor: rather than >> evaluating to the default value immediately, "default" could resolve to a >> special value, essentially wrapping the reflection parameter info. Then when >> the function is actually called, it would be "unboxed" and the actual value >> fetched, but use in any other context would be a type error. >> >> That would allow arbitrarily complex expressions to resolve to "default", >> but not perform any operations on it - a bit like propagating sqrt(-1) >> through an engineering formula where you know it will be cancelled out >> eventually. >> > > I 100% agree with this. > "default" should not evaluate to a value before sending it as an > argument to the function or method. > I understand from what the RFC author wrote a while ago that doing so > (evaluating to the actual default value using reflection) was the > easier and perhaps only viable way at the moment, but if that's the > case, I don't think the value of this RFC justifies doing something > like that, which to me seems like a hack. > > For those already expressing interest in being able to modify a binary > flag default parameter using this "trick", I still don't think it > justifies this RFC. In my opinion, functions that accept multiple > arbitrary options by compressing them into a binary flag have a badly > designed interface to begin with. > > So, my 10c: Make "default" a pure keyword / immutable value if > possible, or reconsider whether this feature is really worth the fuss. The problem here is that `foo(default | ADDITIONAL_FLAG)` is so far the most compelling use case I've seen for this feature. It's really one of only two I see myself possibly using, frankly. So a limitation that would disallow that pattern would render the RFC almost useless. The other compelling case would be the rare occasions where today you'd do something like this: if ($user_provided_value) { foo($beep, $user_provided_value); } else { foo($beep); } Which this RFC would allow to be collapsed into foo($beep, $user_provided_value ?: default); So far those are the two use cases I can realistically see being helpful, and I acknowledge both are. I recognize that "limiting the allowed expression structures arbitrarily is way harder than it sounds" is a valid argument as well. At the same time, John C has offered some valid examples of cases where it would open up additional footguns, and we want to minimize those in general. Those shouldn't be ignored, either. At the moment I'm on the fence on this RFC. I could go either way right now, so I'm watching to see how it develops. --Larry Garfield
Re: [PHP-DEV] State of Generics and Collections
On Mon, Aug 19, 2024, at 12:08 PM, Derick Rethans wrote: > Hi! > > Arnaud, Larry, and I have been working on an article describing the > state of generics and collections, and related "experiments". > > You can find this article on the PHP Foundation's Blog: > https://thephp.foundation/blog/2024/08/19/state-of-generics-and-collections/ > > cheers, > Derick To offer my own answers to the questions posed: * I am against erased generics in the language, on the grounds that we already have them via docblocks and user-space tooling. Pushing the entire ecosystem to move that existing syntax into another existing syntax that doesn't really offer the user anything new is not worth the effort or disruption it would cause. Reified, enforced generics would be worth the hassle. * Even if I could be convinced of erased generics as a stop-gap, I would want to see a official, supported, first-party support for validating them in the PHP linter command, or similar. If that is surprisingly hard (it may be), then that would preclude erased generics for me. * I am open to punting on type inference, or having only limited type inference for now (eg, leaving out union types). Primarily, doing so would be forward-compatible. Saying for now that you must type `foo(new A())` even if it's redundant doesn't preclude the language in the future allowing `foo(new A())` that figures out the generic type for you, and the explicit code would still continue to work indefinitely. So this seems like an area that is safe to allow to grow in the future. * I am also OK if there is a (small) performance hit for generic code, or for especially esoteric generic code. Eg, if `new Foo` has a 1% performance hit vs `new Foo`, and `new Foo` has a 5% performance hit, I can live with that. `new Foo` is a zany edge case anyway, so if that costs a bit more, I'm fine. It would not be fine if adding generics made `new Foo` 30% slower, or if `new Foo` was 30% slower than the non-generic version. * My sense at the moment is that in/out markers for variance would not be a blocker, so I'd prefer to include those from the start. That's caveated on them not being a blocker; mainly I want to make sure we ensure they can be done without breaking things in the future, and I suspect the difference between "make sure we can do it" and "just do it" is small. (I could be wrong on that, of course.) * I feel the same about `class Foo` (Foo is generic over A, but A must implement the Something interface): We should make sure it's doable, and I suspect verifying that is the same as just doing it, so let's just do it. But if we can verify but it will be a lot more work to do, then we could postpone that. * I could deal with the custom collection syntax, but I'd much rather have real reified generics and then build on top of that. That would be better for everyone. I'm willing to wait for it. (That gives me more time to design collections anyway. :-) ) --Larry Garfield
Re: [PHP-DEV] [RFC] Default expression
On Sun, Aug 25, 2024, at 10:29 AM, Bilge wrote: > On 25/08/2024 14:35, Larry Garfield wrote: >> The approach here seems reasonable overall. The mental model I have from >> the RFC is "yoink the default value out of the function, drop it into this >> expression embedded in the function call, and let the chips fall where they >> may." Is that about accurate? Yes, as it happens. That is the approach we >> took, because the alternative would have been changing how values are sent >> to functions, which would have required a lot more changes to the engine >> with no clear benefit. Internally it literally calls the reflection API, but >> a low-level call, that elides the class instantiation and unnecessary hoops >> of the public interface that would just slow it down. My main holdup is the >> need. I... can't recall ever having a situation where this is something I >> needed. Some of the examples show valid use cases (eg, the "default plus >> this binary flag" example), but again, I've never actually run into that >> myself in practice. That's fine. Not everyone will have such a need, and of >> those that do, I'm willing to bet it will be rare or uncommon at best. But >> for those times it is needed, the frequency by which it is needed in no way >> diminishes its usefulness. I rarely use `goto` but that doesn't mean we >> shouldn't have the feature. My other concern is the list of supported >> expression types. I understand how the implementation would naturally make >> all of those syntactically valid, but it seems many of them, if not most, >> are semantically nonsensical. Eg, `default > 1` would take a presumably >> numeric default value and output a boolean, which should really never be >> type compatible with the function being called. (A param type of int|bool >> is a code smell at best, and a fatal waiting to happen at worst.) In >> practice, I think a majority of those expressions would be logically >> nonsensical, so I wonder if it would be better to only allow a few >> reasonable ones and block the others, to keep people from thinking >> nonsensical code would do something useful. > Since you're not the only one raising this, I will address it, but just > to say there is no good reason, in my mind, to ever prohibit the > expressiveness. To quote Rob > >>I'm reasonably certain you can write nonsensical PHP without this feature. I >>don't think we should be the nanny of developers. See, I approach it from an entirely different philosophical perspective: To the extent possible, the language and compiler should prevent you from doing stupid things, or at least make doing stupid things harder. This is the design philosophy behind, well, most good user interfaces. It's why it's good that US and EU power outlets are different, because they run different voltages, and blindly plugging one into the other can cause damage or death. This is the design philosophy behind all type systems: Make illogical or dangerous or "we know it can't work" code paths a compile error, or even impossible to express at all. This is the design philosophy behind password_hash() and friends: The easy behavior is, 99% of the time, the right one, so doing the "right thing" is easy. Doing something dumb (like explicitly setting password_hash() to use md5 or something) may be possible, but it requires extra work to be dumb. Good design makes the easy path the safe path. Now, certainly, the definition of "stupid things" is subjective and squishy, and reasonable people can disagree on where that threshold is. That's what a robust discussion is for, to figure out what qualifies as a "stupid thing" in this case. Rob has shown some possible, hypothetical uses for some of the seemingly silly possible combinations, which may or may not carry weight with people. But there are others that are still unjustified, so for now, I would still put "default != 5" into the "stupid things" category, for example. As you've noted, this is already applicable only in some edge cases to begin with, so enabling edge cases of edge cases that only maybe make sense if you squint is very likely in the "stupid things" territory. > I fully agree with that sentiment. It seems to be biting me that I went > to the trouble of listing out every permutation of what *expression* > means where perhaps this criticism would not have been levied at all > had I chosen not to do so. >From one RFC author to another, it's better to make that list explicitly and >let us collectively think through the logic of it than to be light on details >and not realize what will break until later. We've had RFCs that did that, >and it caused problems. The discussion can absolutely be frustrating (boy do >I know), but the language is better for it. So I'm glad you did call it out >so we could have this discussion. --Larry Garfield
Re: [PHP-DEV] [RFC] Default expression
On Sat, Aug 24, 2024, at 11:49 AM, Bilge wrote: > Hi gang, > > New RFC just dropped: https://wiki.php.net/rfc/default_expression. I > think some of you might enjoy this one. Hit me with any feedback. > > This one already comes complete with working implementation that I've > been cooking for a little while. Considering I don't know C or PHP > internals, one might think implementing this feature would be > prohibitively difficult, but considering the amount of help and guidance > I received from Ilija, Bob and others, it would be truer to say it would > have been more difficult to fail! Huge thanks to them. > > Cheers, > Bilge I am still not fully sold on this, but I like it a lot better than the previous attempt at a default keyword. It's good that you mention named arguments, as those do replace like 95% of the use cases for "put default here" in potential function calls, and the ones it doesn't, you call out explicitly as the justification for this RFC. The approach here seems reasonable overall. The mental model I have from the RFC is "yoink the default value out of the function, drop it into this expression embedded in the function call, and let the chips fall where they may." Is that about accurate? My main holdup is the need. I... can't recall ever having a situation where this is something I needed. Some of the examples show valid use cases (eg, the "default plus this binary flag" example), but again, I've never actually run into that myself in practice. My other concern is the list of supported expression types. I understand how the implementation would naturally make all of those syntactically valid, but it seems many of them, if not most, are semantically nonsensical. Eg, `default > 1` would take a presumably numeric default value and output a boolean, which should really never be type compatible with the function being called. (A param type of int|bool is a code smell at best, and a fatal waiting to happen at worst.) In practice, I think a majority of those expressions would be logically nonsensical, so I wonder if it would be better to only allow a few reasonable ones and block the others, to keep people from thinking nonsensical code would do something useful. --Larry Garfield
Re: [PHP-DEV] State of Generics and Collections
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 >> 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 and supporting Foo>. The nesting isn't the hard part. The hard part is not having to type Foo 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 tr
Re: [PHP-DEV] State of Generics and Collections
On Fri, Aug 23, 2024, at 6:48 AM, Roman Pronskiy wrote: > On Mon, Aug 19, 2024 at 7:11 PM Derick Rethans wrote: >> >> Arnaud, Larry, and I have been working on an article describing the >> state of generics and collections, and related "experiments". >> >> You can find this article on the PHP Foundation's Blog: >> https://thephp.foundation/blog/2024/08/19/state-of-generics-and-collections/ > > Thank you Arnaud, Derick, Larry for the article. > > Do you consider the path of not adding generics to the core at all? In > fact, this path is implicitly taken during the last years. So maybe it > makes sense to enforce that status quo? > > Potential steps: > - Make the current status quo official by recognizing generics PHPDoc > syntax as The Generics for PHP. Just adding a php.net manual page will > do. > - Recognize Composer as the official PHP tool. It's currently not > mentioned on php.net at all. > - Suggest using PHPStan or Psalm for generics and type checks. > - Add an official specification for generics in the PHP manual to > eliminate semantic variances between tools. > > This will keep the core simple and reduce the maintenance burden, not > increase it. > > Moreover, it does not contradict with any other implementation > mentioned in the article, should they happen. In fact, it could be a > first baby-step for any of them. > > There is also an attempt to do generics via attributes – > https://github.com/php-static-analysis/attributes – it could > potentially be a better alternative of recognising “official” syntax, > because unlike PHPDocs, attributes can be available in core and the > syntax is checked. > > What do you folks think? > > -Roman The null option is always an option, yes. The thing to understand is that today, *we already have erased generics*, via PHPStan/Psalm. That's one reason I am, personally, against erased generics in the language proper. They don't really offer anything we don't have already. 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, or will involve a lot of deeply nested attribute classes. For instance, if today you'd write: /** * @var array> */ protected array $foos; (An entirely reasonable lookup table for some circumstances). What would that be in attributes? This would still need string parsing: #[GenericType('string', 'Dict>')] And a form that doesn't need string parsing: #[DictType('string', new Dict('string', Foo::class))] Which is getting kinda ugly fast. All else equal, if we have to keep generics to implicit/erased, I'd favor going all the way to the latter (no-string-parsing attributes), and revising the syntax along the way. (The current syntax used by SA tools is decidedly weird compared to most generic languages, making it hard to follow.) If instead we used attributes for reified generics, then we have all the same challenges that make reified generics hard, just with a different syntax. As I understand it (again, Arnaud is free to correct me), these two syntaxes would be equally straightforward to parse, but also equally complex to implement the runtime logic for: #[DictType('string', new Dict('string', Foo::class))] protected array $foo; protected Dict> $foo; The latter is more compact and typical of our sibling languages, but once the parser is done, all of the other challenges are the same. As for making docblock generics "official", one, as I noted I hate the current syntax. :-) Two, that seems unwise as long as PHP still has an option to remove comments/docblocks at compile time. Even if it's not used much anymore, the option is still there, AFAIK. And that's before we even run into the long-standing Internals aversion to even recognizing the existence of 3rd party tools for fear of "endorsing" anything. (With the inexplicable exception of Docuwiki.) --Larry Garfield
Re: [PHP-DEV] State of Generics and Collections
On Fri, Aug 23, 2024, at 4:58 AM, Kévin Dunglas wrote: > Thanks for sharing this research work. > > Instead of having to choose between fully reified generics and erased > type declarations, couldn't we have both? A new option in php.ini could > allow to enable the “erased” mode as a performance, production-oriented > optimization. > In development, and on projects where performance isn't critical, types > (including generics) will be enforced at runtime, but users will have > the option of opting to disable these checks for production > environments. Strictly speaking, yes, a disabled-types mode could be made regardless of what happens with generics. But the downsides of that approach remain the same. I'm personally against type erasure generally, in large part because I don't know what it would break in terms of reflection, and in part because I *know* people will turn it off for dev, too, and then end up writing buggier code. > If this is not possible, the inline caches presented in the article, > combined with “worker” runtimes such as FrankenPHP, Swoole, RoadRunner, > etc., could make the cost of enforcing generics negligible: > technically, types will be computed once and reused for many HTTP > requests (because they are handled by the same long-running PHP script > under the hood). As working runtimes already provide a significant > performance improvement over FPM, we could say that even if > non-performance-critical applications (most applications) will be a bit > slower because of the new checks, people working on > performance-sensitive applications will have the opportunity to reduce > the cost of checks to virtually nothing by switching to a > performance-oriented runtime. >From talking to Arnaud, the main issue here is the file-at-a-time compilation. > I'm not entirely clear if a persistent process would side-step that, with the >delayed resolution bits, or if those would have to be re-resolved each time. >(That's an Arnaud question.) Another possibility that's been floated a bit, >tangentially, is allowing some kind of multi-file loading, which would allow >for a larger scope to be included at once as an opcache segment, and thus the >optimizer could do more. That said, I suspect the benefits of the JIT when using a worker-mode runner would be larger anyway. Also, speaking for me personally and no one else, I am still very much in favor of official steps to improve worker-mode options in php-src directly. What form that takes I'm not sure, but I would very much favor making worker-mode a first-class citizen, or at least a one-and-a-half class citizen, rather than its current second-class status. --Larry Garfield
Re: [PHP-DEV] State of Generics and Collections
On Mon, Aug 19, 2024, at 5:16 PM, Bob Weinand wrote: > Regarding the Collections PR, I personally really don't like it: > > • It implements something which would be trivial if we had reified > generics. If this ever gets merged, and generics happen later, it would > be probably outdated and quirkiness the language has to carry around. > • It's not powerful. But rather a quite limited implementation. No > overrides of the built-in methods possible. No custom operations ("I > want a dict where a specific property on the key is the actual unique > key", "I want a custom callback be executed for each modification"). > It's okay as a PoC, but far from a complete enough implementation. I think we weren't that clear on that section, then. The intent is that dedicated collection classes are, well, classes. They can contain additional methods, and probably can override the parent methods; though the latter may have some trickiness if trying to access the internal data structure, which may or may not look array-ish. (That's why it's just a PoC and we're asking for feedback if it's worth trying to investigate further.) > • It's a very specialized structure/syntax, not extensible for > userland at all. Some functionality like generic traits, where you'd > actually monomorphize the contained methods would be much more > flexible. E.g. class Articles { use Sequence; }. Much less > specialized syntax, much more extensible. And generic traits would be > doable, regardless of the rest of the generics investigation. > In fact, generic traits (essentially statically replacing the generic > arguments at link-time) would be an useful feature which would remain > useful even if we had fully reified generics. > I recognize that some functionality will need support of internal > zend_object_handlers. But that's not a blocker, we might provide some > default internal traits with PHP, enabling the internal class handlers. > So to summarize, I would not continue on that path, but really invest > into monomorphizable generic traits instead. Interesting. I have no idea why Arnaud has mainly been investigating reified generics rather than monomorphized, but a monomorphized trait has potential, I suppose. That naturally leads to the question of whether monomorphized interfaces would be possible, and I have no idea there. (I still hold out hope that Levi will take another swing at interface-default-methods.) Though this still wouldn't be a path to full generics, as you couldn't declare the inner type of an object at creation time, only code time. Still, it sounds like an area worth considering. --Larry Garfield
Re: [PHP-DEV] Should there be a `get_declared_enums()` function ?
On Fri, Aug 16, 2024, at 7:53 PM, Juliette Reinders Folmer wrote: > On 16-8-2024 17:01, Ayesh Karunaratne wrote: >> I went ahead and created PR https://github.com/php/php-src/pull/15443 along >> with tests, UPGRADE notice, etc. I think having a `get_declared_enums` >> function will be helpful. The implementation is simple and straightforward >> too. > Thanks for creating the PR Ayesh! > > I'm presuming it's too late for PHP 8.4, what with feature freeze > having come & gone this week. > > Based on the mostly supportive responses on the list, I wonder whether > an RFC is needed. If so, I'd be happy to create an initial draft (for > PHP 8.5). > > Smile, > Juliette I would prefer to have an RFC for this, even if it's short. I'm not against it, I just think there's enough non-trivial questions (eg, impact on get_declared_classes()) that it warrants an RFC process/discussion. --Larry Garfield
Re: [PHP-DEV] String enums & __toString()
On Fri, Aug 16, 2024, at 5:01 PM, Bilge wrote: > On 16/08/2024 22:51, Gina P. Banyard wrote: >> On Friday, 16 August 2024 at 22:01, Bilge wrote: >>> >>> >>> On Fri, 16 Aug 2024, 20:57 John Coggeshall, wrote: >>>> >>>> I'm not seeing an obvious upside to forbidding straight out `__toString()` >>> >>> I tend to agree, but Crell will drive by in a minute to drop some >>> philosophical nonsense about why we're all wrong :^) >> >> If you could avoid disrespecting a contributor to the project, this would be >> appreciated. > To be clear, I have nothing but love and respect for Larry. > > Cheers, > Bilge I appreciate that. :-) To the original question, there's two reasons that __toString() was deliberately omitted from enums: 1. To discourage their use as "fancy strings". Enums are their own type, independent of any other. Making them usable as 95% strings partially defeats their purpose. 2. We still intend to add associated values to enums at some point (aka ADTs, aka tagged unions), and... we're not really sure yet if that will impact __toString() at all. It may, it may not, we don't know. So for now we're keeping our options open by disallowing __toString(), in case it ends up being needed for some ADT-related behavior in the future. Point 2 will, hopefully, resolve itself in time once we can get ADT support in. Point 1 will remain, however. --Larry Garfield
Re: [PHP-DEV] [DISCUSSION] Class Constant Enums?
On Fri, Aug 16, 2024, at 1:31 PM, Arvids Godjuks wrote: > Hello Larry, > I feel obliged to remind about the 80/20 rule where the last 20% of > progress ends up being 80% of all the work. And from the discussion > it's already looking like there are some major questions and caveats > and engine problems that are gonna rear their ugly heads. I'm more in > favour starting with somewhat self-contained features and steadily work > to expand on them as people put the effort into it. The same as was > done with the type system. You can lay the proper foundation now, so > it's not blocking future expansion, but I really do not think full > embedded classes are gonna be a short endeavor - probably multiple > years if not half a decade going by prior record on features of this > size. > -- > > Arvīds Godjuks > +371 26 851 664 > arvids.godj...@gmail.com > Telegram: @psihius https://t.me/psihius To go off on this tangent for a bit... There's a difficult balancing act to be had here. On the one hand, yes, design small and grow as you get feedback makes sense. On the other hand, if you don't think through the whole plan, those early steps could end up being blockers for expansion, not a benefit. The most obvious example, readonly was billed as a building block toward aviz. It ended up making aviz harder, and it not passing the first time around. It remains to be seen if first-class callables end up getting in the way of full PFA in the future. The piecemeal way in which anonymous functions have been added over time has led to a lot of rough edges, and made discussions about smoothing them over harder (eg, the auto-closure-long-callable RFC). When those first steps are effectively set in stone forever, rather than something you can adjust based on future feedback, "YAGNI" becomes an actively harmful approach to system design. --Larry Garfield
Re: [PHP-DEV] [DISCUSSION] Class Constant Enums?
On Fri, Aug 16, 2024, at 6:35 AM, Alexandru Pătrănescu wrote: > Hi Nick, >> >> Is there any interest in having enums as class constants? >> >> I'm often finding cases where I would like to have an enum inside of a >> class, but don't want a free-floating enum that's basically like >> another class. >> > > .. > >> >> class SSHClient { >> >>public const enum CommandResult >>{ >>case Success; >>case Failure; >>case Unknown; >>case Timeout; >>} >> >>// ... >> } >> >> >> // Usage: >> >> SSHClient::CommandResult::Success > > > I feel this topic could be maybe more broad and be called "nested > classes" that are already supported in multiple languages: Java, Swift, > Python, C#, C++, JavaScript, etc. > > The syntax you showed is usually identical with what other languages > use, except that probably the const is unnecessary. > The nested class can have visibility as sometimes having it private > makes sense. > Accessing it through `::` is probably fine, but a deeper look at the > grammar might be necessary. > The nested class would have access to parent class private properties > and methods. > > I also mentioned this topic on the subject of defining a type in an > autoloader compatible way. > And indeed, a type could also be defined nested in a class if we want > to support that as well. > > Now, this feature is not simple, and I think it needs proper > sponsorship from someone experienced with internals. > > Regards, > Alex I agree with Alexandru. Since enums are 90% syntactic sugar over classes, "inner enums" would be 80% of the way to "inner classes". And I would be in favor of inner classes. :-) There's a lot of potential benefits there, but also a lot of edge cases to sort out regarding visibility, what is allowed to extend from what, etc. But that would support inner enums as well. Based on our sibling languages (Java, Kotlin, C#, etc.), the syntax would likely be something like: class Outer { private string $foo; public function __construct(protected Sort $order) {} enum Sort { case Asc; case Desc; } class Inner { public function __construct(private string $baz) {} } private class HIdden { public function __construct(private string $baz) {} } } Which enables: $case = Outer::Sort::Asc; $o = new Outer($case); $i = new Outer::Inner('beep'); $h = new Outer::Hidden('beep'); // Visibility error I would have to research to see if other languages did this, but one option would be to allow an inner class to extend an outer class even if it's final, which would essentially give us sealed classes for free: final class Outer { class InnerA extends Outer {} class InnerB extends Outer {} class InnerC extends Outer {} } // But this is still not OK: class Sibling extends Outer {} Note: I have no idea how difficult/complicated this would be, but I would be in favor of exploring it. --Larry Garfield
Re: [PHP-DEV] Should there be a `get_declared_enums()` function ?
On Wed, Aug 14, 2024, at 8:51 PM, Juliette Reinders Folmer wrote: > L.S., > > I just noticed the following, which struck me as weird/inconsistent: > > There are four different OO structures in PHP: > 1. Classes > 2. Interfaces > 3. Traits > 4. Enums > > For all four, an `*_exists()` function is available, i.e. > `class_exists()`, `interface_exists()`, `trait_exists()` and > `enum_exists()` [2]. > > But only for three out of the four, a `get_declared_*()` function > exists. > There is `get_declared_classes()`, `get_declared_interfaces()`, > `get_declared_traits()`, but no `get_declared_enums()` [2]. > > I'm aware that enums are internally considered classes and that > `get_declared_classes()` will retrieve them [1], but the same could be > said about interfaces and traits, yet they do have their own > `get_declared_*()` function. > > Should a `get_declared_enums()` function be added ? > And should the `get_declared_classes()` function be adjusted to exclude enums > ? > > I did check the enum RFC [3], but I couldn't find any mention or > discussion about this in the RFC. > > Smile, > Juliette > > > 1: https://3v4l.org/0ub6I > 2: https://www.php.net/manual/en/ref.classobj.php > 3: https://wiki.php.net/rfc/enumerations Conext: I can't remember the last time I used get_declared_classes() (thanks to autoloading and class_exists() it's a kinda pointless function), so when we were working on enums it never occurred to us to think about it. It wasn't a deliberate decision to omit, as far as I recall. I think I'd be open to adding it; my concern would be the overlap with get_declared_classes(), which as you note currently would include enums, and changing that is a BC break (even if a tiny one that I doubt would impact anyone). --Larry Garfield
Re: [PHP-DEV][Discussion] Should All String Functions Become Multi-Byte Safe?
On Sun, Aug 11, 2024, at 10:50 AM, Nick Lockheart wrote: > HTML 5 was adopted in 2014, over ten years ago. HTML 5 only supports > the UTF-8 multi-byte character encoding. > > It seems like there's still a lot of string functions that assume that > a character is a single byte, and these may actually work as expected > when dealing with Latin characters, but may fail unexpectedly if a > sequence is more than one byte. > > Are there any use cases for PHP where **single-byte** characters are > the norm? > > It seems that if everything on the Internet is multi-byte encoded now, > then all of the PHP string functions should be multi-byte safe. > > > The WHATWG Encoding Standard: > > https://encoding.spec.whatwg.org/ > > Also, according to Mozilla, "[The meta charset] attribute declares the > document's character encoding. If the attribute is present, its value > must be an ASCII case-insensitive match for the string "utf-8", because > UTF-8 is the only valid encoding for HTML5 documents." > > https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#charset Some background and history, for those not familiar... After PHP 5.2, there was a huge effort to move PHP to using Unicode internally. It was to be released as PHP 6. Unfortunately, it ran into a whole host of problems, among them: 1. It tried to use UTF-16 internally, as there were good libraries for it but it was much much slower than was acceptable. 2. It required rewriting basically everything. 3. Trying to support two string variants at the same time (because binary strings are still very useful) in almost the same syntax turned out be, um, kinda hard. After a number of years of work, it was eventually concluded that it was a dead end. So the non-Unicode-related bits of what would have been PHP 6 got renamed to PHP 5.3 and released to much fanfare, kicking off the PHP Renaissance Era. When PHP 5.6+1 was released, there was a vote to decide if it should be called 6 or 7. 7 won, mainly on the grounds that a number of very stupid book publishers had released "PHP 6" books in anticipation of PHP 6's release that were now completely useless and misleading. So we skipped 6 entirely, and PHP 6-compatibility is a running joke among those who have been around a while. Fortunately, the vast majority of single-byte strings are ASCII, and ASCII is, by design, a strict subset of UTF-8, so in practice the lack of native UTF-8 strings rarely causes an issue. Trying to introduce Unicode strings to the language now as a native type would... probably break just as much if not more. If anything it's probably harder today than it was in 2008, because the engine and existing code to not-break has grown considerably. A much better approach would be something like this RFC from Derick a few years ago: https://wiki.php.net/rfc/unicode_text_processing If you need something today, then Symfony has a user-space approximation of it: https://symfony.com/doc/current/string.html --Larry Garfield
Re: [PHP-DEV] [Vote] Asymmetric visibility v2
On Fri, Jul 26, 2024, at 1:25 PM, Larry Garfield wrote: > Voting for Asymmetric Visibility is now open. > > https://wiki.php.net/rfc/asymmetric-visibility-v2 > > The vote will end on 9 February, probably afternoonish in my timezone. I have now closed the vote on this RFC. The final result is 24 Yes, 7 No, for a total of 77.4% in favor. The RFC has passed. Thanks everyone for your participation and input. Ilija will get the PR merged soonish. --Larry Garfield
Re: [PHP-DEV] [RFC] [VOTE] Transform exit() from a language construct into a standard function
On Thu, Aug 8, 2024, at 9:10 AM, Andreas Heigl wrote: > Hey Gina, hey all > > Am 08.08.24 um 15:44 schrieb Gina P. Banyard: >> On Wednesday, 7 August 2024 at 17:07, Andreas Heigl >> wrote: >>> Stupid question maybe, but are we voting on the RFC or on the patch? >>> >>> If the patch does not match what.the RFC proposes, then the patch has >>> a problem. That should IMO though not affect voting on an RFC. >>> >>> Or am I.missimg something? >> >> In theory, it is the RFC idea. >> In practice, a lot of the times it is the patch for complex features. >> >> However, it is still within the purview of core developers to veto the >> implementation of an RFC. >> Which could be the case here rather than voting against the RFC outright. > > I have no problem that core developers veto a certain implementation of > an RFC. I actually expect them to do so. > > But the vote should IMO *always and exclusively* be based on the RFC. > Not on the implementation. If the voting happens based on the > implementation due to the complexity of the features that means that the > RFC is not wel written and needs to be improved. Or the implementation > is problematic and needs to be vetoed by the core developers. How exactly would voters veto an implementation if not through the RFC? That's literally the only formal input mechanism they have, and previous attempts to add others have been soundly rejected. As a historical note, the partial function application RFC was declined despite there being general consensus that the proposal was quite good and quite desireable. The issue was that Nikita felt the implementation proposed with it was too fragile, and wasn't sure how to make it less fragile, so he voted No and several others followed suit. I am fairly confident that if a less-fragile implementation could be found, it would pass handily. So yes, RFCs have been rejected in the past on "implementation only." --Larry Garfield
Re: [PHP-DEV] [RFC] [VOTE] Transform exit() from a language construct into a standard function
On Mon, Aug 5, 2024, at 6:04 AM, Derick Rethans wrote: > On Tue, 30 Jul 2024, Christoph M. Becker wrote: > >> On 30.07.2024 at 11:49, Gina P. Banyard wrote: >> >> > I have just opened the vote for the "Transform exit() from a >> > language construct into a standard function" RFC: >> > https://wiki.php.net/rfc/exit-as-function >> > >> > The vote will last for two weeks until the 13th of August 2024. >> >> As userland PHP developer, I always regarded `exit` as a control flow >> instruction (quite similar to `break`), and as such I'm not really in >> favor of converting it to a proper function (especially since it is >> not, because the parantheses could be omitted). > > Xdebug uses exit for exactly that too. For control flow analysis. And I > also always have considered it to be a control flow instruction. > > I see no benefit in changing it to a function, especially because > there will never be a function "exit" from it, just only an "entry". > This breaks function execution symmetry (and causes issues with Xdebug > when I last tried to make it work with a development branch for this > RFC). > > As the RFC is scarce on mitigations for this, I am currently voting "no" > as I am unsure how certain features in Xdebug could remain working. I > have written to the list on other reasons before > (https://externals.io/message/123277#123450) without a conclusion. > > I'll consider changing it to yes if there is a commitment for addressing > these feature-maintaining-requirements to keep Xdebug working, either > through new APIs (think observer) or other mitigations. > > cheers, > Derick While I support language and engine cleanup, if this change causes issues for Xdebug that is a fairly significant problem. For that reason I have shifted my Yes to a No for now. Like Derick, I will switch it back to a Yes should the Xdebug issue be resolved to his satisfaction. But "keep Xdebug working" is a rather mission-critical requirement for any RFC, as a practical matter. --Larry Garfield
Re: [PHP-DEV] [RFC] Asymmetric Visibility, v2
On Mon, Aug 5, 2024, at 7:27 AM, Vincent de Lau wrote: > From: Rob Landers > Sent: Sunday, July 21, 2024 11:21 AM > >> On Sat, Jul 20, 2024, at 23:51, Larry Garfield wrote: >> > On Sat, Jul 20, 2024, at 7:22 AM, Rodrigo Vieira wrote: >> > > Will the alternative syntax on hook not even be put to a vote? > >> > It was, a year and a half ago when Aviz was first proposed. The >> > preference was split, but leaned toward the prefix-style syntax. So we >> > went with that. I don't think we'll ever get everyone to want the same >> > syntax, but we're using the one that was both somewhat more popular, and >> > (as discussed in the RFC) arguably superior. > >> > As the "comments in yield from" thread has shown, *any* even slight change >> > to PHP's syntax will require work from static analysis tools. That's the >> > nature of the problem space, regardless of the syntax specifics. > >> Just to play devil’s advocate, it was also before we had property hooks who >> advertised itself as a way to “wrap and guard access to object properties” >> but we are simply ignoring their existence here. > > I'm very disappointed that this discussion was not concluded before the > vote was started. One of the main arguments for picking this syntax is > the research from two years ago, when hooks where not a thing. In my > opinion that makes that whole research obsolete in this new context. > I've asked to redo the research, but that was not acknowledged > > For the 'split visibility' concern, there has been some mentioning of > reviving the `var` keyword, allowing you to place all visibility in the > hook block. > > While I don't have the 'perfect' syntax in mind, I strongly believe > that this subject required a bit more investigation and discussion. My > only hope now is that the people voting take this into consideration, > especially as this is now being rushed into 8.4. While hooks were not a feature when Aviz was first proposed, it was very clear at the time that they were coming, and the syntax was mostly already figured out, at least in broad strokes. It's not like no one knew we'd be having {} after the property if hooks pass. I would not call the results obsolete. Rather, I think what it shows is that there's no syntax that will satisfy everyone, so trying to find a syntax favored by everyone would just waste time and end in failure anyway. I would hardly call this rushed; it was open for multiple months, and built on the previous discussion in 2023. Lazy Objects, for instance, was first proposed a month after aviz, and started its vote on the same day. (No shade on Lazy Objects; I'm happy to see that passing.) --Larry Garfield
Re: [PHP-DEV] [Vote] Asymmetric visibility v2
On Mon, Aug 5, 2024, at 8:49 AM, Theodore Brown wrote: > On Fri, July 26, 2024 at 12:25 Larry Garfield wrote: > >> Voting for Asymmetric Visibility is now open. >> >> https://wiki.php.net/rfc/asymmetric-visibility-v2 > > Hi Larry and Ilija, > > Thank you for all your work on this RFC! > > One part that doesn't make sense to me is this sentence near the end in > the "Readonly is incompatible with inheritance" section: > >> With asymmetric visibility, the `readonly` usage here can be replaced with >> `protected protected(set)` or `readonly protected protected(set)`, avoiding >> the need to double-declare properties. > > `protected protected(set)` just removes readonly, and is the same as > `protected`, right? So couldn't such a change be done now without > asymmetric visibility? > > And the change to `protected protected(set) readonly` as shown in the > example also seems unnecessary, since earlier in the RFC it says that > readonly will be changed to imply `protected(set)` rather than > `private(set)`. So it seems that no change is needed to the abstract > class here - the properties can remain `protected readonly`, and the > implementation can be simplified since readonly properties will now > imply `protected(set)`. > > Or have I misunderstood something here? I believe in this case you're correct. That example was written early on, before we decided to expand readonly to protected(set) by default. I didn't realize that needed to be updated as well. Yes, in this case, the widening of readonly would also resolve that issue. `protected protected(set)` would now be redundant, but not hurt anything, whereas `protected private(set)` would have an effect. `public public(set) readonly` would also be legal (though I don't personally know why you'd do that, there's no inherent reason to make it illegal). --Larry Garfield
Re: [PHP-DEV] [Vote] Property Hook performance improvements
On Mon, Jul 15, 2024, at 2:05 PM, Larry Garfield wrote: > Hi all. I have just opened the voting on the property hook > (performance) improvement RFC. > > https://wiki.php.net/rfc/hook_improvements > > With the readonly bits pushed out to later, this is probably the > shortest RFC I have ever written. :-) Vote opens now, and will close > in 2 weeks on 29 July. A day late but not a dollar short, I have closed the voting for the hook improvements RFC. The final vote is 33 in favor, 0 against. The RFC has passed. Thanks everyone! --Larry Garfield
Re: [PHP-DEV] [Vote] Asymmetric visibility v2
On Fri, Jul 26, 2024, at 6:54 PM, Bilge wrote: >> Presumably the proposed PHP version is wrong? No, this is still within the window to target 8.4. --Larry Garfield
Re: [PHP-DEV] [Vote] Asymmetric visibility v2
On Fri, Jul 26, 2024, at 6:25 PM, Larry Garfield wrote: > Voting for Asymmetric Visibility is now open. > > https://wiki.php.net/rfc/asymmetric-visibility-v2 > > The vote will end on 9 February, probably afternoonish in my timezone. > > -- > Larry Garfield > la...@garfieldtech.com Sigh. And of course I meant the voting will end on 9 AUGUST, aka, two weeks from today. (No idea where that came from.) --Larry Garfield
[PHP-DEV] [Vote] Asymmetric visibility v2
Voting for Asymmetric Visibility is now open. https://wiki.php.net/rfc/asymmetric-visibility-v2 The vote will end on 9 February, probably afternoonish in my timezone. -- Larry Garfield la...@garfieldtech.com
Re: [PHP-DEV] [RFC] Asymmetric Visibility, v2
On Fri, Jul 26, 2024, at 12:58 PM, Rob Landers wrote: >> And now that I see it spelled out more, I do agree that while it appears a >> bit more verbose, and this "(set)" looks odd at first, having all the >> visibility upfront is a lot clearer than having to read through the hooks to >> see what visibility applies. > > On a large property hook that potentially span hundreds of lines, I'd > rather only need to scroll up to the "set =>" to see how it is set vs. > going all the way back up to the property itself. If someone has a property hook that is hundreds of lines long, their code is already crap and there's no hope for them. --Larry Garfield
Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4
On Fri, Jul 26, 2024, at 11:11 AM, Christoph M. Becker wrote: > On 26.07.2024 at 12:03, Gina P. Banyard wrote: > >> Stephen Rees-Carter, a security expert that has performed countless security >> audits on Wordpress and Laravel websites, would like to disagree with the >> fact that it is not enough of a good reason. [1] >> A warning on a documentation page is useless, as nobody is forced to read it. > > Right, but even a deprecation notice is likely to be ignored by those > (either use the shut-up operator, or use hash("md5), or maybe a polyfill > to support old PHP versions), so the deprecation wouldn't help in such > cases. > > (I've recently seen a new release of a software which still uses > <https://www.openwall.com/phpass/>. Apparently, the notice to prefer > the password_*() API has been ignored or overlooked.) > > On the other hand, I'm quite confident that a deprecation could be > useful for some developers, who would at least reconsider the use of > md5/sha1 hashes, but just have overlooked this; although some static > analysis should report respective issues. However, there is certainly > code without any static analysis, where at least this discussion appears > to be helpful, e.g. our php-sdk-binary-tools might reconsider their use > of md5() and md5(uniqid())[2]. > > Note that I'm not against these deprecations, but I'm also not strongly > in favor. I see valid arguments from both proponents and opponents. > >> [1] https://x.com/valorin/status/1816593881791860963 > > [2] <https://github.com/php/php-sdk-binary-tools/issues/21> > > Cheers, > Christoph One thing to remind people about, the deprecations for md5(), sha1(), and uniqid() explicitly say they cannot be outright removed before PHP 10. That's at least 6 years away. That gives a loong time for documentation, tutorials, instructions, and code to be updated. That long deprecation period is the reason why I was comfortable voting yes. This isn't something that would happen tomorrow. It would be in at least two presidential elections from now. --Larry Garfield
Re: [PHP-DEV] [RFC] Lazy Objects
On Thu, Jul 18, 2024, at 7:12 AM, Nicolas Grekas wrote: >> Otherwise, I'm quite looking forward to this. > > 🤞 Another thought that occurred to me. Given how lightweight it *looks* to be (may not actually be, but looks it), how much overhead would there be to having a compiled DI container that is lazy by default? Just make everything lazy with a fairly standard initializer or factory, unless a specific case says you shouldn't. That way you can use optional dependencies in a constructor pretty much at will with no overhead of needing to create a chain of dependencies as a result. Would that be a bad idea for some reason, or would it actually work? (This doesn't really affect my vote, more just a thought that came up.) --Larry Garfield
Re: [PHP-DEV] [RFC] Asymmetric Visibility, v2
On Mon, Jul 22, 2024, at 7:07 PM, Tim Düsterhus wrote: > Hi > > On 7/20/24 03:14, Larry Garfield wrote: >> Baring any new developments, we plan to start the vote early next week. > > I've went through the RFC once more. I have the following remarks: > >> For that reason, a private(set) property is automatically final and may not >> be redeclared at all. >> > > I assume that explicitly marking it as final is still allowed (just > redundant)? Correct. I have added a comment to that effect. >> There is one caveat regarding virtual properties that have no set operation. >> If there is no set operation defined on a property, then it is nonsensical >> to specify a visibility for it. That case will trigger a compile error. For >> example: >> > > How does this interact with inheritance? Consider the following example: > > class P { > public $answer { get => 42; } > } > > class C extends P { > public protected(set) $answer { get => 42; set => 'dummy'; } > } > > This could be considered to be both narrowing the `set` visibility from > `public` to `protected` (which is unsound), but also widening it from > “never” to `protected` (which would be sound). I checked with Ilija, and confirmed that it's the second. I have updated the RFC accordingly to make that explicit. >> as it's possible now for a property to be visible but not writeable. For the >> time being, > > I dislike the “for the time being” phrasing, because changing that would > effectively result in a breaking change, because the __set() may be > called in situations that were not anticipated. I would have preferred a > stronger phrasing that makes it clear that the RFC authors know what > they are talking about. > > Best regards > Tim Düsterhus I wordsmithed this a bit further. We're not trying to be wishy-washy. Rather, there are a couple of knock-on implications that are worth discussing that we consider off topic, but the approach we're taking does not preclude them. We're deliberately taking the conservative approach. Adding a __set fallback in the future would not be a BC break, as it would be changing a hard error condition to a legal condition, which is something nearly all new features do. We don't think it's wise to do that, but if someone wanted to advocate for that in the future we're not precluding it. If none of those further discussions happen, we still consider this behavior complete and acceptable. --Larry Garfield
Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4
On Tue, Jul 23, 2024, at 4:00 PM, Matthew Weier O'Phinney wrote: >> However, a few people indicated a desire to have an explicit wildcard _ >> anyway, even if it's redundant, as it's a more common and standard approach >> in other languages. We've indicated that we are open to making that an >> optional secondary vote in the pattern matching RFC if there's enough >> interest (it would be trivial), though I haven't bothered to add it to the >> RFC text yet. >> >> Having _ available could also be used in other "wildcard" or "ignore this" >> cases, like exploding into a list assignment or similar, though I don't >> believe that has been fully explored. > > Can you provide examples of what that usage would look like? And the > question I have really is, does this actually _require_ using "_", or > could another token be used for such matches? Hypothetical pattern matching example: $foo is ['a' => int, 'b' => $b, 'c' => mixed]; That would assert that there's 3 keys. "a" may be any integer (but only an integer), "b" can be anything and will be captured to a variable, and "c" must be defined but we don't care what it is. The suggestion is to basically alias _ to "mixed" for pattern purposes: $foo is ['a' => int, 'b' => $b, 'c' => _]; As "there's a var here but I don't care what it is, ignore it" is a common meaning of _ in other languages. But that would need to be disambiguated from a pattern saying "c must be an instance of the class _". Technically any symbol/set of symbols could be used there (as it's just an alias to mixed, which has the exact same effect), but _ is a common choice in other languages. In theory, that could be expanded in the future to something like (note: this hasn't been seriously discussed that I know of, I'm just spitballing randomly): [$a, $b, _] = explode(':', 'foo:bar:baz'); To assign $a = "foo", $b to "bar", and just ignore "baz". Which might cause parser issues if _ is a legal class name, I'm not sure. There's probably other "ignore this" cases we could come up with, but I haven't actually thought about it. Again, whether any of the above is a compelling argument or not I leave as an exercise for the reader. --Larry Garfield
Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4
On Tue, Jul 23, 2024, at 2:41 PM, Christoph M. Becker wrote: > On 23.07.2024 at 16:04, Larry Garfield wrote: > >> On Tue, Jul 23, 2024, at 1:42 PM, Matthew Weier O'Phinney wrote: >> >>> On Fri, Jul 19, 2024 at 12:41 PM Gina P. Banyard wrote: >>> >>>> I have opened the vote for the mega deprecation RFC: >>>> https://wiki.php.net/rfc/deprecations_php_8_4 >>> >>> The section "Deprecate using a single underscore ''_'' as a class name" >>> indicates that probably the primary reason to deprecate it is a >>> potential future conflict in the pattern matching RFC, where it can be >>> used as a wildcard. >>> >>> However, I see no mention of this character as a wildcard anywhere in that >>> RFC. >>> >>> Can somebody clarify? >> >> The pattern matching RFC previously listed _ as a wildcard character. >> >> In the discussion a month ago, someone pointed out that `mixed` already >> serves that exact purpose, so having an extra wildcard was removed. >> >> However, a few people indicated a desire to have an explicit wildcard _ >> anyway, even if it's redundant, as it's a more common and standard approach >> in other languages. We've indicated that we are open to making that an >> optional secondary vote in the pattern matching RFC if there's enough >> interest (it would be trivial), though I haven't bothered to add it to the >> RFC text yet. >> >> Having _ available could also be used in other "wildcard" or "ignore this" >> cases, like exploding into a list assignment or similar, though I don't >> believe that has been fully explored. >> >> That's the context/background here. Whether that encourages you to vote for >> or against that section I leave as an exercise for the reader. > > Well, I wonder how that is supposed to work. Assuming the underscore > would be used as wildcard in a class name context, that could only be > done after using that character as class name is no longer allowed. So > that would have to wait for the next major PHP version (at least). > > Note that I'm not worried about no longer being able to use an > underscore as class name, but rather that this introduces another > inconsistency to our indentifiers. Disallowing an underscore as > function name is obviously off the table, thanks to gettext. > > Christoph I think someone checked and found no examples of someone using _ as a class name, so the impact of removing it and/or using it for something else would be nearly nil. That may still push _ as a wildcard out to a future version, but I leave that up to others. As I said, I don't have strong feelings either way. --Larry Garfield
Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4
On Tue, Jul 23, 2024, at 1:42 PM, Matthew Weier O'Phinney wrote: > On Fri, Jul 19, 2024 at 12:41 PM Gina P. Banyard wrote: >> Hello internals, >> >> I have opened the vote for the mega deprecation RFC: >> https://wiki.php.net/rfc/deprecations_php_8_4 >> >> Reminder, each vote must be submitted individually. >> >> >> Best regards, >> >> >> Gina P. Banyard > > > The section "Deprecate using a single underscore ''_'' as a class name" > indicates that probably the primary reason to deprecate it is a > potential future conflict in the pattern matching RFC, where it can be > used as a wildcard. > > However, I see no mention of this character as a wildcard anywhere in that > RFC. > > Can somebody clarify? The pattern matching RFC previously listed _ as a wildcard character. In the discussion a month ago, someone pointed out that `mixed` already serves that exact purpose, so having an extra wildcard was removed. However, a few people indicated a desire to have an explicit wildcard _ anyway, even if it's redundant, as it's a more common and standard approach in other languages. We've indicated that we are open to making that an optional secondary vote in the pattern matching RFC if there's enough interest (it would be trivial), though I haven't bothered to add it to the RFC text yet. Having _ available could also be used in other "wildcard" or "ignore this" cases, like exploding into a list assignment or similar, though I don't believe that has been fully explored. That's the context/background here. Whether that encourages you to vote for or against that section I leave as an exercise for the reader. --Larry Garfield
Re: [PHP-DEV] [RFC] Asymmetric Visibility, v2
On Sun, Jul 21, 2024, at 2:45 PM, Tim Düsterhus wrote: > Hi > > On 7/20/24 03:14, Larry Garfield wrote: >> We've made one change since we last discussed it: Specifically, Ilija >> realized that __set's behavior is already inconsistent, so supporting it for >> aviz properties with invisible set would make it even more inconsistent, not >> less. For that reason, we've changed the __set behavior such that a >> non-readonly aviz property will not trigger __set. Further details are in >> the RFC, but in short, all of the use cases for that behavior now have >> better alternatives, such as property types, hooks, and aviz itself. So >> there's really no point to falling back to __set in edge cases. >> >> https://wiki.php.net/rfc/asymmetric-visibility-v2#interaction_with_set_and_unset >> >> Baring any new developments, we plan to start the vote early next week. > > I find it unfortunate that this RFC received a non-trivial change on a > Saturday after the discussion has been idle for more than a month > together with the announcement that the vote will begin shortly after > the weekend. Folks should be given sufficient time to react to the > newest developments. Personally I plan to give this RFC another read, > because I already forgot the details after a month of not looking at it, > but I'm not sure if I'll manage today. > > For now: > > Is there any implementation of this RFC? The RFC text only references > the https://github.com/php/php-src/pull/9257 PR hasn't been updated > since December 2022. > > Best regards > Tim Düsterhus Oof, sorry, I thought Ilija had updated the link already. It is now updated, and the PR is here: https://github.com/php/php-src/pull/15063 Since the PR wasn't easily available until now, we're going to push the vote start back to this coming Friday. --Larry Garfield
Re: [PHP-DEV] Request for opinions: bug vs feature - change intokenization of yield from
On Sat, Jul 20, 2024, at 11:51 AM, Tim Düsterhus wrote: > Hi > > On 7/20/24 18:40, Juliette Reinders Folmer wrote: >> Tim, you're making my point for me. This is *exactly* why the current >> change should be reverted. > > I am not sure how you read "PHP users have no idea what a token is" as > an argument in favor of reverting the change, because reverting the > change means that completely reasonable code suddenly stops working with > a parser error in a patch version and PHP users will rightfully come to > PHP's issue tracker to complain. > >> And not, like it is now, an undocumented, random change creating an >> inconsistency in the Tokenizer. > > The tokenizer is doing the right thing: It tokenizes the PHP source > code. It is absolutely normal that PHP first and second-digit updates > make changes to the token stream. New tokens are added, old tokens are > removed, tokens may appear in places where they previously could not > appear for well-formed PHP programs. Tools working on the token stream > need to adapt and this change is no different from any other change to > PHP's syntax in that regard (except that documenting the change was > forgotten). > > Best regards > Tim Düsterhus Yes, any syntax change means tools need to adapt, but that doesn't mean tokenization can change randomly and accidentally. Syntax changes require an RFC. If an RFC passes that necessitates SA tools update, so be it. (That happens almost every version.) But that's still an RFC change. I would agree with reverting this change for now. The odds of it breaking something for someone are vanishingly small, and it's a bug, not a feature. If we want it to be a feature, we can make an RFC for it. --Larry Garfield
Re: [PHP-DEV] [RFC] Asymmetric Visibility, v2
On Sat, Jul 20, 2024, at 7:22 AM, Rodrigo Vieira wrote: > Will the alternative syntax on hook not even be put to a vote? It was, a year and a half ago when Aviz was first proposed. The preference was split, but leaned toward the prefix-style syntax. So we went with that. I don't think we'll ever get everyone to want the same syntax, but we're using the one that was both somewhat more popular, and (as discussed in the RFC) arguably superior. As the "comments in yield from" thread has shown, *any* even slight change to PHP's syntax will require work from static analysis tools. That's the nature of the problem space, regardless of the syntax specifics. --Larry Garfield
Re: [PHP-DEV] [RFC] Asymmetric Visibility, v2
On Sat, Jul 20, 2024, at 10:47 AM, Ilija Tovilo wrote: > Hi Rob > > On Sat, Jul 20, 2024 at 3:47 PM Rob Landers wrote: >> >> On Sat, Jul 20, 2024, at 03:14, Larry Garfield wrote: >> >> On Wed, May 29, 2024, at 2:15 PM, Larry Garfield wrote: >> > >> > https://wiki.php.net/rfc/asymmetric-visibility-v2 >> >> Hi folks. After a side quest to polish off hooks, we're nearly ready to >> bring aviz to a vote. >> >> We've made one change since we last discussed it: Specifically, Ilija >> realized that __set's behavior is already inconsistent, so supporting it for >> aviz properties with invisible set would make it even more inconsistent, not >> less. For that reason, we've changed the __set behavior such that a >> non-readonly aviz property will not trigger __set. Further details are in >> the RFC, but in short, all of the use cases for that behavior now have >> better alternatives, such as property types, hooks, and aviz itself. So >> there's really no point to falling back to __set in edge cases. >> >> https://wiki.php.net/rfc/asymmetric-visibility-v2#interaction_with_set_and_unset >> This is a pretty massive breaking change. > > There was a miscommunication between Larry and me. The change is not > to any existing behavior. __get/__set are currently called under two > circumstances: > > * The properties _full_ visibility is not met. > * The property was explicitly unset. > > We're not changing this behavior. Instead, we decided not calling > __set for asymmetric visibility, when only the set visibility isn't > met. Before making this decision, implicitly implying protected(set) > for a readonly property would have led to __set being called (because > the scope protection now comes from asymmetric visibility, rather than > readonly itself), which would have been a change to the current > behavior. > > So, in short: If only the set visibility isn't met, we're now throwing > an error. This is consistent with readonly today, and with get-only > hooks. If somebody wants to change this in the future, they can do so > without any BC breaks, and most likely should make the behavior > consistent across all of these three cases. > > Ilija After discussing with Ilija further, I've rewritten the __set section (again). As Ilija said, the long and short of it is "we change nothing", but leave the door open to clean up __set's behavior in the future, once we decide what cleanup is warranted. --Larry Garfield
Re: [PHP-DEV] [RFC] Asymmetric Visibility, v2
On Wed, May 29, 2024, at 2:15 PM, Larry Garfield wrote: > As promised, Ilija and I offer this revised version of asymmetric visibility. > > > https://wiki.php.net/rfc/asymmetric-visibility-v2 > > It's still essentially the same as last year's version, but with a few > adjustments and changes: > > * readonly properties are now supported in a logical fashion. > * We've brought back the abbreviated form, as public-read, something > else set is the most common use case. > * The section on magic methods has been greatly simplified. The > implementation itself hasn't changed, but the explanation is a lot less > confusing now. > * We've explained how aviz interacts with hooks (they don't, really) > and with interface properties (in the obvious way), which didn't exist > at the time of the last draft. > * We've added a section with examples of how aviz is a concrete > improvement, even in a world with readonly and hooks. > * We've added a section discussing why the prefix-style syntax was > chosen. Hi folks. After a side quest to polish off hooks, we're nearly ready to bring aviz to a vote. We've made one change since we last discussed it: Specifically, Ilija realized that __set's behavior is already inconsistent, so supporting it for aviz properties with invisible set would make it even more inconsistent, not less. For that reason, we've changed the __set behavior such that a non-readonly aviz property will not trigger __set. Further details are in the RFC, but in short, all of the use cases for that behavior now have better alternatives, such as property types, hooks, and aviz itself. So there's really no point to falling back to __set in edge cases. https://wiki.php.net/rfc/asymmetric-visibility-v2#interaction_with_set_and_unset Baring any new developments, we plan to start the vote early next week. Cheers. --Larry Garfield
Re: [PHP-DEV] Optional constructor body
On Thu, Jul 18, 2024, at 2:03 PM, Lily Bergonzat wrote: > I would love to see those improvements as well, however I am surprised > we seem to be more inclined to push a more substantial change than a > minor one. > > I feel like the more substantial one would be more likely to break > stuff, compared to the minor one, and so I don't see why the minor one > would be refused? > > That said, I am new here, and I do not yet know how things work, so it > probably is because I lack experience. As you're new, I'll just note, please don't top post. :-) The optimal size of an RFC is a very squishy topic. There are some that argue for "the smallest possible and no smaller," on the theory that bite-sized changes are easier to discuss. However, they also attract more bikeshedding, and often a feature is not actually useful except in conjunction with other parts of it. On the flipside, a tiny RFC has a hard time justifying its existence, since whatever intended follow-ups that would make it actually useful are never guaranteed to happen (either the authors lose interest or they get voted down later, etc.). Going through an RFC also has a lot of process overhead, and breaking one small RFC into many tiny RFCs can actually take far longer than the one larger RFC. Conversely, an RFC can be too big to really comprehend, and then no one really understands what it's doing without hours of reading and research, and there's so many moving parts even the authors cannot keep track of them. On the flipside, some parts just don't make any sense on their own unless combined with other aspects of a proposal. So there's really no "natural" size for RFCs generally. It will vary with the topic. Also, the impact of an RFC often has very little to do with its length or number of features. The RFC text for "don't require ; to end a statement anymore" would likely be pretty short, but would also break, er, everything. :-) Conversely, offering a new syntax for abbreviated constructors (as being discussed here) would be longer than that, but the impact on existing code would be zero (unless it's done badly). Also, "minor work" can end up causing problems for future work. See also: readonly, which was intended as a "junior stepping stone" to more complex features, but as we've found, actually makes those future features *more* complex because it wasn't designed with those future expansions in mind. My own stance (which I do not claim to be universal) is that an RFC is "right-sized" when it offers notable, meaningful benefit on its own, without "holes" in the functionality, but can and should have natural "extension points" where it will dovetail nicely with other, future features, which can be planned or not. Sometimes that means a very short RFC, other times it means something the size of property hooks. :-) It's really a case-by-case situation. --Larry Garfield
Re: [PHP-DEV] Optional constructor body
On Thu, Jul 18, 2024, at 10:11 AM, Oliver Nybroe wrote: > Thanks for sharing previous discussions, I will definitely take a look > at those before writing up the RFC. > > >> If you do with to go with an RFC, I'd like to see if your proposal > addresses whether this syntax should implicitly call > `parent::__construct()`, and if a semi colon is expected or not > (`public function __construct(public int $foo);` vs `public function > __construct(public int $foo)`). > Thank you, these are very valuable points to address in the RFC. > > I can definitely feel that there will be some mixed opinions about > semicolon vs no semi colon. > > > Best regards > Oliver Nybroe (he/him) Please don't top-post. Since the last time this came up, PSR-12 has been replaced with PER-CS, which as of 2.0 now says: > If a function or method contains no statements or comments (such as an empty > no-op implementation or when using constructor property promotion), then the > body SHOULD be abbreviated as {} and placed on the same line as the previous > symbol, separated by a space. cf: https://www.php-fig.org/per/coding-style/#44-methods-and-functions (I... suppose technically it doesn't mention classes, but I've been doing it for empty classes too.) So the "coding style" part of the previous issue has been resolved. Whether that changes anyone's mind about whether this should be done or not is up to them to decide. Personally, I'd probably vote for it if it came up, but I agree it's a pretty minor improvement and unlikely to pass. It would probably only be worth doing if there were other common-pattern-optimizations around the constructor that came with it. Things like auto-forwarding to the parent, or a more compact syntax than a full constructor method, or other things that make writing a "pure data" product type easier rather than just s/{}/;/ I don't know what those could look like. As a data point, in Kotlin (which is what my day job is now), constructor properties are always promoted, essentially. class Foo(val a: String, val b: String) { // This is the equivalent of PHP's promoted properties. val c: Int = 5 // A non-constructor-initialized property. These can have hooks, constructor ones I think cannot. init { // This is the non-promoted part of a constructor body, and runs after the properties are assigned. } } In case of inheritance, there's dedicated required syntax for forwarding to the parent: class Foo(val a: String, val b: String) : Bar(b) { // equivalent to parent::__construct($b) } You can also make the constructor private (etc.) with more explicitness: class Foo private constructor(val a: String, val b: String) {} Of note, if there's no constructor then the parens are omitted, and if there's no body then the {} body is omitted. That means a great many "value objects"/DTOs, etc just look like this: class Foo( val a: String, val b: String, ) Which would be equivalent to PHP's class Foo { public function __construct( public readonly string $a, public readonly string $b. ) {} } cf: https://kotlinlang.org/docs/classes.html To be clear, I'm not suggesting PHP just copy Kotlin directly. I'm saying that if we want to improve the constructor syntax for common cases, which I am open to, we should be looking to do something more substantial and ergonomic than just replacing {} with ;, and we could probably get some good inspiration from other languages in our family. (Java, Kotlin, C#, Swift, etc.) --Larry Garfield
Re: [PHP-DEV] [RFC] Lazy Objects
On Wed, Jul 17, 2024, at 6:31 PM, Nicolas Grekas wrote: > A bit unrelated to the above topic: we've further clarified the RFC by > addition restrictions to what can be done with lazy proxies. Namely, > when the factory returns an object from a parent class, we describe > that adding more on the proxy class would throw, and we also explain > why. We also added a restriction to prevent a proxy from having an > overridden __clone or __destruct when the factory returns a parent, and > explained why again. > > This should simplify the overall behavior by preventing edge case that > wouldn't have easy answers. If those limitations prove too restrictive > in practice (my experience tells me they should be fine), they could be > leveraged in the future. > > On our side, this should close the last topics we wanted to address > before opening the vote. > > Please let us know if anyone has other concerns. > > Cheers, > Nicolas Minor point: Why is the $initializer return type null, instead of void? I don't see a purpose to allowing an explicit null return and nothing else. Otherwise, I'm quite looking forward to this. --Larry Garfield
Re: [PHP-DEV] array_reduce callback key
On Wed, Jul 17, 2024, at 9:01 AM, Bilge wrote: > On 17/07/2024 01:41, Levi Morrison wrote: >> Adding arguments to a function can mess up internal callbacks, btw, so I >> don't like modifying the >> existing function. > Which internal callbacks can be messed up by this change? They clearly > aren't tested, as the build is passing. > > Cheers, > Bilge There's a number of issues here. PHP-defined functions ignore excess arguments. C-defined functions error on excess arguments. A function with an optional second argument... may break if it gets passed an optional argument that isn't aligned with its expectation. intval() is the usual example (https://www.php.net/intval), but it would also impact something like trim(). If someone is using a function with one param and one optional param as a callback right now, suddenly passing the key as the second argument could cause all sorts of weirdness. Similarly, if someone is using a single-param C-defined function as a callback right now, and array_reduce() starts passing a second argument, it will fatal. I ran into this issue while building Crell/fp, and my only solution (after swearing a lot) was to just make two separate versions of every operation: One that passes the key and one that doesn't. (cf: https://github.com/Crell/fp/blob/master/src/array.php) The user has to pick the right one. That is, sadly, the only reliable solution, even if done in the stdlib. (Of course, the real solution is to introduce a separate map/dict type that has its own dedicated API for map/filter/reduce, but now we're well out of scope... Using the same structure for lists and maps is PHP's original sin.) --Larry Garfield
[PHP-DEV] [Vote] Property Hook performance improvements
Hi all. I have just opened the voting on the property hook (performance) improvement RFC. https://wiki.php.net/rfc/hook_improvements With the readonly bits pushed out to later, this is probably the shortest RFC I have ever written. :-) Vote opens now, and will close in 2 weeks on 29 July. -- Larry Garfield la...@garfieldtech.com
Re: [PHP-DEV] [RFC] [Discussion] Add WHATWG compliant URL parsing API
On Mon, Jul 15, 2024, at 9:20 AM, Máté Kocsis wrote: > Hey Ignace, Nicolas, > > Based on your request for adding support for RFC 3986 spec compatible > parsing, > I evaluated another library (https://github.com/uriparser/uriparser/) > in the recent days > in order to add support for the requested functionality. As far as I > can tell, the results > were very promising, so I'm ok to include this into my proposal (I > haven't pushed my > changes yet and haven't updated the RFC yet). > > Regarding the reference resolution > (https://uriparser.github.io/doc/api/latest/#resolution) > feature which has also already been asked for, I'm genuinely wondering > what the use-case is? > But in any case, I'm fine with incorporating this as well into the RFC, > since apparently > both Lexbor and uriparser support this (naturally). > > What I became puzzled about is the correct object structure and naming. > Now that uriparser > which can deal with URIs came into the picture, while Lexbor can parse > URLs, I don't > know if it's a good idea to have a dedicated URI and a URL class > extending the former one... > If it is, then in my opinion, the logical behavior would be that Lexbor > always instantiates URL > classes, while uriparser would have to decide if the passed-in URI is > actually an URL, and > choose the instantiated class based on this factor... But in this case > the differences between > the RFC 3986 and WHATWG specifications couldn't be spelled out, since > URL objects > could hold URLs parsed based on both specs (and therefore having a > unified interface is required). > > Or rather we should have a separate URI and a WhatwgUrl class so that > the former one would > always be created by uriparser, while the latter one by Lexbor? This > way we could have a dedicated > object interface for both standards (e.g. the RFC 3986 related one > could have a getUserInfo() method, > while the WHATWG related one could have both getUser() and > getPassword() methods). But then > the question is how interchangeable these classes should be? I.e. > should we be able to convert them > back and forth, or should there be an interface that is implemented by > the two classes? > > I'd appreciate any suggestions regarding these questions. > > P.S. due to its bad receptance, I got rid of the UrlParser class as > well as the UrlComponent enum from my > implementation in the meantime. > > Regards, > Máté I apologize if I missed this up-thread somewhere, but what precisely are the differences between URI and URL? My understanding was that URL is a subset of URI (all URLs are URIs, but not all URIs are URLs). You're saying they're slightly disjoint sets? Can you give some concrete examples of where the parsing rules would produce different results? That may give us a better sense of what the logic should be. --Larry Garfield
Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)
On Wed, Jul 10, 2024, at 1:38 AM, Mike Schinkel wrote: >> In fact, if you use an optimized/dumped autoloader, then Composer simply >> builds an internal giant lookup table of what class maps to what file. >> PSR-4 is then *completely irrelevant* at runtime. It's already one giant >> O(1) lookup map. That can be done *today*. That *is* done today. > > Yes, it can be done today. It *is* done today. By. Developer. Managed. Apps. > Already done. I explained how an `spl_autoload_map()` would do exactly > that above. > >> When you have a proven that it's even possible to have multiple local symbol >> tables, we can talk. Until then, please spare us. > > My one useful takeaway from your email — except that I already knew > that — was the need to figure out how PHP can handle multiple symbol > tables. Beyond that, your take your own advice and spare us (me) from > your contempt and condescension as they are not good looks on anyone. I find it amusing that several of your responses to me saying "you could do this stupid thing but no one does that" is "WordPress does that thing." I make no comment other than to observe it. But let me understand: In a thread started by Michael Morris where he explicitly said the most important thing for him is multi-version loading, you're going to insist you're talking only about moving Composer's classmap logic into core, and nothing about multi-version loading. If that's the case, then please be polite to Michael Morris and get out of his thread. Also, be aware that classmap-in-core was already discussed 3 years ago and went nowhere. https://wiki.php.net/rfc/autoload_classmap https://externals.io/message/113545 Largely because, as Sara said then, and Rowan just said on this thread, it can be done better in user-space and is already done better in user-space... by Composer. https://externals.io/message/113569 You even commented in that thread: https://externals.io/message/113554 So it's not a new idea, it's an idea that's already been greeted with a general "meh". Yes, most "developer managed apps" use Composer today to side-step the "bajillion autoloaders" problem. It's a solved problem. Nothing precludes Wordpress from doing the same. I admittedly have not looked at WP's core in a very long time, but I would be absolutely shocked if it wasn't pretty straightforward to build code into WP core that looks at the source directories of all plugins, finds the classes there, and builds a big index (stored in a cache directory or the database) that it can use in one single autoloader registered by WP itself. I know that can be done, because that's exactly how Drupal 7's autoloader worked. I know, because I wrote it. In 2008. (It was later modified by others, but the initial version was mine.) That would work even with WP's "download code and drop it on disk" model. That has been possible since PHP 5.2 at least, when I wrote exactly that for Drupal. It wasn't even that hard. Literally any "user managed app" could do the same. Why hasn't WP core done that in order to make life easier for plugin developers and avoid registering 50 separate autoloaders? I dunno, you should ask Matt Mullenweg. We have nothing to do with it. --Larry Garfield
Re: [PHP-DEV] [RFC] Property Hook improvements
On Mon, Jul 1, 2024, at 12:02 PM, Larry Garfield wrote: > Hi folks. As Ilija's been polishing off hooks to get the PR merged, > we've run into two small revisions that should make life better for all > involved. One is a performance improvement that requires a very slight > error handling behavior change, and the other is enabling readonly in > selected (but probably all of the relevant) circumstances. > > I'd say we expect these to be uncontroversial, but this is PHP. :-) So > I will instead just note that it's a short RFC and open the discussion > accordingly. > > https://wiki.php.net/rfc/hook_improvements Based on discussion here and off-list, and after confirming with Nicolas that lazy objects would be compatible with readonly properties already (which have very similar use cases in practice), we're going to hold off on the readonly hooks part of this RFC. I've split it off to its own RFC for later: https://wiki.php.net/rfc/readonly_hooks The other half of this RFC, removing the recursion guard in return for performance, has had no objections. Its discussion period ends Friday, so I will open the vote on that Monday-ish. --Larry Garfield
Re: [PHP-DEV] [RFC] Improve language coherence for the behaviour of offsets and containers
On Tue, Jul 9, 2024, at 7:52 PM, Levi Morrison wrote: >> Moreover, I know the traffic on the list has been pretty high, but I do >> intend to have this RFC up for voting for inclusion in PHP 8.4, and I'm not >> exactly sure how I am meant to interpret the lack of responses. > > I am personally strongly in favor of the direction. As mentioned in > the PR, my main concern is honestly quite a small one: I think > `Appendable::append` ought to be renamed. Maybe `Appendable` and > `FetchAppendable` too. > > The reason is that `append` is a common operation on a container type, > which is likely to want to implement these interfaces. I easily > identified a few such things with a quick GitHub search: > 1. > https://github.com/pmjones/php-styler/blob/5c7603f420e3a75a5750b3e54cc95dfdbef7d6e2/src/Line.php#L166 > 2. > https://github.com/ParvulaCMS/parvula/blob/dcb1876bef70caa14d09e212838a35cb29e23411/core/Models/Config.php#L46 > > Given that I anticipate these methods to largely be called by > handlers, and not by names, I think an easy solution is to just name > this `offsetAppend` to match the other offset operations. For example, > I don't anticipate code doing: > > $container->append($item); > > I expect largely they will do: > > $container[] = $item; > > So it doesn't really matter if the name is `append` or `offsetAppend` > for the main use-case, and thereby we avoid some road bumps on > adoption. Any SPL containers with `append`, such as ArrayObject, can > make it an alias of `offsetAppend`, I think? > > Anyway, this is a minor thing, and I will vote yes regardless of > whether it (and maybe the *Appendable interface names) are changed. > But I do think it would be prudent to change it. It would also match > the `offset*` convention of the other interfaces. Based on my research into collections with Derick, I agree that "append" is not a good name to claim for this interface; it would make it incompatible with standard collection method naming. offsetAppend() would neatly side-step that issue. +1 to what Levi said. As to my limited response so far, it's mostly because I read through the proposal in detail a few months ago when it was first informally put forward and liked it then, and it seems there haven't been any serious changes since for me to comment on. I am very much in favor, though. --Larry Garfield
Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)
oes Wordpress. Or TYPO3. Or any other project. Because that's a core PHP limitation. In Python, every module is really just an object with a big dictionary of the functions/classes it has. When you "import" a symbol from another module, the engine is doing little more than `$this['foo'] &= $that['foo']`. That's a core part of how the language works. (I'm not sure of Javascript's details, but I suspect from using it that it's similar.) PHP works very very differently. PHP has a single global list of symbols. (Well, two, for classes and functions.) Namespaces are just syntax sugar over very-long-names, nothing more. There is no "local symbol table," so having different local symbol tables point to different code blocks using the same name is not even conceivable. If you want to change that, and give PHP multiple local symbol tables, then autoloading... is utterly irrelevant. The question there is "how can we introduce local symbol tables in the engine without requiring 10 million developers to rewrite the file header of 1 billion PHP files across the world?" Honestly, I'm not convinced its even possible. Someone with more engine knowledge than I could be able to find away, maybe, but I am skeptical. If it's even possible, I suspect it would be an absurdly large amount of work and necessarily include many hard BC breaks. If you'd like to prove me wrong, go for it. But that's the problem to address. Debating file paths is about four steps down the line before it's even relevant. And even then... if you can't make a PSR-4-organized package (of which there are several hundred thousand) slot into that new model comfortably with zero effort on the part of the package author, it's doomed. So please, spare us the ill-informed descriptions of how you think autoloaders work, when you have demonstrated you do not know how they work. Spare us the litany of complaints about PSR-4 when you have demonstrated you don't know what PSR-4 says. Spare us the gnashing of teeth about how hard it is to use a Wordpress plugin that hasn't been updated in 10 years with a modern plugin because the former is still using a 10 year old abandoned version of some library, when that's not PHP's problem, that's a Wordpress maintenance problem. If you want to move this effort forward, here's your todo list: 1. Do some research in the engine to determine if local symbol tables are even possible without rewriting the engine. 2. Work through the highly complex logic of handling three layer overlapping transitive dependencies in a diamond pattern with conflicting version requirements. 3. Investigate the performance impact of maintaining multiple versions of the same code in memory at once, when the order they get loaded will vary by request. 4. Think through how you'd support *both* composer-based and "user managed" applications with such a model, especially projects that are already architecturally a decade out of date (like Wordpress). When you have a proven that it's even possible to have multiple local symbol tables, we can talk. Until then, please spare us. --Larry Garfield
Re: [PHP-DEV] [RFC] Improve language coherence for the behaviour of offsets and containers
On Thu, Jul 4, 2024, at 8:52 AM, Gina P. Banyard wrote: > Hello internals, > > I would like to formally open the discussion on an RFC I've been > working on for the past year: > https://wiki.php.net/rfc/container-offset-behaviour > > As DokuWiki is a bit of a faff at times, the Markdown sources are > available on GitHub: > https://github.com/Girgias/php-rfcs/blob/master/container-offset-behaviour.md > > The implementation is basically done, other than some mysterious JIT > issues that I haven't been able to pinpoint yet. > > > Best regards, > > Gina P. Banyard I want to find time to go through some of the bits in finer detail to be sure, but you've gone through enough finer bits that I doubt I'd find much to object to. :-) Strongly supportive here. --Larry Garfield
Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)
On Thu, Jul 4, 2024, at 5:48 AM, Rob Landers wrote: > If I could have one to be a PER first, it would be the container > interface (PSR-11). When it was originally worked on, there was > basically one lifecycle of an object: a request. For almost all > possible SAPIs, after the request ended, everything was gone. Today, we > basically have multiple ones if you are using modern runtimes: > 1. Environment Scope: configuration that survives execution of the > program > 2. Global Scope: services/entities that can exist beyond the lifetime > of a request, but may or may not (depending on runtime) > 3. Request Scope: services/entities that should be unique for every > request. > 4. Volatile Scope: services/entities that should be created every time > they are injected. > Right now, these are all mixed into one giant container, that may or > may not be shared between requests, because that is the interface we > have to work with. It isn't great :| but it works, barely. > > — Rob There's been on and off discussion this year about container registration, not just retrieval. That could be done as an add-on PSR, most likely. The challenge is that there's fundamentally different ways to go about registration, and little consensus on it. (And the people most interested in talking about it haven't wanted to go to the effort of organizing a Working Group.) I suspect scoping would have similar challenges. But if someone can get a working group together around a particular direction, we'd be open to that discussion. That would be entirely off topic for this list, though, so let's not go further down that rabbit hole. --Larry Garfield
Re: [PHP-DEV] [RFC] Property Hook improvements
On Mon, Jul 1, 2024, at 8:32 PM, Tim Düsterhus wrote: > Hi > > On 7/1/24 19:02, Larry Garfield wrote: >> I'd say we expect these to be uncontroversial, but this is PHP. :-) So I >> will instead just note that it's a short RFC and open the discussion >> accordingly. > > Big fan of the performance improvement, given that I convinced Ilija to > look into that once more. Really happy with what he found there. > > For the second part about supporting readonly: I don't want to rush this > in the last few weeks before feature freeze, especially since the word > 'investigating' appears in the RFC text. Given that readonly is > currently entirely unsupported, this could very well be added with PHP > 8.5, allowing folks to really think about the implications and how it > interacts with stuff. That's a "no" from my side. "Investigating" here is a small term, honestly. Ilija just hadn't had a chance to poke at it to see where is more feasible. I expect it would be a day or so at most to sort that part out; we just wanted to get the discussion going given the timing, and he didn't have time over the weekend. :-) Are there specific concerns you have about implications, or just a general "dude, it's July" sense? > Best regards > Tim Düsterhus > > PS: Small typo: '$this-dbApi->loadCategory($this->categoryId);', '>' > missing there after 'this-'. Fixed, thanks. --Larry Garfield
Re: [PHP-DEV] [RFC] Property Hook improvements
On Mon, Jul 1, 2024, at 5:28 PM, Lynn wrote: > "A side effect of that optimization, however, is that we cannot > proactively detect the bug above. Instead, it would result in an > infinite loop, which would eventually trigger a a stack overflow." > > This got a small typo ("a a" at the end). Fixed, thanks. > This reads no different to me > than infinite recursion between 2 methods. It honestly does not bother > me, and any static analysis tool will be able to pick this anyway. > Sounds like a free performance gain to me! Yep, it would be exactly 2 method recursion, and the engine would naturally treat it as such. --Larry Garfield
[PHP-DEV] [RFC] Property Hook improvements
Hi folks. As Ilija's been polishing off hooks to get the PR merged, we've run into two small revisions that should make life better for all involved. One is a performance improvement that requires a very slight error handling behavior change, and the other is enabling readonly in selected (but probably all of the relevant) circumstances. I'd say we expect these to be uncontroversial, but this is PHP. :-) So I will instead just note that it's a short RFC and open the discussion accordingly. https://wiki.php.net/rfc/hook_improvements -- Larry Garfield la...@garfieldtech.com
Re: [PHP-DEV] Re: [Discussion] Add date_test_set_now() function
On Mon, Jul 1, 2024, at 3:56 PM, Go Kudo wrote: > I apologize, the main point of my explanation was off. > > To put it simply, I'm suggesting that it might be good to implement > convenient and commonly used features from Carbon at the ext-date level. > > I'm proposing the date_test_set_now() function for the following reasons: > > User-land libraries like Carbon / Chronos have a setTestNow method, > indicating a potential demand for this feature. > It's impossible to determine whether a value is relative or absolute > time from either user-land or Extension. > While this is convenient for maintaining legacy systems, that's not the > essence of this proposal. > > As you pointed out, this is an issue that should ideally be solved in > user-land. I deeply understand that. > > However, in reality, PHP's time-related processing is diverse, and to > comprehensively handle all of these, it seems necessary to address this > at the ext-date level. > > https://www.php.net/manual/en/ref.datetime.php > > For example, you might want to use the date() function to display the > current time on a whim. However, doing this ruins everything. > > Even if other parts of your code use Carbon or comply with PSR-20, > using the date() function is problematic because the current time it > references cannot be modified. > > `date_test_now(\DateInterval $shiftInterval)` can solve this problem. > > Of course, there might be various side effects. However, seeing > `Carbon::setTestNow()` being used in various places, I think this > feature might be necessary. > > I would appreciate your thoughts on this. > > Best Regards, > Go Kudo They are unchanged. > For example, you might want to use the date() function to display the > current time on a whim. So don't do that. Relying on global mutable state is a bug. That older parts of the stdlib made that mistake doesn't mean we should continue it. (See also the Random extension, which also works to avoid global mutable state.) > Of course, there might be various side effects. Exactly. This is not something to just brush aside with a comment. The way Carbon does it is wrong, for the same reason: It just sets a global state. The correct answer is to use PSR-20 and inject a fixed-time instance of the Clock. --Larry Garfield
Re: [PHP-DEV] [Discussion] Add date_test_set_now() function
On Mon, Jul 1, 2024, at 1:07 PM, Go Kudo wrote: > Hi, Internals. > > I've been absent for a long time due to poor health. I'm finally back. > > I maintain a legacy application written in PHP, and occasionally need > to fake the current time for testing purposes. However, PHP doesn't > provide a standard way to fake the current time, so I've been changing > the OS's current time to do this, which is quite painful. > > This can be avoided by using third-party libraries (such as > Carbon::setTestNow()). However, it's almost impossible to modify all > parts of a legacy application that depend on the current time. > > Another option is to use libfaketime > (https://github.com/wolfcw/libfaketime), but this is also quite painful > to use. > > Since this was absolutely necessary for my work, I implemented this > functionality as a PHP Extension. (Please ignore the dirty > implementation related to PDO. I'm not planning to propose it this > time.) > > https://github.com/colopl/php-colopl_timeshifter > > However, this Extension has some problems. > > The first is that there's no way to determine whether the format passed > to the ext-date parser is relative or absolute time, resulting in a > dirty hack using usleep. The second is that it depends on timelib, so > it breaks when upstream changes related to timelib are made. > > So, how about adding a `date_set_test_now(\DateInterval > $shiftInterval)` function to ext-date? > > This function would treat the current time as shifted by the passed > DateInterval. Since it's implemented on the ext-date side, there's no > need for dirty hacks using usleep. > > I'd like to hear your opinions. Thank you. > > Best Regards, > Go Kudo We don't generally add features just to support very-old legacy code. These days, the correct answer would be to use PSR-20. (Implementations are trivially easy, many available, and it's dead easy to write your own.) That doesn't much help legacy code, but adding global features just to support legacy code that should get refactored anyway doesn't seem like a great idea. --Larry Garfield
Re: [PHP-DEV] [Initial Feedback] Typed Arrays
On Mon, Jul 1, 2024, at 12:21 PM, Richard Miles wrote: > Howdy Rob, > >>> I appreciate your feedback, and I think it’s valid. I try to compare my >>> expectations to what is possible in typescript. >> >> I feel like Typescript is the wrong model to follow. The type system in >> Typescript is Turing Complete >> (https://github.com/microsoft/TypeScript/issues/14833) and php barely has a >> type system. It doesn’t even have consistent type checking, for that matter >> (properties are checked differently than arguments which are checked >> differently than constructor arguments — and the fact they agree with each >> other at all, is interesting, because they don’t arrive at the same >> conclusions in the same way. I’ve been dealing with subtle bugs here for >> weeks on an unannounced RFC implementation) and this is why generics is a >> can of worms: implementing it would essentially force a rewrite of the type >> system into a proper type system. >> >> In my honest opinion, before we can even have this type of conversation, we >> need to have an RFC about the syntax (there may already be one, I haven’t >> checked — and internet is spotty where I currently am). The pattern matching >> RFC was proposed as though it would be written one way, people have thrown >> out ideas of different syntax, but I don’t think there is an “official” >> syntax. A good starting point may be to simply propose an RFC about syntax >> so future RFCs can be consistent. >> >> — Rob > > I actually did not know it was turning complete, very interesting! > While it is easy for anyone to say, ‘we're not even close to > typescript,’ > that’s precisely what brings me to the table. I would be happy with us > just voting on syntax. It seems like past RFC’s only > ever got hung up on generics (wrongfully?). I want to work on > implementing generics, too, after this. I feel this is probably a good > stepping stone. > > A vote would solidify the following: > > > interface iArrayA ['a' => string ] > interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’ > => SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ] > $array = (iArrayA &| iArrayB) [ ‘a’ => ‘hello’ ]; > > > That would allow us to move into an implementation discussion, which is > also absolutely needed. > > Best, > Richard Miles As Stephen already said, we have this already. It's spelled like this: class A { public function __construct(public string $a) {} } class B extends A { public function __construct( public string $a, public string $b, public ?string $c, public SomeClass $d, public A $e, mixed $f, ) {} } If you know the keys at code time, use a class, not an array. Full stop, period, end of story. Using an array as a record object in PHP >= 7 *is wrong*. It's slower, more memory-intensive, less ergonomic, harder to debug, harder to statically analyze, harder to learn, harder to use. If you're still doing that, it's past time to stop. If your legacy application from the PHP 3 days is still doing that, it's past time to upgrade it. So new language features to make "misuse arrays as objects" easier are actively counter-productive. A Dict / Hashmap is appropriate when you do *not* know the keys in advance, and thus cannot use a pre-defined object for it. There are plenty of use cases for that, but in that case, all you need type-wise is the key type and value type, because all entries should be of the same type (give or take inheritance). Mixing in random other types... is wrong. That's the whole reason why people keep talking about collections/typed arrays/generics. So the "array interface" syntax you keep posting is actively counter-productive. --Larry Garfield
Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)
On Sun, Jun 30, 2024, at 8:28 PM, Michael Morris wrote: > So let's take another crack at this based on all the points raised in > the thread. This should also underline why I don't consider this an RFC > - I am iterating until we arrive at something that may be refinable > into an RFC. And I say we because without the aid of those in this > conversation I would not have arrived at what will follow. > > Before I continue I would like to apologize for being somewhat > irritable. We're all here because we enjoy using this language and want > to see it improved and prevent bad changes. Opinions will differ on > this and in the heat of the moment of arguing a point things can get > borderline. > > > Returning to a point I made earlier, Composer isn't used on Wordpress. > I went over to the Wordpress discussion list and read over why, because > that discussion provides clues to what kind of package management may > be adoptable. I think the largest point is that Wordpress should be > usable without ever resorting to using the command line. Yes, it does > have a command line tool - wp-cli - and it is powerful, but using it as > an administrator of a Wordpress site is not required. > > The largest block to composer's inclusion in Wordpress is the inability > to run multiple versions of a module. Yes, it's a mess when this > happens, but if you're an end user, you just want your plugins to work. > If one plugin that no one has updated in a year that you're using is > consuming version 2 of a package, you're gonna be annoyed at best if > the module stops working when you install a new plugin that is using > version 3 of the same package and has a BC break in it. Composer can't > resolve this easily. There's still a few key, fatal issues in this version of the proposal. 1. It appears like it expects PHP to be able to write to disk itself as part of normal operation. This is an immediate fatal flaw. Most security best practices these days recommend that the disk where code is be read-only. Some hosting companies mandate it. Any language feature that precludes that is dead in the water. 2. Supporting multiple versions of the same class is *wy* out of scope. You seem to imply Composer is the reason we cannot do that. That's incorrect. PHP has a single global symbol table for classes. (And a separate one for functions for not-great historical reasons.) Trying to define the same class twice will fatal the engine. While there are some screwy conditional-include games you can play, they're fragile and still would not allow WP Plugin A to use v1 of a library and WP Plugin B to use v2 of a library. I am not versed in that part of the engine, but I would be shocked if splitting up the global symbol table was possible, let alone feasible. 3. Using URLs as the package naming system is the dumbest thing Go ever did. Let's not replicate that. :-) I think the core problem here is that this thread keeps trying to graft Python/Go/JS/Rust style packages onto PHP. PHP, however, is structurally closer to Java/C#, so following that package logic (which is built off of namespaces) would be far more natural, and thus far easier to migrate to. Really, the only targets we should be looking at, IMO, are: 1. Package-level visibility. 2. Giving the compiler/optimizer/JIT a larger "scope" of code to compile/optimize at once, so it can do smarter things. I think everything else is a distraction. I have some thoughts on how we can far more easily accomplish 1, and maybe 2, but I will probably hold off on that for now as it would just get lost in the noise of this thread, plus the list is too busy as is these days with everyone trying to get their in-flight RFCs finalized before the feature freeze deadline. :-) (Really, this is a poor time to be having this kind of discussion. Fall is generally the better time, just logistically.) --Larry Garfield
Re: [PHP-DEV] [Initial Feedback] Typed Arrays
On Mon, Jul 1, 2024, at 4:48 AM, Michał Marcin Brzuchalski wrote: > pon., 1 lip 2024 o 03:01 Larry Garfield napisał(a): >> Contextual point: Nearly every other major language at this point that has a >> meaningful standard library has gone with a three-separate-object approach >> (Seq, Set, Dict, called various things). At least Python, Javascript, Rust, >> Kotlin, and Swift, in my research. (Go doesn't, but Go avoids having >> features by design.) And AFAIK *every* language except PHP and Lua >> separates sequences from dictionaries. Typed arrays will not full resolve >> the seq vs dict problem, which is arguably PHP's original sin. And there's >> a lot of weird issues to resolve around what the syntax could even be, since >> PHP has untyped variables. >> >> The custom collection syntax Derick has been working on is a second-best >> alternative to generics, essentially. It is less ergonomic, no question, >> but can also be implemented without generics, and so is about 5x easier to >> do. If we could get native generics, then I think everyone involved agrees >> building collections off of that -- in essentially the same way as every >> language I mentioned above --- would be preferable to a custom one-off >> syntax. >> >> --Larry Garfield > > Considering other languages it is worth mentioning that Java and C# > have generics AND typed arrays that act as a typed list/seq so sure it > doesn't solve all problems otherwise these languages wouldn't have both > of them. I believe in those languages Array came first, and then the collections were added later when they determined that Array was insufficient and too low-level. (I'm not an expert on the history of either language, but that's my understanding from reading their documentation.) Using the collections is the preferred approach now for most applications. > From my personal experience, a typed list/seq solves most cases where I > need the elements of an array to be strictly instances of a specific > type. > What I see typed list/seq like `string[]` has more ergonomics, it can > be used to interact between libraries and application code without > creating intermediate objects, while collection proposal always > requires declaring type - this simply multiplies the number of declared > types and create more coupling where it is not needed! Also, most cases > I work with are just fine with using just foreach or array_ family > functions. Yes, the need to create the monomorphized object yourself is a downside of the dedicated collections syntax. No question. The trade-off is that it's vastly easier to implement than either full generics or typed arrays. We haven't fully developed it yet as there's still experimentation going on (by people with far more engine knowledge than me) to see if we can have our cake and eat it too. > This doesn't have to collide with generics in any way, as mentioned > before in the thread these features may exist simultaneously, typed > list/seq can translate in the future to a generic type. > I believe it'd make people's lives easier if we could have this in > place soon. > Don't you agree? > > Cheers, > Michał Marcin Brzuchalski 1. I think you are vastly under-estimating the level of effort for making typed arrays, and making them performant. Arnaud has been exploring that, and it's far from trivial. "Have this in place soon" hand-waves over an awful lot of complexity. 2. You're correct that typed arrays and generics could coexist in the language, if both could be implemented. But that is also a lot of work, with overlapping problem spaces. 3. The core failing of typed arrays is that they still don't guarantee a sequence; everything is still a string|int key dictionary with no support for object keys, and PHP's screwy array-specific type casting. Frankly, people who don't see the challenges here have not tried to write array-handling libraries. :-) (Crell/fp taught me all kinds of things about how broken arrays are, due to their fundamental unpredictability.) --Larry Garfield
Re: [PHP-DEV] [Initial Feedback] Typed Arrays
On Sun, Jun 30, 2024, at 11:13 AM, Michał Marcin Brzuchalski wrote: > Hi Richard, > > czw., 27 cze 2024, 22:33 użytkownik Richard Miles > napisał: >> >> > I worked with Joe Watkins to do a proof-of-concept for generic traits. >> > It's a bit old since it's from 2017, but could be a useful starting >> > point if you are serious about pursuing this idea: >> > >> > https://github.com/php/php-src/compare/master...morrisonlevi:php-src:parameterized_traits >> >> >> I’m also interested in this; it will help see branches like these. >> Did you ever get the POC working? What did you feel like was the biggest >> hurdle? > > There even was an RFC in voting which Joe implemented and it addresses > nearly what is discussed it this thread https://wiki.php.net/rfc/arrayof > > I must admit that the collection proposal is bit too complex to > address such tiny but powerfully in my opinion functionality which is > typed array. What Derick showed looks more like generic collection and > such require declaring it's type. In my opinion this is way too mush > hassle to declare as many collection types as many usages in > application. Also two collection types with the same collection item > type will not be compatible from type perspective. While typed array > seems much more clear and compatible in all places where typed array is > needed without declaring separate type for each usage. > > If I were to choose between typed-array and collection like Derick > showed a little bit I'd choose typed arrays definitely as a first > feature to be merged into PHP. > > Cheers, > Michał Marcin Brzuchalski Contextual point: Nearly every other major language at this point that has a meaningful standard library has gone with a three-separate-object approach (Seq, Set, Dict, called various things). At least Python, Javascript, Rust, Kotlin, and Swift, in my research. (Go doesn't, but Go avoids having features by design.) And AFAIK *every* language except PHP and Lua separates sequences from dictionaries. Typed arrays will not full resolve the seq vs dict problem, which is arguably PHP's original sin. And there's a lot of weird issues to resolve around what the syntax could even be, since PHP has untyped variables. The custom collection syntax Derick has been working on is a second-best alternative to generics, essentially. It is less ergonomic, no question, but can also be implemented without generics, and so is about 5x easier to do. If we could get native generics, then I think everyone involved agrees building collections off of that -- in essentially the same way as every language I mentioned above --- would be preferable to a custom one-off syntax. --Larry Garfield
Re: [PHP-DEV] [RFC] [Discussion] Add bcdivmod to BCMath
On Sun, Jun 30, 2024, at 10:11 AM, Saki Takamachi wrote: > Hi, > >>> Just a suggestion: what about making the returned array an associative >>> array ? Like so: >>> ``` >>> array( >>> 'quotient' => 61, >>> 'remainder' => 1, >>> ); >>> ``` >>> This would remove the need for devs to remember the order of the return >>> values and would make the return value self-documenting. >> >> An associative array would combine the worst of an array (no IDE >> autocompletion, no strong typing, increased memory usage) with the worst of >> an object (no easy way to extract the values into local variables with array >> destructuring). >> >> The example in the RFC doesn't show it, but the following makes the proposed >> API really convenient to use: >> >>$slicesOfPizza = new BcMath\Number(8); >>$mouthsToFeed = new BcMath\Number(3); >>[$perMouth, $slicesLeft] = $slicesOfPizza->divmod($mouthsToFeed); >> >> Note how the order of values matches the words in the method name. First the >> result of 'div', then the result of 'mod’. > > > Thanks, I have added this example to the RFC (Please let me know if you > have any problems). > > >> I came here to say the same thing. The best solution would be not having to >> refer to documentation or experiment with values, and this hits the nail on >> the head. >> >> The only thing that makes it weird is having to write it out, which at that >> point, it is probably faster to type out bcdiv and bcmod separately. >> >> Have you considered simply using references passed to the function? I feel >> like that is more idiomatically php. > > Of course, that idea was proposed, but it was pointed out that current > PHP tends to avoid such implementations, so we didn't adopt it. The > reason why passing by reference was not adopted was added to the RFC. > > Regards, > > Saki I agree an associative array is the second-worst option. An inout by-ref argument is the absolute worst. Normally my default position is that when in doubt, make it a structured object with properly defined properties, and screw whatever micro-performance hit it is, you won't notice. 99% of the time I believe that is the correct approach. I can see the argument that this is the other 1%, since it's just two values, which will basically always be wanted separately but both wanted (meaning divmod(...)->divsor is kinda pointless), and their order should be fairly self-evident. However, in that case I would urge that both the RFC and the resulting documentation *always* use examples that return into a `[$foo, $bar]` destructured list. Don't even suggest that people should use 0 and 1 indexes. It's a tuple for deconstruction, that's it, if you're using it some other way you're probably wrong. Politely ignore that it's even possible, lest we lead people down the dark path. (Which means removing the current index-using example and just keeping the pizza example.) --Larry Garfield
Re: [PHP-DEV] [RFC] [Discussion] Add WHATWG compliant URL parsing API
On Sun, Jun 30, 2024, at 1:00 AM, Máté Kocsis wrote: >> It mirrors the interface, but it can’t be swapped out for a UriInterface >> instance, especially since it can’t be extended, so I wouldn’t consider it >> compatible. I would still need to write a compatibility layer that composes >> Url\Url and implements UriInterface. > > I guess my words were slightly misleading: what I should have written > is that the methods themselves are compatible. > >> Since PSRs are concerned with shared interfaces and this class is final and >> does not implement any interfaces, I’m not sure how you envision “a next >> iteration” of PSR-7 to use this directly, unless what you mean is that >> UriInterface would be deprecated and applications would type directly >> against Url\Url. > > Yes, I meant the latter exactly. If we had a well-usable URL object > representation in the standard library, then there would be no need to > have an userland interface as well (unless they have different behavior > or purpose). Analogically, we have DateTimeImmutable, and there is no > PSR for a date time interface. (I know there is Carbon and other > libraries, but they are for convenience, not for interoperability). I cannot speak on behalf of FIG here, but as a long-time member of FIG and a member of the Core Committee, I would urge you to *not* try to make a core Url object compatible with UriInterface. It's solving a slightly different problem, using a language that is very different (PHP 8.4 vs 5.5 or so), with somewhat different constraints. Instead, let's make sure that any new Url object is *composable* by PSR-7 UriInterface. A UriInterface implementation that is backed by a Url object internally should be an easy task to do if anyone wants, and we should make sure we don't do anything that makes that unnecessarily hard, but right now the language is simply not capable of making core Url a drop-in replacement for UriInterface, so let's not even try. Whether that means Url should be readonly or not, have getters/setters/withers, split authority into user:pass, etc. are things we should discuss on their own merits, not based on "well PSR-7 did it this way over 10 years ago, so we'll just do that." --Larry Garfield