Re: [PHP-DEV] [RFC] Policy on 3rd party code

2024-10-08 Thread Mike Schinkel
> 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..."


> On Sun, Oct 6, 2024, at 12:33 PM, Mike Schinkel wrote:
>> 
>> IOW, given that all the current infrastructure really supports are 
>> static pages — without a gargantuan effort to write and maintain a 
>> custom framework from scratch by unpaid volunteers — the resultant 
>> website can only realistically be static pages. 
> 
> Developing and maintaining the PHP websites is far from a gargantuan effort, 
> as evidenced by how it is currently (and has long been) maintained on a very 
> ad-hoc basis by a very small number of volunteers with some work that is now 
> sponsored by the PHP Foundation. (I believe that amounts to maybe the 
> equivalent of one full-time person.)

What I was thinking when I spoke of a "gargantuan effort" was if a team were to 
try to duplicate the functionality of a modern website vs. just maintaining the 
aging and minimal website that is currently php.net <http://php.net/>.  

> I think a proposal for the PHP project taking on something like centralized 
> databases of "all" third-party packages also needs to come up with a very 
> good rationale as to why that will turn out differently than how PEAR and 
> PECL did.

That rationale is an easy one. 

1. First, both PEAR and PECL are package managers. I was proposing a directory. 
 Directories are an order of magnitude easier to manage than a package manager.

2. PECL was an extremely high bar as it was a package needed to be written in 
C, so we should just ignore that one.

3. PEAR had huge friction because (from what I understand) it required approval 
from members of the PEAR Group to be included.

Let's instead compare to examples that turned out very different from PEAR and 
PECL, and although are arguable also package managers it is their directory 
aspect that I am focusing on and that IMO has been a significant reason for 
their success:

- https://packagist.org/ <https://packagist.org/> 
- https://wordpress.org/plugins/ <https://wordpress.org/plugins/>
- https://www.drupal.org/project/project_module 
<https://www.drupal.org/project/project_module>

The reason those three have been far more successful has a large amount to do 
with the fact that the directory is managed by all the individuals in the 
community with solutions to showcase and and not a small group of overworked 
and underpaid individuals, and especially not having gatekeepers who must scan 
everything and who have subjective approval for inclusion. 

And ensuring against bad actors have obviously been effectively managed by 
these other projects.

Given all those factors I do not see a strong argument to compare the 
experience with PECL and PAIR to the idea of php.net <http://php.net/> hosting 
a directory of 3rd party solutions.

> (And I think that "minus any objectively determined bad actors" is 
> hand-waving away some extremely hard non-technical issues.)


While I would admit there may be some hand waving there, but to claim something 
is "extremely hard" without examples as a justification for not doing it is 
even more hand-wavy.  Care to delineate at least of few of those extremely hard 
non-technical issues you envision to see if they are indeed extremely hard?

>> Or, imagine a store where PHP could sell T-Shirts, plushies and more, 
>> all to fund more core development?
> 
> I have a hard time imagining that this would ever be more than a rounding 
> error compared to the sponsorships and individual contributions that the PHP 
> Foundation currently relies on.

Maybe, maybe not. 

But that perspective obscures the point I was trying to make. It is entirely 
possible that soliciting an RFP for a website that could also help generate 
revenue would present the community with ideas that nobody here has even 
considered.

One this is for absolutely certain, though.  Keeping the website as-is will 
certainly not generate any additional revenue.  

For me I would rather bet on the potential for innovation than bet against it.

> Frankly, I find your proposal dubious because it assumes that there is some 
> body of "interested stakeholders"  who are going to be able to come to an 
> agreement on an RFP tha

Re: [PHP-DEV] [RFC] Policy on 3rd party code

2024-10-06 Thread Mike Schinkel



> On Oct 7, 2024, at 1:39 AM, Larry Garfield  wrote:
> 
> 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.  

It is not off-topic, because it directly addresses the concern of mentioning or 
not mentioning web frameworks and not using them for internal use.

> 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.

However, yes, this point is completely valid, and can and should happen sooner 
and with or without what I suggested.

-Mike

Re: [PHP-DEV] [RFC] Policy on 3rd party code

2024-10-06 Thread Mike Schinkel
> On Oct 2, 2024, at 3:36 PM, Andreas Heigl  wrote:
> IMO the PHP website is more or less a bunch of static pages. There is not 
> really much interaction necessary. So having a framework might not 
> necessarily be The Thing.

You may be confusing cause with effect.  

IOW, given that all the current infrastructure really supports are static pages 
— without a gargantuan effort to write and maintain a custom framework from 
scratch by unpaid volunteers — the resultant website can only realistically be 
static pages. 

Frankly, I envision the PHP website could be so much more if developing and 
maintaining it were not a gargantuan effort. Like WordPress' plugin and theme 
repositories, PHP could have a database of *all* third party offerings — minus 
any objectively determined bad actors — and showcase to the world all that the 
extended PHP community has to offer.

Or, imagine a store where PHP could sell T-Shirts, plushies and more, all to 
fund more core development?


> 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.

What do I mean by "merit?"  

Consider the potential of adopting a new approach where PHP puts out a call for 
RFPs to any and all who are interested in submitting a proposal to build and 
maintain a website for PHP for three (3) years at a time. 

Interested stakeholders could join the PHP internal infrastructure mailing list 
and brainstormwhat is wanted tor the website and then prepare an RFP to put out 
for bid.  Nominally we would do so without paying for the service — their 
benefit would be getting prominently featured as the developer and maintainer 
of the website — but we could ask organizations in the community like JetBrains 
to pitch into a pot that could go to the winner of the bid, if we want to.

Then we take proposals from the projects themselves, any agency, and/or any 
other organization that want to propose and we have the members of the PHP 
internal infrastructure mailing list create a short list of the proposers based 
on criteria such as if we think they will be able to maintain doing so for a 3 
years as well as what they actually propose, and finally have all voting 
members would vote on it.

Why would we do it his way?  Because this is how web development for 
organizations usually gets done today. I was involved in a agency project back 
in probably 2017 to build the website for the Agile Alliance 
(www.agilealliance.org). Certainly they had community members that could have 
built it but they chose instead to have it done by deciding what they wanted 
and they putting out an RFP. The result was they actually got the features they 
wanted in the near term instead of looking back 10 years or more thinking "When 
we can get around to it we can implement...whatever."

We would want to start this process well in advance to ensure enough people 
know about it and how time to submit a proposal — e.g. 18 months? — and that 
the RFP process for 3 years later would start a year after the site is 
launched.  I can imagine that a lot of PHP-focused YouTubers would be all over 
promoting this.

Then the unpaid volunteers here need not be as highly skilled nor as burdened 
to maintain all the technical infrastructure and can instead focus on 
maintaining the actual **content**. 

The concern for bias also gets thrown out the door because it is based more on 
merit, and the decision is widely distributed across all the voting 
stakeholders in PHP in a relatively transparent process.  We could even say 
that any framework used for the last 3 years cannot be awarded the winning bid 
for the next 3 years to give more "big names" as shot at being the framework 
chosen.

There are tons of details that would need to be worked out, but as this is a 
wildly different approach from any the community has taken in the past — 
although as I said this is the common approach organizations take today to 
build and maintain websites — if it gets shot down by too many then no need to 
discuss the details any further.

-Mike
[1] I am being deliberately hyperbolic here for hopefully humorous effect. :-)


Re: [PHP-DEV] [RFC] [Discussion] Add get_declared_enums() function

2024-10-06 Thread Mike Schinkel

> On Oct 6, 2024, at 3:25 AM, Juliette Reinders Folmer 
>  wrote:
> 
> On 4-10-2024 13:44, Nicolas Grekas wrote:
> 
> Hi Nicolas,
>> # Introduction of the new function: get_declared_enums()
>> 
>> About this proposal, I shared a one-liner in the previous thread that shows 
>> listing only enums is trivial already.
>> IMHO we don't need this function since the engine already provides 
>> everything one needs if they want to list enums. I won't object either, I'm 
>> just "-0".
> 
> The upside of a PHP native function would be one of performance.
> 
>> # Deprecation of using class_exists() on enum names
>> 
>> This is a big NO on my side. This will break perfectly fine code for the 
>> sake of some high level ideas that matter less is practice than ensuring 
>> stability of the PHP platform. A BC break has to be worth it and this is 
>> clearly not the case to me. The canonical examples are checks like 
>> `class_exists($c) || interface_exists($c, false) || trait_exists($c, 
>> false)`. This is common code to check if a symbol exists in 
>> current PHP. Yet, with your RFC, all such checks would become broken 
>> immediately.
> 
> Well, this statement made me curious to see just _how_ common this type of 
> code is, so I've done a scan of the Packagist top 2000 projects [1].
> 
> The check you mention is used a total of 36 times in ~20 packages out of 2000 
> (includes some duplication, mostly within Symfony, which also contains the 
> fast majority of the uses of the above mentioned combination).
> 
> The full break down of the scan results [2] are as follows:
> 
> Combination of the following function calls within a set of parentheses 
> (typically: control structure condition):
> 4 out of 4: class_exists() + interface_exists() + trait_exists() + 
> enum_exists() 3
> 3 out of 4: class_exists() + interface_exists() + trait_exists()  
>   36
> 2 out of 4: class_exists() + interface_exists()   
>  131
> 2 out of 4: class_exists() + trait_exists()   
>8
> 2 out of 4: class_exists() + enum_exists()
>1
> 2 out of 4: interface_exists() + trait_exists()   
>1
> 
> 
> Combination of the following function calls within the same function scope 
> (not necessarily in the same statement, excluding the above):
> 4 out of 4: class_exists() + interface_exists() + trait_exists() + 
> enum_exists() 2
> 3 out of 4: class_exists() + interface_exists() + trait_exists()  
>   17
> 3 out of 4: class_exists() + interface_exists() + enum_exists()   
>3
> 2 out of 4: class_exists() + interface_exists()   
>   32
> 2 out of 4: class_exists() + enum_exists()
>4
> 2 out of 4: class_exists() + trait_exists()   
>2
> 
> Please note that not all of this code would need updating.
> 
>> BTW, this makes me wonder if we could have a new symbol_exists() function, 
>> that'd basically do the above checks in one go? Mixing this idea with 
>> Claude's, the signature could be symbol_exists($class, $filter = -1, 
>> $autoload = true), where $filter is a bitfield that'd allow listing only 
>> classes, abstract classes, interfaces, enums, traits at will?
>> 
>> # Change of the return value of get_declared_classes()
>> 
>> This proposal is problematic on two aspects:
>> The planned BC break feels needless to me. Its motivation is very moot 
>> compared to its impact on the PHP community, which will be forced to update 
>> perfectly fine code.
> Again, let's look at the real world impact based on a scan of the Packagist 
> top 2000.
> 
> In the top 2000 packages, there are only 47 calls to the 
> `get_declared_classes()` function. These calls are found in 29 packages. 
> [1][3]
> And for the record, there are only 16 calls each to 
> `get_declared_interfaces()` and `get_declared_traits()`.
> 
> Also note that not all of this code would need updating, only that code which 
> is also targeting enums.
> 
>> The BC break is planned without any ahead-of-change deprecation notice 
>> (except doc of course). From a deprecation policy POV, we reject this 
>> practice in the Symfony community. We don't do "hard BC breaks", or 
>> "unannounced" ones: we mandate that any BC break is first announced in the 
>> current major. This ensures the community won't miss the notice, and won't 
>> discover the BC break when it's very late and thus costly. There is always a 
>> way to follow that policy, so I'd strongly recommend adopting this practice 
>> in PHP itself, and in this RFC today. Here, this could be done by either 
>> keeping the function as is in PHP 9, or just deprecating it (in favor of 
>> get_declared_symbols()?)
> 
> I hear what you are saying and largely agree with you. The problem is, of 
> course, that it seems unlikely that we can find a way to throw a depreca

Re: [PHP-DEV] Zephir, and other tangents

2024-09-22 Thread Mike Schinkel
 I have discredited above.

Second, that sounded like a Freudian slip where you said the quiet part out 
loud. Is this about you somehow having a hot button about "some people wanting 
to make money" rather than accepting people just want to be able to write 
better and faster websites in PHP? If "some people wanting to make money" were 
the discrediting bar then (almost?) every feature request could be denied on 
that basis. 

> Honestly, a DSL would be the perfect solution here. Anyone familiar with 
> writing PHP extensions knows about `gen_stub.php`, which scans PHP stubs and 
> generates the corresponding binding C code. 

When and where does the C code get compiled? 

And isn't that what Zephir actually is?

> I've often thought this process could be extended to handle more complex 
> scenarios like promoted properties, simple expressions (e.g., assignments, 
> property access, comparisons), and anything that can be easily translated 
> into C code.
> 
> V8 has a similar tool called Torque, and I've always wondered what something 
> like that would look like for PHP. It would result in a strict, statically 
> typed subset of PHP that satisfies all the requirements, except for the last 
> one (which it would only partially fulfill).
> 
> Since the generated code would interface directly with the Zend API, we can 
> consider the DSL code as safe as the PHP implementation itself. While there 
> wouldn't be CPU throttling, hosts shouldn't have major objections since it 
> would essentially be as safe as PHP.
> 
> Most importantly, this approach would benefit everyone. It would have no 
> third-party dependencies and would only need to evolve alongside PHP/Zend as 
> they grow.
> 
> That’s how I would approach it.

I await your proposal.  Sincerely. 

And I don't mean to the level of an RFC, but a document that details how it 
would work, and one that could be discussed and commented on as you can on a 
Github repo.

Note I am not advocating fro a *specific* approach — e.g. WASM — I am advocated 
to achieved the stated goal, e.g. an extension mechanism that can run at near 
native speed for low-level string parsing and maths that realistically will be 
able to be run on managed hosts which IMO means they have to be adopted by 
major CMS and/or Frameworks as requirements if not at least recommendations. 

If your ideas can achieve those goals, I would fully be behind them.  (I am 
however skeptical that what you proposal can achieve all those goals; prove me 
wrong.)

> On Sep 20, 2024, at 4:18 AM, Rowan Tommins [IMSoP]  
> wrote:
> On 20 September 2024 06:20:46 BST, Mike Schinkel  wrote:
>> Moot point as it cannot be run on a managed hosted server.
> 
> Why not? Only because the people managing that server haven't been persuaded 
> to include it as an option. And that is mostly because it's currently 
> experimental, and there isn't wide demand for it.

You can hypothetical all day long, but the reality is that if something is not 
shipped with PHP, someone wanting to write PHP code that a library, CMS or 
frameworks depends on would have to play a failure-guaranteed game of 
whack-a-mole to get a lot of managed hosting providers to support it. 

And the larger CMS and frameworks are rightly not going to support something 
that does not get bundled into php-src.

>>> Just to reiterate, if by "built-in to PHP core", you mean "every copy of 
>>> PHP includes a functional WASM runtime", that's not going to happen. It 
>>> would mean bundling (or requiring every user to install) a huge third-party 
>>> dependency, with all of its dependencies and platform requirements, even if 
>>> they weren't interested in using it.
>> 
>> So why do you claim that bundling a third-party dependency is a "never going 
>> to happen" scenario?  
>> 
>> By that logic PHP would have none of these functionalities:
>> 
>> • cURL
>> • GD
>> • PDO
>> • OpenSSL
>> • MBString
>> • Zlib
>> • Zip
>> • XSL
>> • EXIF
>> • BCMath
> 
> None of those are "built into PHP core" in the sense of "every copy of PHP 
> includes them". Nor do any of them bundle their third-party dependencies.They 
> are all optional extensions, which the user has to provide the dependencies 
> for if they want to install and enable them.

Fine, we can treat WASM the same as all those other extensions and bundling it 
with PHP meaning `;extension=wasm` line in production.ini, the internal code 
needed to link in the library, and compiler switches to compile it in.

If PHP were to ship in this way then CMS and Frameworks could choose to add 
WASM to their list of required or recommended extensions, as it

Re: [PHP-DEV] Zephir, and other tangents

2024-09-19 Thread Mike Schinkel
> On Sep 19, 2024, at 12:00 PM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Wed, 18 Sep 2024, at 20:33, Mike Schinkel wrote:
>> Yeah. That was the original goal.
>> 
>> But to say WASM's domain is limited to browsers is not valid any longer:
>> [...]
> 
> While it's definitely interesting seeing what uses it's being put to beyond 
> the browser, the majority of those articles are talking about using WASM on 
> its own, in the kind of places where you might use a container, to host 
> things like microservices, serverless functions, etc.

Sigh. I did not include all potential examples. Leave it to you to limit your 
characterizations to only the ones I included. 

Here is another:

https://github.com/wasmerio/wasmer-php

> Embedding it into other languages is a different usage again. It's certainly 
> something that is being explored, e.g. by Extism, and that seems like a good 
> project for anyone interested here to participate in, e.g. to help design the 
> "glue" between PHP and WASM / Extism.

Moot point as it cannot be run on a managed hosted server.

https://github.com/extism/php-sdk

>> WASM's ability to run on a managed server – assuming it were built-in 
>> to PHP core
> 
> Just to reiterate, if by "built-in to PHP core", you mean "every copy of PHP 
> includes a functional WASM runtime", that's not going to happen. It would 
> mean bundling (or requiring every user to install) a huge third-party 
> dependency, with all of its dependencies and platform requirements, even if 
> they weren't interested in using it.

So why do you claim that bundling a third-party dependency is a "never going to 
happen" scenario?  

By that logic PHP would have none of these functionalities:

• cURL
• GD
• PDO
• OpenSSL
• MBString
• Zlib
• Zip
• XSL
• EXIF
• BCMath

And PHP would be much less useful without any one of them. 

> The only runtimes where WASM is ever going to be available "out of the box" 
> are those already built on a JavaScript engine (usually V8), like node.js, 
> Deno, Electron, etc. The WASM is then running inside the existing runtime, 
> not a whole new VM - like running Scala and Java code in the same JVM; or 
> Hack and PHP in (older versions of) HHVM.

Seems you do not actually understand WASM runtimes.  

While WebAssembly is available "out of the box" in JavaScript-based runtimes 
like Node.js, Deno, and Electron, it is not limited to them. Standalone 
WebAssembly runtimes like Wasmtime and WAVM allow WebAssembly to be run as a 
general-purpose compute target, outside the scope of a JavaScript engine. 

> On Sep 19, 2024, at 4:41 PM, Hammed Ajao  wrote:
> 
> Shared hosting for php gets you the worst possible version of php. Can't 
> recompile to enable any bundled extension, can't install any new extensions, 
> so how exactly would you approach this? Wasm bundled with the engine by 
> default? Or some kind of opt in mechanism that shared hosters won't even be 
> able to use?

To be clear, shared hosting and managed hosting can be VERY different animals. 

I am advocating for enterprise-level managed hosting — like Pantheon — not 
shared hosting like GoDaddy.

> On Sep 19, 2024, at 4:12 PM, Hammed Ajao  wrote:
> On Wed, Sep 18, 2024, 1:33 p.m. Mike Schinkel  wrote:
> But to say WASM's domain is limited to browsers is not valid any longer:
> 
> I don't know where you got that since I never said anything along those lines.

You did not say that explicitly, but you strongly implied it. Had you not meant 
to imply it then you'll argument would have made little sense because you would 
been implicitly admitting there are other uses for it.

> But since you have all those guides and it's so practical, what's stopping 
> you? You'd do a better job of convincing me with a MVP than some random blog 
> posts.

Here you go:

https://github.com/wasmerio/wasmer-php

BTW, as you being a C++ developer your argument is rather cynical because most 
PHP developers do not have the skills to write PHP extensions or work with FFI, 
and it is not a skill that can be acquired in a few weeks worth of free time. 
So you saying "Just do it" can be seen by a cynical person as you attempting to 
shut down discussion by presenting a blocking task that you can be pretty sure 
is too high a technical bar for most PHP developers.

I do want to gain that skill, but I doubt that I will be able to any time in 
the near future, especially not with other work commitments. 

> - https://docs.docker.com/desktop/wasm/
> 
> You mean the feature that's been in beta since 2022? Yeah that's exactly what 
> I'm referring to. If docker and all their money and engineers haven't shipped 
> wasm in 2 years, 

Re: [PHP-DEV] Zephir, and other tangents

2024-09-18 Thread Mike Schinkel
> On Sep 18, 2024, at 3:09 PM, Hammed Ajao  wrote:
> Yes and no. The primary goal of WebAssembly is to support high-performance 
> applications on web pages. The premise is simple: JavaScript is the only 
> language natively supported by browsers, but developers want to use various 
> other languages (e.g., C, C++, Rust), particularly for performance-critical 
> tasks. WebAssembly allows code written in these languages to be compiled to a 
> universal format (Wasm) that browsers can run efficiently.

Yeah. That was the original goal.

But to say WASM's domain is limited to browsers is not valid any longer:

- 
https://www.webassembly.guide/webassembly-guide/webassembly/webassembly-in-the-server
- 
https://blog.pixelfreestudio.com/how-to-implement-webassembly-in-server-side-applications/
- https://medium.com/wasm/webassembly-on-the-server-side-c584f874b4a3
- https://www.secondstate.io/articles/why-webassembly-server/
- 
https://www.techtarget.com/searchitoperations/news/252527414/Server-side-WebAssembly-prepares-for-takeoff-in-2023

And even:

- https://docs.docker.com/desktop/wasm/

> However, in the case of PHP, many of the benefits that WebAssembly brings to 
> other languages are already available through PHP extensions or FFI for 
> non-performance-sensitive tasks. Integrating a Wasm runtime into PHP would be 
> a complex undertaking with significant risks, but it wouldn't necessarily 
> provide proportionate rewards, which is the main point I'm trying to make.

Many of the benefits, but NOT the most important one for a large number of 
installations.

The benefit that neither FFI nor extensions can touch is the ability to be run 
on a managed server.  Without that, none of the other benefits of FFI nor 
extensions even matter.  Full stop.
 
> Extensions, which are already implemented in lower-level languages like C or 
> C++, would still need to be compiled to WebAssembly if the goal were full 
> compatibility. This might lead us down the path of either creating a 
> domain-specific language (DSL) for PHP—similar to AssemblyScript—or simply 
> leaving it up to the library authors to choose lower-level languages (as is 
> currently the case).
> 
> In essence, WebAssembly is great for certain scenarios, but PHP has existing 
> mechanisms that make the addition of a Wasm runtime potentially redundant for 
> most use cases. 

Partial redundancy is not redundancy. 

WASM's ability to run on a managed server – assuming it were built-in to PHP 
core — is the critical non-redundant benefit. If you cannot run those "existing 
mechanisms" then they fact they are redundant does not matter one iota.

-Mike

Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)

2024-09-17 Thread Mike Schinkel
> On Sep 17, 2024, at 8:05 PM, Jordan LeDoux  wrote:
> On Tue, Sep 17, 2024 at 3:44 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> 
> Almost everything you have said are things that I have talked about or been 
> asked about for years. That is why I have been fairly dismissive about them 
> so far, not because I disagree. I am well familiar with these discussions, 
> and I was hoping to get new feedback and thoughts through this thread. To 
> hear specifics.
> 
> The specifics I hear from you is something along the lines of "as long as you 
> give me a way to force all my code, even code other developers wrote, to 
> ignore this feature, I am fine with it". That's not really a helpful position 
> at all, even if it IS a valid one.

Since you you do not share my concerns related to your RFC I will not spend any 
more time on this topic. 

I would close with best of luck, but honestly, I hope for PHP's sake the 
results are the same as last time.

-Mike



Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)

2024-09-17 Thread Mike Schinkel
> On Sep 17, 2024, at 6:04 AM, Andreas Leathley  wrote:
> 
> On 17.09.24 11:14, Mike Schinkel wrote:
>> How would a developer know if they are using an object that has operators, 
>> unless they study all the source code or at least the docs (assuming there 
>> are good docs, which there probably are not?) 
> How is that different from using a method on an object? Operators are roughly 
> speaking a different syntax for methods, and if you use an object method, you 
> have to know about it or look up what it does.
> 
When you see a method call, you know 100% of the time that it calls a method.

Assuming operator overloading, when you see an operator used with variables, 
you will no longer be able to rely on your knowledge of how the operator work 
as it might use the built-in operator OR it might call a method. Most of the 
time it will be the former, occasionally the latter.  

And since a method would only be called occasionally I would likely get tired 
of searching to see if there is a method being called and just assume there 
isn't. Not smart, but having to track down potential methods for every operator 
use would just be far too tedious.
> Also, getting to the implementation of operators would likely be just as easy 
> as looking up methods nowadays, because IDEs would   support that kind of 
> lookup.
> 
The more generic named the method, the more IDEs struggle with finding methods, 
and operators are about as generic as you can get.
> Most framework and library code is by now type-hinted - I would have 
> understood this argument when operator overloading would be implemented into 
> PHP 5.x, where many classes and functions got values and had no enforced 
> types, so they might have expected an int, yet an object with operator 
> overloading might work but in weird ways, because there were no type hints 
> for int. I cannot see this situation now at all - if a Symfony component 
> wants an int, you cannot pass in an object. If a Symfony component wants a 
> Request object, it will not use operators that it does not expect to be 
> there, even if you would extend the class and add operator support. Using 
> operators implies you know you can use operators, otherwise it will be a 
> fatal error (except for comparisons).
> 
ANY object could have an operator overload on `==` and/or `===` and have those 
behave differently.

I also just checked and Symfony has many parameters type hinted as Stringable 
and numerous interfaces that extend Stringable.  Any object that implements 
Stringable could also add operator overloads and introduce subtle bugs into 
those functions.

Symfony has numerous interfaces that extend Countable.  Any object that 
implements Countable could also add operator overloads and introduce subtle 
bugs into those functions.

Symfony has numerous interfaces that extend ArrayAccess.  Any object that 
implements ArrayAccess could also add operator overloads and introduce subtle 
bugs into those functions.

Further — if operator overloads are added — there will likely be demand for 
more "-able" type interfaces, or some other way to make objects behave more 
like scalar types. If we have opt-in then code is safe. If we do not have 
opt-in then unintended consequences are possible, if not likely.
> From your arguments it also seems you are afraid everybody will use operator 
> overloading excessively and unnecessarily. This seems very unlikely to me - 
> it is not that useful a feature, except for certain situations.
> 
We will have to agree to disagree on that then. Look at what happened when is 
was added to C++; people when crazy with it and it was numerous years before 
the community moderated their behavior.

> Many other languages have had operator overloading for many years of even 
> decades - are there really huge problems in those languages?
> 
Depends on what you consider to be "huge" problems.  Many people feel operator 
overloading is a cure for an ailment where the medicine is the worse than the 
disease.  

Just google "operator overloading considered harmful."  But in case you can't 
be bothered to google, here are just three of many opinions:

- https://medium.com/@fmmarzoa/say-no-to-operator-overloading-7b21aa06c518 
<https://medium.com/@fmmarzoa/say-no-to-operator-overloading-7b21aa06c518>
- https://cafe.elharo.com/programming/operator-overloading-considered-harmful/ 
<https://cafe.elharo.com/programming/operator-overloading-considered-harmful/>
- 
https://www.oreilly.com/library/view/sams-teach-yourself/0672324253/0672324253_ch21lev1sec4.html
 
<https://www.oreilly.com/library/view/sams-teach-yourself/0672324253/0672324253_ch21lev1sec4.html>
 

> If yes, maybe PHP can learn from some of the problems there (which I think 
> the original RFC tried to carefully consider), but as far as I kn

Re: [PHP-DEV] Zephir, and other tangents

2024-09-17 Thread Mike Schinkel
> On Sep 17, 2024, at 8:57 AM, Adam Zielinski  
> wrote:
> 
> > To summarize, I think PHP would benefit from:
> >
> > 1. Adding WASM for simple low-level extensibility that could run on
> > shared hosts for things that are just not possible in PHP as described a
> > few paragraphs prior, and where we could enhance functionality over time,
> >
> > 2. Constantly improving PHP the language, which is what you are solely
> > advocating for over extensibility,
> Hi Mike,
> 
> I’m Adam, I'm building WordPress Playground [1] – it's WordPress running in 
> the browser via a WebAssembly PHP build [2]. I'm excited to see this 
> discussion and wanted to offer my perspective.
> 
> WebAssembly support in PHP core would be a huge security and productivity 
> improvement for the PHP and WordPress communities.
> 
> > To summarize, I think PHP would benefit from:
> >
> > 1. Adding WASM for simple low-level extensibility that could run on
> > shared hosts for things that are just not possible in PHP as described a
> > few paragraphs prior, and where we could enhance functionality over time,
> 
> Exactly this! With WASM, WordPress would get access to fast, safe, and 
> battle-tested libraries.
> 
> Today, we're recreating a lot of existing libraries just to be able to use 
> them in PHP, e.g. parsers for HTML [3], XML [4], Zip [5], MySQL [6], or an 
> HTTP client [7]. There are just no viable alternatives. Viable, as in working 
> on all webhosts, having stellar compliance with each format's specification, 
> supporting stream parsing, and having low footprint. For example, the curl 
> PHP extensions is brilliant, but it's unavailable on many webhosts.
> 
> With WebAssembly support, we could stop rewriting and start leaning on the 
> popular C, Rust, etc. libraries instead. Who knows, maybe we could even 
> polyfill the missing PHP extensions?
> 
> > 2. Constantly improving PHP the language, which is what you are solely
> > advocating for over extensibility,
> 
> Just to add to that – I think WASM support is important for PHP to stay 
> relevant. There's an exponential advantage to building a library once and 
> reusing it across the language boundaries. A lot of companies is invested in 
> PHP and that won't change in a day. However, lacking access to the WASM 
> ecosystem, I can easily imagine the ecosystem slowly gravitating towards 
> JavaScript, Python, Go, Rust, and other WASM-enabled languages.
> 
> Security-wise, WebAssembly is Sandboxed and would enable safe processing of 
> untrusted files. Vulnerabilities like Zip slip [8] wouldn't affect a 
> sandboxed filesystem. Perhaps we could even create a secure enclave for 
> running composer packages and WordPress plugins without having to fully trust 
> them.
> 
> Another use-case is code reuse between JavaScript and PHP. I'm sceptical this 
> could work with reasonable speed and resource consumption, but let's assume 
> for a moment there is a ultra low overhead JavaScript runtime in WebAssembly. 
> WordPress could have a consistent templating language. PHP backend would 
> render the website markup using the same templates and libraries as the 
> JavaScript frontend. Half the code would achieve the same task.
> 
> Also, here's a few interesting "WASM in PHP" projects I found – maybe they 
> would be helpful:
> - WebAssembly runtime built in PHP (!) https://github.com/jasperweyne/unwasm 
> 
> - WebAssembly runtime as a PHP language extension: 
> https://github.com/veewee/ext-wasm 
> - WebAssembly runtime as a PHP language extension: 
> https://github.com/extism/php-sdk 
> 
> [1] https://github.com/WordPress/wordpress-playground/ 
> 
> [2] 
> https://github.com/WordPress/wordpress-playground/tree/trunk/packages/php-wasm/compile
>  
> 
> [3] https://developer.wordpress.org/reference/classes/wp_html_processor/ 
> 
> [4] https://github.com/WordPress/wordpress-develop/pull/6713 
> 
> [5] 
> https://github.com/WordPress/blueprints-library/blob/87afea1f9a244062a14aeff3949aae054bf74b70/src/WordPress/Zip/ZipStreamReader.php
>  
> 
> [6] https://github.com/WordPress/sqlite-database-integration/pull/157 
> 
> [7] 
> https://github.com/WordPress/blueprints-library/blob/trunk/src/WordPress/AsyncHttp/Client.php
>  
> 
> [8] https://security.snyk.io/research/zip-slip-vulnerability 
> 

Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)

2024-09-17 Thread Mike Schinkel
> On Sep 17, 2024, at 1:37 AM, Jordan LeDoux  wrote:
> On Mon, Sep 16, 2024 at 9:35 PM Mike Schinkel  wrote:
> 
> Yes, if constraints of the nature I propose below are adopted.
> 
> The biggest problem I have with operator overloads is that — once added — all 
> code could potentially be "infected" with operator overloads. However, if the 
> developer *using* an operator overload could instead opt-in to using them, in 
> context, then I would flip my opinion and I would begin to support them.  
> 
> What might opt-in look like?  I propose two (2) mechanisms of which each 
> would be useful for different use-cases. As such I do not see these two as 
> competing but instead would expect adding both to be preferable:
> 
> 1. Add a pair of sigils to enclose any expression that would need to support 
> userland operator overloading. This would allow a developer to isolate just 
> the expression that needs to use operator overloading. I propose {[...]} for 
> this, but feel free to bikeshed sigils. Using an example from the RFC, here 
> is what code might look like:
> 
> $cnum1 = new ComplexNumber(1, 2);
> $cnum2 = new ComplexNumber(3, 4);
> $cnum3 = {[ $cnum1 * $cnum2 ]};   // Uses operator operloading 
> sigils
> echo $cnum3->realPart.' + '.$cnum3->imaginaryPart.'i';
> 
> 2. For when using `{[...]}` would be annoying because it would be needed in 
> so many places, PHP could also add support for an attribute. e.g. 
> `#[OperatorOverloads(Userland:true)]`. This attribute would apply to 
> functions, methods, classes, enums, (other?) and indicates that operator 
> overloads can be present anywhere in the body of the decorated structure. I 
> included `Userland:true` as an indicator to a reader that this only applies 
> to userland operator overloads and that built-in ones like in GMP and 
> anywhere else would not need to be opted into, but that parameter could of 
> course be dropped if others feel it is not needed. Again, feel free to 
> bikeshed attribute name and/or parameters.
> 
> #[OperatorOverloads(Userland:true)]
> function SprintProductOfTwoComplex(ComplexNumber $cnum1, ComplexNumber 
> $cnum2)string {
>   $cnum3 = $cnum1 * $cnum2;
>   return sprintf("%d + %di", $cnum3->realPart, $cnum3->imaginaryPart);
> }
> 
> If this approach were included in the RFC then it would also ensure there is 
> no possibility of BC breakage. BC breakage which would certainly be an edge 
> case but I can envision it would be possible,e specially where newer 
> instances incorporating operator overloads are passed to functions that did 
> not have parameters type hinted but were not intend to be used with operator 
> overloads resulting in subtle potential breakage. 
> 
> This argument is also consistent with the argument people had about not 
> allowing default values to be generically used in calls to the function 
> function. Their claim was that developers who did not write their code with 
> the intention of exposing defaults should not have their defaults exposed. 
> Similarly developers that do not write their code to enable operator 
> overloads should not be used with  userland operator overloads unless they 
> explicitly allow it, especially as they may not have have tested code with 
> operator overloads.
> 
> Anyway, that is my two cents worth. 
> 
> TL;DR?  I argue that PHP should operator overloads but ONLY if there is a 
> mechanism that requires the user of expressions that call overloaded 
> operators to explicitly opt-in to their use.
> 
> -Mike
> 
> 
> This is interesting, as I've never seen this in any language I researched as 
> part of operator overloading, and also was never given this feedback or 
> anything similar by anyone who provided feedback before.

If all language features required prior art, there would never be innovation in 
programming languages. So for anything that currently exists, there was always 
a first language that implemented it. 

Of course when there is prior art we can use the heuristic of "All these have 
done it before so it must be a good idea."  But lack of prior art should not be 
the reason to dismiss something, it should be evaluated on its merits.

> My initial reaction is that I do not understand how this is any better than 
> parameter typing. If you do not allow any objects into the scope you are 
> using operators, wouldn't that be the same as the kind of userland control 
> you are after? Or rather, how would it be substantially worse?

How would a developer know if they are using an object that has operators, 
unless they study all the source code or at least the docs (assuming there are 
good docs, which there probably are not?) 

It might be illustr

Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again)

2024-09-16 Thread Mike Schinkel


> On Sep 14, 2024, at 5:48 PM, Jordan LeDoux  wrote:
> 
> Hello internals,
> 
> This discussion will use my previous RFC as the starting point for 
> conversation: https://wiki.php.net/rfc/user_defined_operator_overloads
> 
> There has been discussion on list recently about revisiting the topic of 
> operator overloads after the previous effort which I proposed was declined. 
> There are a variety of reasons, I think, this is being discussed, both on 
> list and off list.
> 
> 1. As time has gone on, more people have come forward with use cases. Often 
> they are use cases that have been mentioned before, but it has become more 
> clear that these use cases are more common than was suggested previously.
> 2. Several voters, contributors, and participants have had more time (years 
> now) to investigate and research some of the related issues, which naturally 
> leads to changes in opinion or perspective.
> 3. PHP has considered and been receptive toward several RFCs since my 
> original proposal which update the style of PHP in ways which are congruent 
> with the KIND of language that has operator overloads.
> 
> I mentioned recently that I would not participate in another operator 
> overload RFC unless I felt that the views of internals had become more 
> receptive to the topic, and after some discussion with several people 
> off-list, I feel that it is at least worth discussing for the next version.
> 
> Operator overloads has come up as a missing feature in several discussions on 
> list since the previous proposal was declined. This includes:
> 
> [RFC] [Discussion] Support object type in BCMath [1]
> Native decimal scalar support and object types in BcMath [2]
> Custom object equality [3]
> pipes, scalar objects and on? [4]
> [RFC][Discussion] Object can be declared falsifiable [5]
> 
> The request to support comparison operators (>, >=, ==, !=, <=, <, <=>) has 
> come up more frequently, but particularly in discussion around linear 
> algebra, arbitrary precision mathematics, and dimensional numbers (such as 
> currency or time), the rest of the operators have also come up.
> 
> Typically, these use cases are themselves very niche, but the capabilities 
> operator overloads enable would be much more widely used. From discussion on 
> list, it seems likely that very few libraries would need to implement 
> operator overloads, but the libraries that do would be well used and thus 
> MANY devs would be consumers of operator overloads.
> 
> I want to discuss what changes to the previous proposal people would be 
> seeking, and why. The most contentious design choice of the previous proposal 
> was undoubtedly the `operator` keyword and the decision to make operator 
> overload implementations distinct from normal magic methods. For some of the 
> voters who voted yes on the previous RFC, this was a "killer feature" of the 
> proposal, while for some of the voters who voted no it was the primary reason 
> they were against the feature.
> 
> There are also several technical and tangentially related items that are 
> being worked on that would be necessary for operator overloads (and were 
> originally included in my implementation of the previous RFC). This includes:
> 
> 1. Adding a new opcode for LARGER and LARGER_OR_EQUAL so that operand 
> position can be preserved during ALL comparisons.
> 2. Updating ZEND_UNCOMPARABLE such that it has a value other than -1, 0, or 1 
> which are typically reserved during an ordering comparison.
> 3. Allowing values to be equatable without also being orderable (such as with 
> matrices, or complex numbers).
> 
> These changes could and should be provided independent of operator overloads. 
> Gina has been working on a separate RFC which would cover all three of these 
> issues. You can view the work-in-progress on that RFC here: 
> https://github.com/Girgias/php-rfcs/blob/master/comparison-equality-semantics.md
> 
> I hope to start off this discussion productively and work towards improving 
> the previous proposal into something that voters are willing to pass. To do 
> that, I think these are the things that need to be discussed in this thread:

Anyone who just happened to see my prior messages on the topic know that I have 
strongly advocated against operator overloads.

Rather than repeat my full arguments on the list, I will instead summarize by 
linking to three (3) of the comments from Jordan's Reddit poll, two of them 
mine.  If you *only* read one of them, read the *last* one:

- https://www.reddit.com/r/PHP/comments/rv11fc/comment/hr2ujix/ 

- https://www.reddit.com/r/PHP/comments/rv11fc/comment/lnha4gq/ 

- https://www.reddit.com/r/PHP/comments/rv11fc/comment/lnhcbqr/ 


Basically my concerns are that operator overloading has benefits for a subset 
of developers that 

Re: [PHP-DEV] Zephir, and other tangents

2024-09-11 Thread Mike Schinkel
> On Sep 11, 2024, at 4:43 PM, Hammed Ajao  wrote:
> 
> Using WebAssembly (Wasm) for PHP doesn't make much sense. PHP already runs on 
> its own virtual machine server-side, so adding another VM (Wasm) would just 
> introduce unnecessary complexity and overhead. 

Sorry, but I am going to have to call your assertions ill-informed, at best.  
Having one VM does not invalidate the value of a different VM with very 
different strengths. 

If using two VMs really made no sense there would not be so many people running 
a Lua VM in Java.

> Additionally, would this be the LLVM or Cranelift variant of Wasm?

TBD


> For extensions, Wasm would perform even worse than current implementations, 
> no matter how it's integrated. Presently, I define zif_handler function 
> pointers that operate on the current execution frame and return value, 
> triggered when the engine detects an internal function (fbc). This approach 
> is as direct as it gets.

It is not the performance of integration point but what can be done within 
WASM, and that would be able to be done on managed hosts if incorporated into 
PHP core.  

As for use of extensions that are not part of core on a managed host, some of 
us in the USA have a saying that relates: 

 "Besides that Mrs. Lincoln, how was the play?"  

> Suggesting AssemblyScript, especially in this context, seems illogical. Have 
> you actually worked with WebAssembly and considered performance implications, 
> or is this based on theoretical knowledge?

Admittedly theoretical.  

Are your objections based on actually working with it, or theoretical too?

> Your point about operator overloading doesn't seem valid either.

One cannot validly claim validity or lack of validity of an _opinion_.  

You can disagree or agree — as that is how one engages with opinion — but an 
opinion does not beg a proof.

> Consider the following:
> 
> ```php
> class X {
> public function plus(X $that) {}
> public function equals(X $that) {}
> }
> ```
> 
> In this case, `plus` could represent any behavior, as could `equals`. If I 
> wanted to, I could implement `plus` to perform what `equals` does and vice 
> versa. Should we consider methods broken just because their names can be 
> arbitrary?

You are comparing apples and oranges.  

There are very few standardized method names and the number of potential method 
names is combinatorially large. There are a very few number of operators and 
each has a well-known meaning with numbers or in boolean expressions, which 
means that if you use one you have reduced by one the scarce resource of 
operators, assuming they are used in a manner were 99 out of 100 developers 
would choose to overload them in the same way (vs. say 60 out of 100.)

But this is just one concern. Read on for other concerns.

> PHP already distinguishes between comparison operators for objects:

It seems them operator overloading is not needed so much then, right?

> `===` compares object IDs, while `==` compares their properties. Beyond this, 
> there's little reason to apply an operator to an object directly. Why would 
> you need to call `$user1 + $user2` or similar operations on an object? 

Why would you add $money1 + $money2, or more likely $subtotal *(1+ $tax) + 
$shipping?  Because it make sense.  

And my opinion is that is makes sense if done in core, but not if done in 
userland.  Again, my *opinion*.

> What scenario would break by allowing operator overloads?

The scenario of reading code and being confused if looking at scalars or 
objects, and if objects then being able to find the implementation. The more 
unique a method is named, the faster it is to find in a codebase, even with a 
really smart IDE like PhpStorm. Now imagine having to search for the 
implementation of `+`, and not even knowing if there is such an override for 
code that is not type-hinted.

Basically operator overloading is one of the subsets of features for writing 
DSLs and having watched everyone in the Ruby community write their own DSLs in 
their projects they ended up with as many different languages as they had 
programming teams, and 99% of those languages were incomplete and poorly 
designed.  

There is something freeing about constraints and it is just my opinion that PHP 
having the constraints that you cannot really write  DSLs mean that people end 
up more often getting work done rather than writing their own custom DSL.And 
operator overloads are in this category for me.

BTW, the first time I realized this was in the early 90's when I compared 
Clipper to FoxPro.  Clipper was so much more powerful than FoxPro as a 
language. I taught Clipper professionally and I wrote a book on it.  But after 
the end of that phase of my life I looked back on Clipper vs. FoxPro and 
realized that Clipper developers spent lots of time trying to create their 
perfect DSL — myself included — but because you couldn't do that in FoxPro 
people just really got a lot of shit done with FoxPro.

> However,

Re: [PHP-DEV] Zephir, and other tangents

2024-09-11 Thread Mike Schinkel
> On Sep 11, 2024, at 4:55 PM, Rowan Tommins [IMSoP]  
> wrote:
> On 11 September 2024 20:12:53 BST, Mike Schinkel  wrote:
>>> It also risks conflicting with a future language feature that overlaps, as 
>>> happened with all native functions marked as accepting string automatically 
>>> coercing nulls, but all userland ones rejecting it. Deprecating that 
>>> difference has caused a lot of friction.
>> 
>> That is a little different in that it was a behavior that occurred in both 
>> core and userland whereas only allowing operator overloading in core would 
>> mean there would be not userland differences that could conflict.
> 
> Historically, that's what we had for scalar parameters. All the way back in 
> PHP 4 (I think), the engine had a function called "zend_parse_parameters" 
> (ZPP), which took the PHP values a user provided, and either converted them 
> to the desired C type, or rejected them. In effect, it allowed functions 
> defined in extensions to declare scalar typed parameters.
> 
> Then in PHP 7, we added scalar type declarations for parameters in userland 
> functions, and had to work out how they fitted with those internal functions. 
> Part of the motivation for the strict_types toggle was to manage their 
> behaviour; and userland functions require explicit nullable types, whereas 
> ZPP historically coerced nulls regardless.
> 
> Anything we let extensions do could end up with the same dilemma later: do we 
> match userland to existing extension behaviour, change extension behaviour, 
> or live with an awkward inconsistency?

There are several levels of hypotheticals in your stated concern, so yes, if we 
make all regrettable decisions then we possibly have a problem.  But if we 
allow several levels of hypotheticals to be criteria for every decision we make 
then we can probably find an argument against any improvement.  

That said, not doing this seems to matter more to you than doing it matters to 
me, so I relent.

>> WebAssembly has a deny-by-default design so could be something to seriously 
>> consider for extensibility in PHP. Implementations start with a full 
>> sandbox[2] and only add what they need to avoid those kinds of concerns. 
> 
> The problem is that second part: in order to be useful for writing a PHP 
> extension, what would we need to let through the sandbox?

Initially, only scalar parameters and scalar return values. (Stop and 
contemplate this for a moment, please.)

Then we can consider "letting through" more in future RFCs as we all learn more 
about using WASM and so that each thing we add can be well considered.

>> I think that actually supports what I was saying; people would gravitate to 
>> only doing in an extension what they cannot do in PHP itself, and over time 
>> if PHP itself improves there is reason to migrate more code to PHP.  
>> 
>> But there can still be reasons to not allow some thing in userland. Some 
>> things like __toArray.
> 
> I think there's ideas pulling in opposite directions here: on the one hand, 
> using the difficulty of building extensions as a deliberate "speed bump" to 
> avoid people using features "badly"; but on the other hand, wanting to reduce 
> the difficulty of building extensions.

That is one way to look at it, but not the only way and not the way I was 
looking at it.

Let's say the effort to write something in PHP is 1 and the effort to write in 
C is 100 using arbitrary units where 100 means almost nobody ever does it. My 
argument considers 100 being too high a bar, but maybe 50 or 25 is low enough 
so as to not open the floodgates but still make it easy enough that people 
actually do it occasionally as clearly even 25 is many times harder than 1.

And no need to bikeshed those numbers. I was using arbitrary numbers to try and 
illustrate a concept, nothing more.

BTW, I was not looking at it as a "speed bump," I was looking at it as the fact 
that features in core are written in C, not PHP.

> I think the latter is a more noble goal, and one way to help is to make it 
> less *necessary* to build extensions, by adding to the core language the 
> things you currently need extensions to do. Things like efficient string 
> buffers and binary stream manipulation, or attributes and magic methods to 
> override object behaviour.

That is one way to consider it, and one I would definitely like to see. 

But I still do not think you can optimize out all need for low level languages 
by adding userland features.  

For example, how do we add a feature that allows for efficient looping? 
Certainly we can optimize the loops themselves; we already have with functions 
like `array_map()`, but there would still be need to context switch between C

Re: [PHP-DEV] Zephir, and other tangents

2024-09-11 Thread Mike Schinkel
Hi Rowan,

> On Sep 11, 2024, at 2:55 AM, Rowan Tommins [IMSoP]  
> wrote:
> Perhaps you're unaware that classes in core already can, and do, provide 
> operator overloading. GMP is the "poster child" for it, overloading a bunch 
> of mathematical operators, but the mechanism it uses to do so is reasonably 
> straightforward and available to any extension.

I was making an (evidently) uninformed assuming that it was non-trivial to add 
operator overloading at the C level. If it is easy, then my comments were moot. 
 

That said, writing extensions in C and deploying them is non-trivial —comparing 
to writing code in PHP— so there is that. ¯\_(ツ)_/¯

> I've never liked that approach, because it means users can't write polyfills, 
> or even stub objects, that have these special behaviours. It feels weird for 
> the language to define behaviour that isn't expressible in the language. 

Understood. In _general_ I don't like it either, but I will use as an analogy a 
prior discussion regarding __toArray, and I quote[1]:

"For the "convertible to array" case, I think __toArray, or an interface 
specifying just that one method, would make more sense than combining it with 
the existing interfaces. I'm sceptical of that concept, though, because most 
objects could be converted to many different arrays in different circumstances, 
each of which should be given a different and descriptive name."

I am of course quoting you.   

Similarly, operators could mean different things, e.g. it is possible to have 
different meaning of equal, and even different meanings of plus. Or worse be 
applied in ways that are non-sensical to anybody but the developer who 
implements them (that would be the same kind of developer who names their 
variables after Game of Thrones characters.)  

That is why I am not a fan of operator overloading, just as you were not a fan 
of __toArray which to me is less problematic than overloaded operators because 
it has such smaller scope and is actually quote useful for a common set of 
use-cases regardless of the potential for confusion. But I digress.

> It also risks conflicting with a future language feature that overlaps, as 
> happened with all native functions marked as accepting string automatically 
> coercing nulls, but all userland ones rejecting it. Deprecating that 
> difference has caused a lot of friction.

That is a little different in that it was a behavior that occurred in both core 
and userland whereas only allowing operator overloading in core would mean 
there would be not userland differences that could conflict.

Whatever the case, if there are only two options: 1.) no operator overloading, 
and 2.) userland operator overloading I would far prefer the former.

> This is the tricky part for me: some of the things people want to do in 
> extensions are explicitly the kinds of thing a shared host would not want 
> them to, such as interface to system libraries, perform manual memory 
> management, interact with other processes on the host.
> 
> If WASM can provide some kind of sandbox, while still allowing a good portion 
> of the features people actually want to write in extensions, I can imagine 
> that being useful. But how exactly that would work I have no idea, so can't 
> really comment further.

WebAssembly has a deny-by-default design so could be something to seriously 
consider for extensibility in PHP. Implementations start with a full sandbox[2] 
and only add what they need to avoid those kinds of concerns. 

Also, all memory manipulations sandboxed, though there are still potential 
vulnerabilities within the sandbox so the project that incorporates WASM needs 
to be careful.  WASM written in C/C++ can have memory issues just like in 
regular C/C++, for example.  One option would be to allow only AssemblyScript 
source for WASM. Another would be a config option that a web-host could set to 
only allow signed modules, but that admittedly would open another can of worms. 
 But the memory issues cannot leak out of the module or affect other modules 
nor the system, if implemented with total memory constraints.

That said, web hosts can't stop PHP developers from creating infinite loops so 
the memory issues with WASM don't feel like too much bigger of a concern given 
their sandboxed nature.  I've copied numerous other links for reference: 
[4][5][6]


>>> The overall trend is to have only what's absolutely necessary in an 
>>> extension.
>> 
>> Not sure what you mean here.
> 
> I mean, like Phalcon plans to, ship both a binary extension and a PHP 
> library, putting only certain essential functionality in the extension. It's 
> how MongoDB ships their PHP bindings, for instance - the extension provides 
> low-level protocol support which is not intended for every day use; the 
> library is then free to evolve the user-facing parts more freely.

Gotcha.  

I think that actually supports what I was saying; people would gravitate to 
only doing in an extension what they 

[PHP-DEV] Zephir, and other tangents

2024-09-10 Thread Mike Schinkel
Hi Rowan,

This message is in reply to https://externals.io/message/125455#125496 from the 
thread "bikeshed: Typed Aliases"

> On Sep 10, 2024, at 5:35 PM, Rowan Tommins [IMSoP]  
> wrote:
> On 10 September 2024 19:32:19 BST, Mike Schinkel  wrote:
>> BTW, why has nobody ever mentioned Zephir on this list (that I am aware of?)
> 
> Zephir is an interesting idea that has never quite fulfilled its aims. The 
> Phalcon developers hoped that creating a more PHP-like language would allow 
> more people to work on extensions such as their framework, but it doesn't 
> seem to have worked out that way. 
> 
> The worse problem was that Zephir itself had very few contributors. A few 
> years ago, the project came close to shutting down as there was nobody left 
> to maintain it; Phalcon was to be rewritten in PHP. 
> <https://blog.phalcon.io/post/the-future-of-phalcon> Since then, somebody has 
> stepped up, but Phalcon work is still focussed on the PHP rewrite, with the 
> intention of a smaller, optional, extension providing performance-critical 
> components. <https://blog.phalcon.io/post/phalcon-roadmap>

Thank you for the details about Zephir, as I was not fully aware of its 
history.  

On the surface it looks like a really promising project, it is a shame that 
more people are not interested in seeing it be successful so that it could be 
maintained and improved.

BTW, my rhetorical comment asking why nobody mentions it on the list was really 
an indirect reference to the "Using and Mentioning Third-party Packages" 
thread[1] I have wanted to comment on but have not had the time to read the 
full thread and craft an argument that I hope would be compelling to many 
people.

> Meanwhile, PHP 7 and 8 have massively increased both the performance and the 
> capability of code written in PHP, and even FFI to bridge to existing native 
> binaries (although I gather there's a lot that could be improved to make that 
> more useful).
> 
> ...except to say that I think we should be aiming to reduce the difference 
> between what can be done in extensions and what in PHP code, rather than 
> planning any new such differences.

True, but let us split this into two discussions. One discussion you made here 
which is "make PHP better rather than make ways to extend PHP externally." 

The 2nd is the discussion I was having which was more constrained, i.e. "In the 
case of operator overloading that I argue we should not offer in userland I was 
exploring the idea of adding internal features that allow extensions to be 
developed to address those use-cases, and especially for extensions that would 
be included in core, not necessarily for optional extensions."  

Before we address the broad question let us address the narrow one I was 
focused on. 

First, do you think we should add general operator overloading as in C++, 
Python, C#, Swift, Ruby, Kotlin and Dart, or do you agree that adding it would 
be opening Pandora's box?  If you think we should add operator overloading then 
we can agree to disagree.

If you agree we should not add then do you agree that we could add operator 
overloading for specific classes in core, such as if we added a Money or 
Currency class? Ignore whether you think we should add a Money or Currency 
class — assume we should — and just answer if you think we should allow 
operator overloading for classes added to core where we can standardize the 
operator's meanings across all uses of PHP?

If you've gotten this far and we are still in agreement then I was looking for 
a way to make it easier to add operator overloading for classes to be added to 
core. So your comment "to reduce the difference between what can be done in 
extensions and what in PHP code, rather than planning any new such differences" 
was really presenting my argument as apples when I was instead discussing 
oranges. Though I can certainly understand if that was not previously clear to 
you, hopefully it is now.

(Alternately, for operator overloading, do you see any way in which we could 
constrain userland operator overloads such that we would not end up many 
different competing meanings of plus, minus, times, divide, equals, not equals, 
etc. for similar types of classes? I certainly cannot envision how we could 
constrain it in a useful way.)

---

With that covered I'll respond to your more general argument which I 
characterized as you advocating to  "Make PHP better rather than make ways to 
extend PHP externally." 

Generally, I agree. Where it is possible — and not harmful — to do so, it would 
be better to make PHP better than to just find ways to extend PHP in other 
ways.  

But let us be realistic and honest with each other. PHP has many strengths but 
it also has weaknesses that it will never be able to address without 

Re: [PHP-DEV] bikeshed: Typed Aliases

2024-09-10 Thread Mike Schinkel
> On Sep 10, 2024, at 5:35 PM, Rowan Tommins [IMSoP]  
> wrote:
> All of which is drifting a long way off topic, 

Yes, very true. 

I will start another thread with the title "Zephir and other tangents" to reply 
to your comments so as not to hijack this thread on those tangents, and so 
others can ignore it unless they really want to follow it.

-Mike


Re: [PHP-DEV] bikeshed: Typed Aliases

2024-09-10 Thread Mike Schinkel
Hi Rob,

> On Sep 10, 2024, at 4:31 AM, Rob Landers  wrote:
> This is very similar (behaviorally) to what I wanted to do with GMP. 
> Overloading GMP would have given you int-like powers in your type. The 
> biggest negative feedback I got was that people would abuse it still; so we 
> need some way to prevent abuse. If you read Jordon's operator overloads RFC, 
> and my GMP overloading RFC, you can see that users basically need a way to 
> define how to operate over even just an integer.
> 
> For example, Dollar(1) + Euro(3) is what? Or even Dollar(1) + 1? How does a 
> developer prevent someone from doing something nonsensical? The language 
> needs to enforce some rules and/or the developer needs to be able to define 
> them. These rules need to be intuitive and well reasoned, IMHO.

My arguments were that the use-cases where it is clear and objective what each 
operator would mean are few and far between[caveat, see below] and so rather 
than provide general operator overloading PHP should build those use-cases into 
a core extension. 

For example, to add Dollar + Euro, having a Money or Currency extension as part 
of PHP core would make huge sense to me, but not giving everyone the ability to 
overload operators for every type.

I did not follow the GMP discussions as I have never needed to use that 
extension in any of my own PHP development so I am not familiar with the 
arguments made and may be mischaracterizing your proposal; correct me if I do. 

BTW, where is your GMP RFC? I searched for it but could not find it.  Did you 
propose operator overloading for GMP in core, or in userland?

> For example, Dollar(1) + Euro(3) is what? Or even Dollar(1) + 1? How does a 
> developer prevent someone from doing something nonsensical? 

If the rules are built into core, then the compiler and/or runtime stops them 
from doing something nonsensical, right?

> The language needs to enforce some rules and/or the developer needs to be 
> able to define them. 

My argument is that the language should enforce those rules as allowing the 
userland developer to overload operators will result in every developer 
defining different rules for their own classes, leading to a tower of babble. 
And the chances that many developers will do things nonsensical with their 
operators approaches 100%. 

I do acknowledge not everyone agrees with me on this, and if so that is their 
right. If enough people disagree with me then PHP may eventually have general 
operator overloading. My hope is that there are not enough people who disagree.

> These rules need to be intuitive and well reasoned, IMHO."  


I hope anything that passes an RFC is intuitive and well reasoned because 
otherwise our governance model is flawed and maybe we need to address that 
first, if so?

-Mike

[caveat] — I am aware there are likely numerous use-cases in financial, 
scientific and/or related fields that could benefit from operator overloading 
but that would likely never be mainstream enough to make it into PHP core. For 
this I think making it easier to implement operator overloading in an extension 
would be a reasonable solution (if that is possible.) Yes, it would require 
people learn to develop extensions, but working groups for those use-cases 
could form, and if it could be done in a way that supports Zephir, then writing 
an extension should not be too hard. https://zephir-lang.com 


That, or come up with some way to limit operator overloading to only those 
things where overloads are objectively obvious, but I really have no idea what 
kind of limits could do that and I doubt it is even possible.

And if none of those things then those communities can get by with what they 
have always been able to do; use methods and parameters.  One thing is clear to 
me, PHP is never going to overtake Python (or Julia, et. al.) in those 
communities, so why appeal to a base that is not really interested except on 
the periphery? OTOH, Python is not likely to overtake PHP for general web 
development no matter how "popular" it becomes.

BTW, why has nobody ever mentioned Zephir on this list (that I am aware of?)

Re: [PHP-DEV] bikeshed: Typed Aliases

2024-09-10 Thread Mike Schinkel
> On Sep 9, 2024, at 5:35 PM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On 09/09/2024 19:41, Mike Schinkel wrote:
>> 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: .;
> I think this would stray into some of the same complexity as operator 
> overloads on objects, in terms of the types and values allowed. For instance:
> 
I tend to agree that allowing operations may be too much for an initial scope 
given that it is unlike anything else in the current language and with no other 
languages offering an equivalent AFAIK.

I would however make the distinction that it is unlike operator overloading 
because the big concern was what constituted an operation for any given type 
could be too subjective.  In your example of `Metres` it is pretty obvious, but 
not at all obvious for a `User`, for example.  (BTW, thank you for not calling 
out my nonsensical example of operations on a `UserId`; when I wrote that I 
clear was not thinking about if they were relevant, doh!)

However give the suggestion regarding operations with a typedef, the only 
operations that I suggested would be valid would be the ones already defined on 
the underlying type, (when I mentioned other operations I was thinking of 
methods — see my the following example with round — not operators so that is 
not the same as operator overload.) For example:

/**
 * Currency is an int so for example in USD 1 
 * unit of currency not a dollar but a cent.
 */
typedef Currency: int operations: +,-,*,/,round;
function CalcTotal(Currency $subTotal, Currency $shipping, float $tax):Currency 
{
   return round($subTotal*(1+$tax/100),0) + $shipping;
}
> typedef Metres: int;
> 
> assert( Metres(2) +  Metres(1) === Metres(3) ); // most obvious
> assert( Metres(2) + 1 === Metres(3) ); // seems pretty clear

Both of those are in line with what I was suggesting.
> $_GET['input'] = '1';
> assert( Metres(2) + $_GET['input'] === Metres(3) ); // might be more 
> controversial
> 
I would not consider this appropriate as it has two levels of conversion and 
could thus end up with unintended edge cases. To do the above I think you would 
have to either convert or typecast:

assert( Metres(2) + intval($_GET['input']) === Metres(3) ); 
assert( Metres(2) + (int)$_GET['input'] === Metres(3) ); 
> typedef Feet: int;
> assert( Metres(2) + Feet(1) === Metres(3) ); // almost certainly a bad idea
> 
This would be operator overloading where knowledge of the conversion between 
meters and feet would be required, and that is not in any way in scope with 
what I was suggesting.  

As an aside, I am against userland operator overloading as I have seen in other 
languages that operator overloading gets abused and results in code that is a 
nightmare to maintain. OTOH, I would support operator overloading in specific 
cases, e.g. a `Measurement` class in PHP core could allow adding meters to 
feet, assuming such a proposal were made and all other aspects of the RFC were 
of the nature to be voted in.

To reiterate on typedefs, what I was suggesting was that if an operation was 
explicitly allowed — e.g. + — then anything that would work with the underlying 
type — such as adding an int 1 would work without typecasting and yet still 
result in the typedef type, e.g. Meters(2) + 1 results in a value of type 
Meters. (note that I corrected your spelling of 'Meters' here. ;-) 

But I agree, this is probably a bridge too far for a first RFC for typedefs. 

>> type MyNewType: Foo
>> type MyAlias = Foo
> I know this was only an example, but as a general point, I think we should 
> avoid concise but cryptic differences like this. PHP is generally 
> keyword-heavy, rather than punctuation-heavy, and I think that's a valid 
> style which we should keep to.
Here, I also tend to agree WRT PHP.  Was just pointing out for sake of laying 
out other options that were implied not to exist.

-Mike



Re: [PHP-DEV] bikeshed: Typed Aliases

2024-09-09 Thread Mike Schinkel
> On Sep 7, 2024, at 4:36 PM, Larry Garfield  wrote:
> 
> 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

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.  

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: .;

Or less cryptic:

typedef UserId: int operations: add, subtract, multiply, divide;
typedef UserName: string operations: concat;

Going with the named operations would allow other operations to be opt-in in 
the future, but would call into question defining operations as a first-class 
language element.

> readonly class UserId {
>  public function __construct(public int $value) {}
> }
> 
> I could see an argument for either.  

Typedefs enable a developer to write more robust code that they currently 
cannot do, whereas typealiases are really just syntax sugar, albeit sugar that 
probably tastes really good.

Said more explicitly, I would prefer both but if it is has to be only one to 
start, I would prefer starting with typedefs.

> 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. :-)

Given that a typedef can always just reference the original type(s) rather than 
basing a typedef on another typedef I would err on the conservative side and 
say initially no typedef of a typedef. 

The current downside would be that a complex union typedef defined in one 
namespace could not easily be referred to in another namespace without 
repeating the union typedef.  Whether that would become a frequent problem 
remains to be seen so it could wait for a future RFC if so.

Another limit would to the workaround would be if a typedef is defined as 
private for a namespace. This as namespace-private is not currently possible we 
could cross that typedef-on-a-typedef bridge on a future day if 
namespace-private ever becomes possible. #jmtcw


> 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`.)

Another option is to use a different syntax:

type MyNewType: Foo
type MyAlias = Foo

Not arguing for or against any specific syntax, just pointing out that there 
are other potential options.

-Mike

Re: [PHP-DEV] bikeshed: Typed Aliases

2024-09-07 Thread Mike Schinkel
> On Sep 7, 2024, at 9:28 AM, Rob Landers  wrote:
> Keep in mind there is already single-class aliasing with well-known behavior 
> for both local and project-wide aliases. Local aliases are done through 'use' 
> statements, and project-wide aliases can be created by using the 
> `class_alias()` function.

Good point. 

While I'd prefer to be able to use a typedef/typealias syntax, I certainly 
would not bikeshed over it.

> On Sep 7, 2024, at 9:21 AM, Larry Garfield  wrote:
>> 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 {}

Gotcha.  That issue had not occurred to me as my use of type aliases is in 
other languages that do not have union types. So I was more concerned with this:

namespace A\Really\Long\Namespace {
   class A {}
}
namespace My\Current\Namespace {
   typedef A: \A\Really\Long\Namespace\A {}

   class B extends A {}
}

However, as Rob pointed out there are already ways to accomplish this that I 
was not thinking of, so my concern for extends and implements is effectively 
moot.

> On Sep 7, 2024, at 9:28 AM, Larry Garfield  wrote:
> 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.

That latter sentence is spot-on.

-Mike

Re: [PHP-DEV] bikeshed: Typed Aliases

2024-09-07 Thread Mike Schinkel
> 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.

> On Sep 6, 2024, at 8:46 PM, Davey Shafik  wrote:
> 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?).

Allowing methods also have definite value as most use-cases I have seen in 
other languages alias in order to add methods, especially for enabling support 
of interfaces.

Which, however, brings up an important distinction that other languages have 
made and which I think PHP would benefit from addressing:

1. Type Alias => Different Name for Same Type
2. Type Def => New Type which has all the same properties and methods of other 
type

e.g. (being hypothetical with the syntax; bikeshed away):

typealias  LocalWidget: Widget

typedef  MyWidget: Widget {
   function foo() {...}
}

function doSomething(Widget $widget) {...}

$w = new LocalWidget;
doSomething($w);   // This works, no problem as LocalWidget === Widget

$w = new MyWidget;
doSomething($w);   // This throws an error as MyWidget !== Widget

-Mike


Re: [PHP-DEV] Local constants

2024-09-06 Thread Mike Schinkel
> On Sep 6, 2024, at 4:47 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Fri, 6 Sep 2024, at 03:01, Mike Schinkel wrote:
>>> Block-scoping doesn't have to allow shadowing of names, 
>> 
>> How exactly would that work?  Are you suggesting to restrict the use of 
>> variable names to one per function but still allow for block scoping?
> 
> Yes. That's how C# works, for example - variables are scoped to the block 
> where they're declared, but each name declared must be unique, not shadowing 
> one that's currently in scope.

Interesting. That seems... an odd choice, just to enable block scoping.  

BTW, I find block scoping has more pain than pleasure, even when it is not 
exactly causing bugs, e.g.:

if (is_null($widget = getWidget())) {
   return;
}
echo $widget->name;  //  block-scoped $widget not available

The above would actually be a runtime bug in PHP, if the code were not covered 
by testing beforehand. In a statically-typed pre-compiled language like Go, it 
is just an annoyance.

OTOH, I very rarely ever find a situation where I am actually happy to have 
block scoping. IOW, I don't know what it enables that make people want it so 
badly, except possibly conflating closures with scoped-blocks, or ability to 
further control scoping in (too) long functions.

I think features that would reward people for writing shorter functions would 
be much better, but maybe that is just me.


>> Shadowing is not a feature that is added, it is the result 
>> of block scoping, AFAIK.
> 
> Shadowing is absolutely a feature that has to be implemented: the compiler 
> has to store some "backup" of the old name binding, so that it can be 
> "restored" when the shadowing variable goes out of scope. Without shadowing, 
> it's instead about tracking the "lifetime" of the variable, and refusing 
> references to it outside of the block where it's "live". I'm sure the 
> implementation of both versions varies wildly.

Meh, you can twist words to mean that, but your words ignore that all variable 
scoping is then explicitly implemented as feature. 

What I meant was the language already implements variable scoping so there is 
no additional work needed beyond what they language already implements. Unless 
the language was weirdly designed in such a way that it cannot reuse existing 
scoping mechanisms, which I will admit may actually be true of PHP.

OTOH, I am not speaking of what you just revealed about C# which I find to be 
also be, weird. 

> You're right, there is some value in letting people know that a feature would 
> be popular if implemented. I'm just aware that threads like this can quickly 
> grow into rambling discussions of wild ideas with little grounding in what's 
> possible, or back-and-forth debates between two people about something 
> completely hypothetical. When that happens, those with the experience to 
> actually implement big new features tend to tune out. 

With respect, local constants and/or immutable local variables are hardly "wild 
ideas," nor likely something that has "little grounding in what's possible."

-Mike

Re: [PHP-DEV] Local constants

2024-09-05 Thread Mike Schinkel
On Sep 5, 2024 at 5:46 PM,  wrote:

> Block-scoping doesn't have to allow shadowing of names, 

How exactly would that work?  Are you suggesting to restrict the use of 
variable names to one per function but still allow for block scoping?

Or if not, how would an inner block variable $x not shadow an outer variable 
$x? Shadowing is not a feature that is added, it is the result of block 
scoping, AFAIK.

> and it certainly doesn't have to be achieved by that incredibly hard to spot 
> syntax. In most languages I've seen, it's indicated by either a keyword such 
> as "let", "var", or "my"; or by  indicating the type of the variable you're 
> declaring.

That declaration syntax is not what makes it problematic, it is the number of 
lines between the two declarations. I would not be so against it if most people 
kept their functions to 25 lines or less, but what have I have seen to think 
200 to 500 line functions are the norm in legacy code I've had to work on.

But then if most people kept their functions small there would be far less 
"need" for block scoping. (Actually — to channel Rob — block scoping could 
encourage people to wrote longer functions which would definitely be a negative 
outcome.)

> For one thing, it would make me much more likely to accept the repeated 
> requests for closures which capture parent scope by default, because it would 
> give a clear opt-out to replace the current clear opt-in of the use() clause.

Scoping within a closure differs from in-line blocks having their own scope. 
For one, a closure is separated by a parameter stack whereas a block shares the 
stack with its function. Closures can be assigned to variables and objects 
properties and also passed to functions, blocks cannot. Closures have their own 
return values, blocks have no return statements thus are coupled to the 
function's scope. And finally and most importantly, the point of a closure is 
to delay or delegate execution whereas blocks execute inline with the function 
where they are located. For all these reasons local scope makes sense in 
closures whereas IMO scope in blocks does not.

> It's something I'd really like to see in PHP. 

Be careful what you wish for. But don't say I did not warn you if it comes to 
pass.

> I've never found myself wishing for local constants, but never really used a 
> language with them, so maybe I'd find them valuable if they were added.

Ignorance is bliss. And I mean that literally, not pejoratively.

> For completeness, I'll mention that *typed* local variables are another 
> related concept, which has also come up in the past.

You'll get no argument from me on type local vars.

> The big challenge in all of them is that these are big fundamental language 
> changes, which require an expert knowledge of how the language works under 
> the hood 

Really? I believe what the OP was asking for — or at least it is what I would 
be interested in — are immutable variables that we could conveniently declare 
with `const`. I could be wrong but it seems the only thing it would require is 
the compiler to throw an error when asked to generate a variable assignment 
opcode to any variable declared as a const.

The above assumes piggybacking on variables with `$` syntax vs. no-`$` syntax, 
so maybe using `const` would not be the best keyword. We could use `var` but 
that doesn't indicate immutability.  

Or it may possible that implementing as `const` w/o `$` syntax would not be 
hard given that global const names are already recognized by the parser. And 
they could internally be kept on the same stack as variables.

> Let's not get too deep into discussing the colour of the bikeshed before 
> we've worked out if there's space to build one.

It is ironic you say we should make sure it's possible before we discuss if we 
want it. I know I have heard the opposite many times on this list — make sure 
we even want it before we worry about how to implement — although I cannot say 
for sure that it was ever you that said that.

Whatever the case, of the features that have been implemented in recent years I 
find it hard to believe adding local constants would be nearly as hard as some 
of those features. Certainly easier than aviz.

-Mike

Re: [PHP-DEV] Local constants

2024-09-05 Thread Mike Schinkel


> On Sep 4, 2024, at 5:41 PM, Rob Landers  wrote:
>> > On Sep 4, 2024, at 16:45, Rob Landers > > > wrote:
>> > 
>> > I think, conceptually, this makes sense, but maybe I'm the only one who 
>> > writes
>> > 
>> > $arr = doSomething();
>> > $arr = array_map(fn($x) => $x->prop, $arr);
>> > $arr = array_filter($arr, $filterFunc);
>> > 
>> > instead of
>> > 
>> > $arr = array_filter(array_map(fn($x) => $x->prop, doSomething()), 
>> > $filterFunc);
>> 
>> IMO, that's a failing of PHP not supporting object syntax (and reasonable 
>> api) for non-object values. In other languages, I can write code such as:
>> 
>> let arr = doSomething()
>> .map { $0.prop }
>> .filter(filterFunc)
>> 
>> Which is more readable than both PHP versions.
> 
> I think that sidesteps the reality we are currently in and is orthogonal to 
> the actual problem I perceive. To be more clear, I think with the current 
> APIs in PHP, having local constants would incentivize people to write less 
> readable code for the reasons you mentioned. 

It could ALSO incentivize people to write their own wrappers — easily done in 
userland — or include a package that has those wrappers already written, and 
then they *would* be able to write more easily-readable code like this:

const WIDGET = getWidgets()
   ->map(fn($w) =>$w->prop)
   ->filter($filterFunc);

Further, as part of the announcement of the new feature that PHP we could write 
that PHP considers it a best practice to use said wrappers rather than to write 
code in the less readable format you presented.

And if people instead do as you fear it would provide more incentive for PHP to 
add such quality-of-life improvements into core.

> Maybe, but I only mention that block-scope would be more valuable than local 
> constants. That they work well together is also interesting.

Block-scope?  Please, just no. 

As someone who also develops in Go, one of the biggest mistakes they made in 
language design IMO is block-scoped variables. In my anecdotal opinion, 
block-scoping is one of the more insidious foot-guns in the language as it is 
all too easy to accidentally shadow a variable that you did not intend to 
shadow which can result in a hard-to-track down bug.  

Not convinced? At least one other person has my same view of the dark despair 
of block-scoping:

https://forum.golangbridge.org/t/warning-for-accidental-variable-shadowing-with-block-scope/4715

Of all the Go code I have written, I'd say accidental variable shadowing is in 
the top-three (3) reasons for bugs in my code, if not the main reason. And if 
it were not for BC breaks, I would lobby hard for Go to remove it. I know that 
some on the Go team lament that they ever included it.

So while block-scoping appears to be a panacea, it is really a wolf in sheep's 
clothing.

> This is a problem that I have run into in only a handful of times in my 
> entire career, across all languages, lots of times in JavaScript files of 
> yesteryear when we had to deal with 10k loc handrolled files. I’ve seen this 
> happen maybe 2-3 times in php (where it has been a bug), and a couple of 
> times in C. I don’t think I’ve ever run into it in C#, Scala, or Python. 
> Maybe I’m just lucky, but I don’t feel like this is a valid reason for the 
> feature.

I have run into this problem a handful of times in the past *month* including 
in other people's code, so clearly one person's experience is not universal.

> Const was added to JavaScript (according to my cobwebbed memories) to 
> introduce block scoping and optimizations around that. In PHP, we also have 
> function scope, like JavaScript, but we also have lexical scope as well. 
> Javascript did not have that at the time; in other words, the following would 
> have output "world":
> 
> Today, it doesn't, and neither would php. The problems that const/let set out 
> to solve in Javascript do not apply here, IMHO.

There are other languages that exists outside the web bubble of PHP and 
JavaScript, and most have local constants for which "the reasons they were 
added to JavaScript do not apply to PHP" — a claim for which I do not know 
enough of this specific history to opine — do not apply:  Java/Kotlin, Swift, 
Go, C/C++, Zig, and Rust (while ignoring TypeScript given its roots in JS.)

Simply put the reason for local const is to declare an immutable variable, one 
whose value we know cannot change. One key reason relevant to PHP is to ensure 
its value is not changed by reference by a function you are calling, but also 
so that you don't accidentally change it in the same function. And here are 
some more reasons elaborated: 

https://stackoverflow.com/questions/622664/what-is-immutability-and-why-should-i-worry-about-it

-Mike



Re: [PHP-DEV] Local constants

2024-09-04 Thread Mike Schinkel
> On Sep 2, 2024, at 11:20 PM, HwapX  wrote:
> Hello internals!
> 
> I was wondering, has there been any discussion about supporting local 
> constants (variables that cannot be reassigned, perhaps even function 
> parameters)?
+1 from me.

-Mike

Re: [PHP-DEV] Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP

2024-09-04 Thread Mike Schinkel
> On Sep 2, 2024, at 11:10 PM, Hammed Ajao  wrote:
> 
> That's one of the reasons, but arrays are not strict enough (you can add 
> anything to any array, no distinction between a list and map), and you can't 
> really specify the shape of an array.

What do you mean by "shape of an array" in this context?  

I am trying to understand how an object differs in "shape" and I am coming up 
with nothing.

> And/or do you want the compiler to validate when you use a name that has not 
> been declared, i.e. when you type "Content_Type" or "Content Type" for   
> you want an error message?
> 
> The cool thing is that the compiler already does this with named parameters 
> or the splat operator applied to an array (https://3v4l.org/tholi#v8.3.11).

That is quite interesting, I did not know that was possible.

Unfortunately though, the validation is done at the point of call not at the 
point of array instantiation which can result in spooky action at a distance if 
use in more than trivial ways:

https://3v4l.org/ZJXYX#v8.3.11

>  Not at all, I just prefer custom and strict data structures with a clear 
> intention.

+1 

> I mean it is more work having to define a custom attribute and reflecting 
> It's target each time you want literal string names. The compiler already 
> does all I need, I just want to extend that support to literal strings.
>  
> I'm proposing using a class every time you need a strict data structure with 
> the keys known ahead of time, trust me i have no issue with more work when 
> it's warranted, your version is just a lot of unnecessary code that doesn't 
> actually achieve that.

Okay, I hear where you are coming from.

>  I'm proposing two things:
> 1. Properties keys as literal strings:
> ```
> class A { public array "key"; }
> ```
> Since php also allows declaring properties in functions (promoted 
> properties), we have to decide what to do with:
> ```
> class A { public function __construct(public array "key"); }
> ```
> Which means we would run into cases where it's valid to pass a literal string 
> as a named parameter
> ```
> $a  = new A("key": 1);
> ```
> I decided to add that to my proposal since there's no point restricting it to 
> only constructors, which brings us to:
> 2. Literal strings as named parameters
> Since I decided to include functions, we now have to decide what to allow and 
> what not, for example, can you now define params as strings too:
> ```
> function func(string "param", array "withDefault" = []) {}
> ```
> or is it only allowed in variadic functions and func_get_args() (so syntactic 
> sugar for what we have now with func(...[]))

That is very helpful to understand why you came to what you are proposing.

For me though, extending it in that way would potentially infect other much 
more common use-cases so I would prefer to have a constrained data type that 
allowed this rather than an open-ended one.  And one that did not perpetuate 
the requirement to use quotes for what are effectively identifiers that do not 
follow the syntactical rules of identifiers.

> Say I have a response class:
> ```
> class Response { 
> public function __construct(private MyHeaders $headers) {}
> }
> ```
> With MyHeaders being a class, nothing is stopping me from passing in:
> ```
> class MyCustomHeaders extend MyHeaders {
> public function __construct() {
> parent::__construct();
> //unset one of the keys or set more
> }
> }
> ```
> That isn't possible with the enum and I would have to store MyHeaders as an 
> array in the Response class.

Fair point on the enum

OTOH as for storing as an array in your Response class, I don't see how that is 
huge issue. I do see how the array does not have a reflectable identity, but 
stuff it in a single property Response class and then together they do. 

But I do get that you want to minimize that boilerplate.

>  > MyHeaders::create("Content-Type": "text/html; charset=utf-8", 
> "X-Custom-Header": "value")
> 
> But it's clear, each key does what it intends, no additional processing will 
> be required to transform/validate the keys.

It is only "clear" if you can get past all the quotes obscuring what is a key 
and what it a value. 

When I first saw your proposal I did not notice the colons and thought you had 
written the following. If you read back at my original reply you'll recognize 
that I misunderstood your example:

MyHeaders::create("Content-Type", "text/html; charset=utf-8", 
"X-Custom-Header", "value")

IOW, I find it too easy to misread and would not want to have to read and/or 
maintain code that did not have a more easily visible distinction between what 
goes on the left of the colon and what goes on the right, remembering that 
reading and maintenance comprise far more time in the life of working code than 
the initial development.  

>  MyHeaders::create(Content-Type: "text/html; charset=utf-8", X-Custom-Header: 
> "value")
> 
> That works for me, but the literal has clearer intent and doe

Re: [PHP-DEV] Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP

2024-09-03 Thread Mike Schinkel



> On Sep 3, 2024, at 7:52 AM, Anton Smirnov  wrote:
> 
> On 03/09/2024 14:48, Anton Smirnov wrote:
>> [new AAA, '123AnyChars%%!@#']();
> 
> Wrong example, sorry, should be
> 
> (new AAA)->{'123AnyChars%%!@#'}();

Still, '123AnyChars%%!@#' is not included in the array returned by 
`get_class_methods()` and/or `ReflectionClass::getMethod()` which is evidence 
of why procedural magic methods are at best a bandaid compared with declarative 
solutions.

-Mike

Re: [PHP-DEV] Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP

2024-09-02 Thread Mike Schinkel



> On Sep 2, 2024, at 1:48 PM, Hammed Ajao  wrote:
> 
> Hello Mike,
> 
> Thanks for reading and responding. While your enum does technically address 
> some of the issues I am discussing, it does so in a very verbose and 
> cumbersome way.
> - First you need the DefaultValue attribute
> - Then you need to use it on each of your `properties`
> - You also need to define an identifier for the const which defeats the 
> purpose of using literal strings
> - Then you need to use reflection to access the properties
> - Then you're left with : MyHeaders::create(MyHeaders::CONTENT_TYPE, 
> "plain/text", MyHeaders::X_CUSTOM_HEADER,"new_value"); which isn't super 
> clear that it's mapping every other value to the one before it.

That is why I wrote that maybe we could consider reducing the verbosity and 
more cumbersome aspects as I proactively recognized it was painful. 

That is why I asked about other use-cases. If the only solid use-case is HTTP 
headers we write it once and its done. 

OTOH, if there are many other use-cases then we could look at adding syntax 
sugar. Adding syntax sugar to languages when boilerplate patterns emerge has 
many benefits: fewer bugs, easier coding, making the language more powerful, 
and etc.

> As for the idea that an object property must be a valid identifier, I'm not 
> sure that's correct. Objects can have integer properties natively i.e 
> $obj->{1}, and literal string properties are already possible when you cast 
> an array to an object

Yes, that was pointed out to me. 

I was thinking more about the PHP language for language parsers syntax when I 
wrote that and thinking less about the fact that instances can have dynamically 
assigned properties.  My bad.

> Let me show you a few other use cases i've run into
> 
> ```php
> 
> class Sizes {
> public function __construct(
> private string $sm,
> private string $md,
> private string $lg,
> private string $xl,
> private string $2xl, // will throw
> private string "10xl", // wouldn't this be nice
> ) {}
> }

Is that really a class that someone would write, with a different property for 
each size and a constructor that required setting each size? Or wouldn't they 
typically have an Enum for the sizes and an array property indexed by the enum?

Maybe your example was just to illustrate your desire for a `$2xl` and `"10xl"` 
property?  I see what you want here, OTOH I would not be a fan. I'm just as 
happy to name them `$twoXL` and `$tenXL`, or `$_2xl` and `$_10xl` vs. dealing 
with non-identifiers in declared property names.  I get that is not what you 
want, but realize I am not the decider, I am just representing one person's 
opinion, and I can't even vote on RFCs, so there is that. ¯\_(ツ)_/¯

> function htmlElement(string $tag, string $content, string|bool 
> ...$attr) {}
> htmlElement("div", "Hello, world!", class: "greeting", id: 
> "greeting", "data-foo": "bar");

I did not grasp the use-case you are showing here because the one in your 
original email included using non-identifiers as parameter names so I conflated 
your two proposals as being one.

In the case you presenting here —assuming I understand what you are proposing — 
I would likely be in favor of something like it. That is if it were orthogonal 
and not requiring of your first proposal i.e. in its own RFC. 

Taking what you have I would expect something more like the following but where 
`[HtmlAttribute]` is my placeholder for a syntax that would specify that zero 
or more named parameters be collected and assigned by property name to the 
object `$attr` of type `HtmlAttribute` — bikeshed away on that syntax —, and to 
assign to arrays you specify the array index in the named argument, e.g. 
`data["foo"]`:

class HtmlAttribute {
   public string $_class;
   public string $id;
   public array $data;
}
function htmlElement(string $tag, string $content, [HtmlAttribute] ...$attr) {}
htmlElement("div", "Hello, world!", class: "greeting", id: "greeting", 
data["foo"]: "bar");

Alternately if you were not envisioning the mapping to an object a similar 
feature could just be way to use a function to collect  arbitrarily names 
parameters into an array, e.g.:

function htmlAttributes(string|int ...$attr) {}
htmlAttributes(class: "greeting", id: "greeting", data["foo"]: "bar");

The above would collect the args into an array `$attr` shaped like this:

array(
   "class" => "greeting",
   "id" => "greeting",
   "data" => array(
 "foo" => "greeting",
   ),
);

Actually, it would be nice if PHP offered both options.

> - Then you're left with : MyHeaders::create(MyHeaders::CONTENT_TYPE, 
> "plain/text", MyHeaders::X_CUSTOM_HEADER,"new_value"); which isn't super 
> clear that it's mapping every other value to the one before it.


BTW: it could currently be written like 

Re: [PHP-DEV] Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP

2024-09-02 Thread Mike Schinkel
> On Sep 2, 2024, at 12:42 PM, Christoph M. Becker  wrote:
> 
> On 02.09.2024 at 16:51, Mike Schinkel wrote:
> 
>> Generally I am one who welcomes new feature ideas, but I fear that string 
>> literals as object properties would break a valuable assumption that all 
>> properties must be a valid identifier. Without that assumption I fear many 
>> things that would become more complex.
> 
> Is that so?  See <https://3v4l.org/bZTFi>.

Consider me corrected.

I seem to now remember once knowing this was possible since you point it out. I 
think my subconscious must have caused me to repress that memory given the 
tragedy of it when I read Hammad's proposal. ¯\_(ツ)_/¯

>> So I am sympathetic to the desire to improve the language. However I fear 
>> this specific change would create more pain than pleasure. Better IMO to 
>> look for less disruptive solutions to achieve the same goals. For example, 
>> if the Enum+Attributes approach meets your needs aside from having too much 
>> boilerplate, maybe we could enhance PHP to have less of that boilerplate?
> 
> ACK

Can you elaborate on what 'ACK' means in this context?

-Mike



Re: [PHP-DEV] Pre-RFC Discussion: Support for String Literals as Object Properties and Named Parameters in PHP

2024-09-02 Thread Mike Schinkel
> On Sep 1, 2024, at 5:47 PM, Hammed Ajao  wrote:
> 
> Dear PHP internals community,
> I hope this email finds you all well. I'd like to propose an idea that I 
> believe could enhance PHP's flexibility and consistency, especially when 
> working with string literals. I'm looking forward to hearing your thoughts 
> and feedback on this proposal.
> Introduction
> I'm suggesting two enhancements to PHP that I think could make our lives as 
> developers a bit easier:
> 
> Support for String Literals as Object Properties
> Support for String Literals as Named Parameters in Function Calls
> 
> The main goal here is to reduce our reliance on arrays and provide more 
> intuitive ways to define and access data, particularly in scenarios like 
> working with HTTP headers where we often deal with non-standard characters 
> and strings.
> 1. String Literals as Object Properties
> Current Situation
> As we all know, we typically define and access object properties using 
> standard identifiers:
> ```php
> class Foo {
> public string $contentType = "application/json";
> }
> 
> $obj = new Foo();
> $obj->contentType = "text/html";
> ```
> 
> But when we're dealing with data that includes non-standard characters or 
> strings (think HTTP headers), we often end up using associative arrays:
> ```php
> $headers = [
> "Content-Type" => "application/json",
> "X-Custom-Header" => "value"
> ];
> ```
> 
> I think we can all agree that this reliance on arrays can make our code less 
> intuitive, especially when we're managing complex data structures.
> Proposed Enhancement
> What if we could use string literals as object property names? Here's what 
> I'm thinking:
> ```php
> class MyHeaders {
> 
> public function __construct(
> public string "Content-Type" = "application/json",
> public string "Cache-Control" = "no-cache, no-store, must-revalidate",
> public string "Pragma" = "no-cache",
> public string "Expires" = "0",
> public string "X-Frame-Options" = "SAMEORIGIN",
> public string "X-XSS-Protection" = "1; mode=block",
> public string "X-Content-Type-Options" = "nosniff",
> public string "Referrer-Policy" = "strict-origin-when-cross-origin",
> public string "Access-Control-Allow-Origin" = "*",
> public string "X-Custom-Header" = "value",
> ) {}
> 
> public static function create(string ...$headers): self {
> return new self(...$headers); // Throws an error if an unknown named 
> parameter is passed
> }
> 
> public function dispatch(): void {
> foreach ((array) $this as $name => $value) {
> header("$name: $value");
> }
> }
> }
> 
> $headers = new MyHeaders("Content-Type": "application/json", 
> "X-Custom-Header": "value");
> // or
> $headers = MyHeaders::create("Content-Type": "text/html; charset=utf-8", 
> "X-Custom-Header": "value");
> $headers->dispatch();
> ```
> This would allow us to include characters in property names that aren't 
> typically allowed in PHP identifiers, like hyphens or spaces. I think this 
> could make our code more readable and aligned with natural data 
> representation.
> Benefits
> 
> Greater Flexibility: We could create more natural and direct representations 
> of data within objects.
> Enhanced Consistency: This aligns with the proposed support for string 
> literals as named parameters, creating a more uniform language experience.
> Simplification: It could reduce our need for associative arrays, which can be 
> more error-prone and less intuitive.
> 
> 2. String Literals as Named Parameters in Function Calls
> If we're going to use string literals as object properties, it makes sense to 
> also use them as named parameters, especially in constructors with promoted 
> properties. And why stop at constructors? This leads to the second part of my 
> proposal.
> Current Situation
> We can use named parameters in function calls, but only with standard 
> identifiers:
> ```php
> function myHeaders(...$args) {
> foreach ($args as $key => $value) header("$key: $value");
> }
> ```
> 
> To use string literals with special characters, we have to use associative 
> arrays:
> ```php
> myHeaders(...["Content-Type" => "application/json"]);
> ```
> 
> This can be a bit cumbersome and less readable, especially for complex data 
> structures.
> Proposed Enhancement
> What if we could use string literals as named parameters? It might look 
> something like this:
> ```php
> foo("Content-Type": "application/json");
> ```
> 
> I think this syntax could offer several advantages:
> 
> Improved Readability: Our code could become clearer and more aligned with 
> natural data representation.
> Automatic Parameter Mapping: We could map string literals to corresponding 
> parameters without requiring manual intervention.
> Simplified Constructor Usage: This could be especially beneficial for 
> constructors where we need to pass complex data structures directly.
> 
> I

Re: [PHP-DEV] PHP 8.3.11 Released

2024-09-02 Thread Mike Schinkel
> On Sep 1, 2024, at 6:12 PM, Christoph M. Becker  wrote:
> 
> On 01.09.2024 at 09:16, Mike Schinkel wrote:
> 
>> One of the benefits for users when software authors strictly follow SemVer 
>> is that automated tooling can decide if an automatic upgrade should be safe. 
>> Depending on out-of-band information to convey BC breakage can result in 
>> those who use automatic upgrades to see unexpected failures en masse since 
>> automated tooling won't look at bespoke, non-standard labels when deciding.
>> 
>> If enough software authors choose to be less strict about SemVer it could 
>> have the fallout that many people decide it is just too risky to use 
>> automated tooling. Once bitten, twice shy.
>> 
>> One approach I have seen on other projects take is they retract the versions 
>> with BC breakage and then release an update reversing the breakage.
> 
> What does "retract" mean in this context?  I mean, we can delete the
> tag, remove the download from php.net – but the version has already been
> released, and might be used in the wild.

Retraction is something I know from Go, but after your question I learned that 
it may be a concept Go introduced as go's binary has tooling to detect and warn 
against reversions built-in.  

If you are unfamiliar with Go, it has location of downloadable source as a 
first class concept in the package name, hence `example.com/my/package` can be 
downloaded with `go get example.com/my/package`.  If I had published then 
retracted a version 1.5.0 and you were to `go get example.com/my/package@1.5.0` 
then Go would warn you that the package is retracted.

Still, you do not need any tooling to effectively revert for all intents and 
purposes:

1. Revert the code.
2. Calculate a new tag by incrementing the to-be-reverted tag by 0.0.1
3. Commit the changes with a commit message saying the commit reverts the prior 
commit named by the new tag.
4. Tag the changes with the new tag and a message saying it reverts the prior 
patch tag.
5. Edit the messages of the reverted tag and reverted commit by prefixing them 
"REVERTED:" and "REVERTED IN x.x.x:", respectively.

Here are some links covering reversion in Go if you want to dive deeper into 
their approach:

- https://www.jvt.me/posts/2024/01/15/retract-go-release/
- https://play-with-go.dev/retract-module-versions_go119_en/


> We already have the "problem" that we tag on Tuesdays, but release on
> Thursdays, but you find builds from Wednesdays in Linux distros.

Retracting is never meant to erase history, and we cannot guard against all 
possible use. Retracting is meant to (hopefully greatly) minimize the use and 
any fallout that might otherwise occur.  

Further, retracting "swims with the current rather than against it" (my 
metaphor) meaning that automated tooling would choose to deploy the fixed 
version over the broken one and would also upgrade from the broken one to the 
fixed one as soon as the tooling was run again.

In the case that a Linux distro captures the reverted release into a periodic 
release of their distro, then whoever discovers this could submit a bug fix for 
them to issue their own bug fig for their released version to update to the 
+0.0.1 tag.

Not perfect, but perfect is usually the enemy of the good.

Hope this helps.

-Mike

Re: [PHP-DEV] PHP 8.3.11 Released

2024-09-01 Thread Mike Schinkel
> On Aug 31, 2024, at 1:44 PM, Christoph M. Becker  wrote:
> 
> On 31.08.2024 at 19:35, Derick Rethans wrote:
> 
>> Shouldn't we have bumped the API number for this? Better safe than sorry.
> 
> That ABI break was accidentially committed.  There was some discussion
> whether to stick with the break and bump API numbers, or to revert, and
> there was consensus that in this case the latter makes more sense (after
> all, just a single release was affected, and only relevant for
> extensions which actually use the streams layer).
> 
>> And I'm wondering why we have no tests for ABI breaks here? I'm sure that I 
>> have seen a report (from Remi?) that highlighted these breakages when I was 
>> still involved in the mongodb extension.
> 
> There was the idea to do some verifcation, but maybe it's enough to add
> something to the PR-labeler which just labels any PR which modifies a
> public header.

One of the benefits for users when software authors strictly follow SemVer is 
that automated tooling can decide if an automatic upgrade should be safe. 
Depending on out-of-band information to convey BC breakage can result in those 
who use automatic upgrades to see unexpected failures en masse since automated 
tooling won't look at bespoke, non-standard labels when deciding.  

If enough software authors choose to be less strict about SemVer it could have 
the fallout that many people decide it is just too risky to use automated 
tooling. Once bitten, twice shy.

One approach I have seen on other projects take is they retract the versions 
with BC breakage and then release an update reversing the breakage. 

Something to consider.

-Mike

Re: [PHP-DEV] [Discussion] Implementing interfaces via traits

2024-08-31 Thread Mike Schinkel
> On Aug 30, 2024, at 10:15 AM, Larry Garfield  wrote:
> I would be very much in favor of revisiting Interface Default Methods, 
> though, as I think it would be a strong feature, and it's one found in nearly 
> all of our sibling languages at this point.  PHP is weird for not having 
> them.  I believe that would also be a better approach than traits that link 
> to interfaces, which achieves not-quite the same result with more steps.

I too am all for revisiting Interface Default Methods.  

Lack of interface default methods is one of the most painful missing features 
in PHP, IMO.

-Mike

P.S. Frankly, I would prefer PHP just merge the functionality of traits and 
interfaces so we can use `implements` or `use` and only have to reference one 
file instead of create two parallel files, but convincing others of this 
approach would likely be a herculean task, so Interface Default Methods would 
be a not-so-bad alternative.


Re: [PHP-DEV] [RFC] Default expression

2024-08-26 Thread Mike Schinkel
> On Aug 26, 2024, at 8:28 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Mon, 26 Aug 2024, at 11:43, Mike Schinkel wrote:
>>> You ask how a library can provide access to that default, and the answer is 
>>> generally pretty trivial: define a public constant, and refer to it in the 
>>> parameter definition. 
>> 
>> A global? Really?
> 
> I didn't say "global", I said "public".

I was imprecise in my description. I meant "global" in the general programming 
sense and not in the PHP keyword `global` sense.

Sorry about my lack of precision here.

> Since you're keen on real-world examples, here's a simplified version of a 
> real class:
> 
> class ConfigSource
> {
>   private HttpClientInterface $httpClient;
> 
>   public const DEFAULT_CONSUL_URL = 'http://localhost:8500';
> 
>   public function __construct(private string 
> $consulUrl=self::DEFAULT_CONSUL_URL, ?HttpClientInterface $httpClient=null)
>   {
>   if ( $httpClient === null ) {
>   $httpClient = new HttpClient();
>   $httpClient->setRequestTimeoutSecs(5);
>   $httpClient->setConnectRequestTimeoutSecs(5);
>   }
>   $this->httpClient = $httpClient;
>   }
> }
> 
> This constructor has two optional parameters; one of them uses a default 
> which is also referenced explicitly in another class, so is exposed as a 
> constant; the other uses a completely opaque method of creating a default 
> object, which even Reflection could not expose.
> 
> The caller doesn't need to know how any of this works to make use of the 
> class. The contract is "__construct(optional string $consulUrl, optional 
> ?HttpClientInterface $httpClient)"
> 
> The purpose of the optional parameters is so that you can write 
> "$configSource = new ConfigSource();" and trust the library to provide you a 
> sensible default behaviour.

Thank you (sincerely) for taking the time to author a real-world use-case.

> If it was decided that the code for creating a default HttpClient was needed 
> elsewhere, it could be refactored into a method, with appropriate access:
> 
> public function __construct(private string 
> $consulUrl=self::DEFAULT_CONSUL_URL, ?HttpClientInterface $httpClient=null)
> {
>   $this->httpClient = $httpClient ?? $this->getDefaultHttpClient();
> }
> 
> public function getDefaultHttpClient(): HttpClient
> {
>   $httpClient = new HttpClient();
>   $httpClient->setRequestTimeoutSecs(5);
>   $httpClient->setConnectRequestTimeoutSecs(5);
>   return $httpClient;
> }

So, nullable is an equivalent to the union-type concern my discussion with John 
Coggeshall uncovered, correct? 

When two different types can be passed then we cannot depend on the `default` 
being a specific type.

> Or perhaps the HttpClient becomes nullable internally:
> 
> public function __construct(private string 
> $consulUrl=self::DEFAULT_CONSUL_URL, private ?HttpClientInterface 
> $httpClient=null) {}
> 
> Or maybe we allow explicit nulls, but default to a simple class instantiation:
> 
> public function __construct(private string 
> $consulUrl=self::DEFAULT_CONSUL_URL, private ?HttpClientInterface 
> $httpClient=new HttpClient) {}
> 
> None of these are, currently, breaking changes - the contract remains 
> "__construct(optional string $consulUrl, optional ?HttpClientInterface 
> $httpClient)".

Great example.

Now consider the following, assuming the RFC passed but with an added 
requirement that `match()` be used exhaustively for nullable parameters (shown) 
or parameters type hinted with unions (not shown):

$configSource = new ConfigSource(default,match(default){ 
NULL=>new 
ConfigSource->getDefaultHttpClient()->withRequestTimeoutSecs(5),
default=>default->withRequestTimeoutSecs(5)
})

Ignoring that this expression is overly complex, if covering all "types"  would 
be a requirement in the RFC — where `NULL` is a type here for purposes of this 
analysis —can you identify another breaking change if the RFC passed?

> On Aug 26, 2024, at 8:43 AM, Rowan Tommins [IMSoP]  
> wrote:
> On Mon, 26 Aug 2024, at 11:43, Mike Schinkel wrote:
>> 
>> But saying that we can be certain default values are private and we 
>> want to keep them that way is provably false by the existence of 
>> Reflection.  
> Right now, accessing the default value of an optional parameter is in the 
> "possible if you mess around with Reflection APIs" set; maybe we do want to 
> move it to the "is part of the language" set, maybe we don't; 

Re: [PHP-DEV] [RFC] Default expression

2024-08-26 Thread Mike Schinkel
> On Aug 26, 2024, at 2:26 AM, John Coggeshall  wrote:
> The proposal in the RFC creates a new dependency and backward compatibility 
> issue for API developers that currently does not exist. It is not just 
> because it allows for non-sensical expressions, but that it allows perfectly 
> sensical expressions that would create dependencies between libraries that I 
> don't think are a worthwhile tradeoff. See my code example below.

If you reread my email you'll note I divided it into two objections and your 
reply seems not to recognize that. 

Your comment defends against the objection I listed as #2 but you quoted the 
discussion of the objective listed as #1. 

> (TL;DR; Down the thread a bit I put together a concrete example of why I'm 
> opposed to this RFC)

I read through the entire thread and I did not see any examples you provided 
that provided any real-world concerns, unless I misunderstood. But since you 
provided a better example let us just ignore my comments on those.

> Consider this metaphor -- If I have a object with private properties, PHP 
> doesn't allow me to reach into that object and extract those values without a 
> lot of work (e.g. Reflection) by design. Right now, there are lots of 
> libraries out there defining default values and right now today they are in 
> the same sense "private" to the function/method they are defined for. This PR 
> would change the visibility of those default values, pulling them higher up 
> into the call stack where IMO they don't belong -- essentially making them a 
> brand new dependency API devs need to worry about.

I acknowledged that. However, I was not convinced that the default value 
concern is an actual concern vs. a theoretical concern.  So that is why I asked 
for specific examples where it would cause a real problem vs. just a 
theoretical concern. 

> Sure if I have `foo(int $index=1)`, a developer calls with `foo(default*3)`, 
> and then the author of foo changes the signature to `foo(int $index=0)` that 
> might cause problems, but what is a real world scenario where a developer 
> would actually do that, the author then change it, and then is causes a 
> non-trivial problem?
> 
> How is that not a real-world contrived scenario?

Because there was no use-case described for:

1. The purpose of the function,
2. Why someone would multiply the default times three, nor
3. Why the API developer would break BC and change the default for the 
use-case. 

That kind of information is what I was looking for.

Besides, are you really calling a function named "foo()" a "real-world 
scenario?"  ;-)

Anyway, I am going to skip to your example because otherwise I would just be 
repeating my call for concrete examples in response to your earlier comments in 
that reply.

> Let me propose this example and see if you still hold firm to your option 
> that the following expression would not be valid and that it still would not 
> be a good idea for the language:
> class MyDependency {...}
> function doSomething(MyDependency $dep= new MyDependency) {...}
> doSomething((default)->WithLogger(new Logger));
> 
> Let's make that a little more complicated so you'll see the problem -- 
> Consider this rather lengthy example building off the concept of your example:
> 
> 
> 
> (new A)->withLogger((default)->log('B'));

Well, this is not the example I asked you to comment on. Yes, you are using 
`WithLogger()` but you are not using it in the same context I asked about. 

Nonetheless, I will consider your example. It would be nice if you would 
revisit mine.

> This would be valid under this RFC, right?

No, because the method log() is implicitly void.  WithLogger() expects a 
Logger, not a null. But then I expect your example just had some logic errors, 
no?

BTW, in your example I am not sure I understand what `log()` does. I assume it 
is logging a value?

> But now as the author of class A I later want to change the default of my 
> withLogger  method. Instead of just passing in new DatabaseLogger, I now want 
> to change my API default to just a LoggerType::DB enum for reasons (What the 
> reasons aren't relevant).
> 
> Today I don't have to think too hard about that change from an API BC 
> perspective because the consumer has either passed in a LoggerInterface  or a 
> LoggerType  -- or left it empty and used it's default value. I can just 
> change the default to LoggerType::DB  and be on my way. The downstream 
> developer will never know or care that I did it because if they wanted to 
> call log()  they had to first create their own instance of LoggerInterface  
> and have a reference to that object in their local context like so:
> 
> $logger = LoggerType::DB->getLogger();
> (new A)->withLogger($logger);
> $logger->log('B');
> 
> With this RFC, now I can't  change this API call without introducing a BC 
> break in my library because I have no idea at this point if some downstream 
> caller decided to use my default value directly or not.

Okay, this I 

Re: [PHP-DEV] [RFC] Default expression

2024-08-25 Thread Mike Schinkel
This is a general comment so not replying to anyone in particular hence the 
top-posting (but with some bottom-posts in particular reply below.)

The RFC — which I am neither pro nor con for — proposes allowing default to be 
an expression, and while many like and support the RFC others are (not quite) 
demanding that it must be limited to its own subset of expressions, because, 
concerns.

It seems to me the "concerns" fall into two categories:

1. Some expressions make no sense so we should disallow them, and 
2. Allowing default to be an expression makes it part of the published API.

Speaking only to #1 for the moment, there are many different places in PHP 
where certain expressions make no sense either, yet I do not see those 
objecting calling the question for those other scenarios, and I ask myself "Why 
not?"  

One obvious answer is "because those are status quo and this is not" but I also 
maybe because the many non-sensical things that can be done elsewhere are, in 
practice, not a problem as nobody ever does them. And why not? Because...they 
are nonsensical. Given this the arguments against feel to me to be rather 
bikesheddy. But I will come back to #1.

Moving on to #2 I respect the argument in theory. But as we are constantly told 
the RFC author's burden is to prove the necessity, it seems only reasonable and 
fair to expect that — when many people see the utility of and support an RFC — 
that those who object to it should provide some concrete examples of how their 
concerns would manifest problems rather than just say "it might allow something 
bad."

I have looked for but yet not seen any examples of how effectively publishing a 
default value could actually cause a significant problem — and this is the 
important part — in a real-world scenario and not just a contrived one. 

Sure if I have `foo(int $index=1)`, a developer calls with `foo(default*3)`, 
and then the author of foo changes the signature to  `foo(int $index=0)` that 
might cause problems, but what is a real world scenario where a developer would 
actually do that, the author then change it, and then is causes a non-trivial 
problem?

Given how much support this RFC appears to have, I think it is incumbent on 
those against it to give valid real-world examples where their fears would 
materialize and cause more than a trivial problem. Again, while I am not pro or 
con on this RFC I do think the pro arguments have been better conceived than 
the con arguments, regardless of the underlying merit of the RFC, hence why I 
comment.

> On Aug 25, 2024, at 4:40 PM, Larry Garfield  wrote:
> 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 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.
> 
> Good design makes the easy path the safe path.

In concept, I am in violent agreement with you.

> 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.

I think you imply that there is a dichotomy or at least a 1-dimensional 
spectrum? 

I think however there is at least a two (2) other dimensions, and they include:

2. "How trivial vs. damaging is a thing" and 
3. "How likely are people to accidentally do that stupid thing?"

If the damage is trivial and/or the thing they is very unlikely for them to do 
— maybe because it is non-sensical — then do we really need extra guard rails?  
Passing `default != 5` to an int parameter is (IMO) both unlikely and not 
particularly damaging (if type-hinted, an error will be thrown.)

But if you disallow `default!=5`, then you (likely?) also disallow `default!=5 
? default : 0` and any other *sensical* expression with that sub-expression. Do 
we really want to flesh out all the potential nonsensical expressions for a 
given use-case and build a custom parser for this one RFC?  

I could see having a context-based expression parser getting an RFC in its own 
right, but IMO doing so would be wildly out-of-scope for this RFC. And if such 
as RFC were pursued, I think in the vast majority of cases it should be 
employed by the userland developer and not in PHP core. But I digress.

So please provide examples where nonsensical expressions cause real-world 
problems. If you can, then maybe everyone supportive of the RFC will see 
use-cases where the RFC is problematic. But without good examples illustrating 
serious problems, is there really anything to worry about here?

BTW, you argue about unintended consequences that could not be foreseen hence 
why complex features need to be fully fleshed out — and I agree — but this RFC 
does not 

Re: [PHP-DEV] [RFC] Default expression

2024-08-24 Thread Mike Schinkel
  
  

  
  

  
>   
> On Aug 24, 2024 at 5:16 PM,  mailto:rob@bottled.codes)>  wrote:
>   
>   
>   
> I'm not sure what you mean here. I use this method all the time :) much to 
> the chagrin of some of my coworkers.
>   
>
>   
> function stuff($foo = 'bar', $baz = 'world');
>   
>
>   
> stuff(...[ ...($foo ? ['foo' =>  $foo] : []), ...($baz ? ['baz' =>  $baz] : 
> [])]);
>   
>   
  

  
 And you are one who complains about gotos!😲
  
  
-Mike
  
   

Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-24 Thread Mike Schinkel
  
  

  
  
  
  
>   
> On Aug 23, 2024 at 2:30 PM,  mailto:tovilo.il...@gmail.com)>  
> wrote:
>   
>   
>   
>  On Fri, Aug 23, 2024 at 8:19 PM John Coggeshall
> wrote:  >   >  1. People who don't think BC is a problem, and would like to 
> drop  >  either the global or local lookup entirely, requiring 
> disambiguation.  >   >  There is also an option of swapping the priority, 
> making local lookups secondary to global lookups -- and to override that 
> behavior you would require disambiguation. It doesn't have to mean drop the 
> lookup entirely. Right, that's my proposal. My point was that few (nobody 
> except you and me, I believe) showed particular excitement for this approach. 
>  
>   
>   
> 
>   
> 
>   
>   

 There is also the 5th (or 4th?) option of making built-ins special and not 
require them nor locals be prefixed, and instead require global userland 
functions to be prefixed.  
>   
  
  
  

  
-Mike
  
 

Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-23 Thread Mike Schinkel
> On Aug 23, 2024, at 8:56 AM, Christian Schneider  
> wrote:
> 
> Am 23.08.2024 um 12:27 schrieb Rob Landers :
>> On Fri, Aug 23, 2024, at 12:14, Christian Schneider wrote:
>>> Am 23.08.2024 um 11:34 schrieb Nick Lockheart :
 I think we are all trying to achieve the same thing here.
>>> 
>>> I'm not sure who "we" and what "same thing" here exactly is.
>> 
>> Nick was replying to me :p, judging by the quoted paragraph.
> 
> The "all" in his sentence suggested to me that he means more than him and you.
> But then again I might have misinterpreted this.
> 
>> As far as function overloading goes, I recommend checking out a draft RFC 
>> I've been working on a very, very long time: 
>> https://wiki.php.net/rfc/records. In some off-list discussions, it was clear 
>> that if I wanted this syntax, I would need to pursue function autoloading.
> 
> Definitely an interesting read, thanks a lot for the work you put into it!
> 
>> Further, function autoloading is a clearly missing feature that would be 
>> useful in many situations.
> 
> The "clearly missing" and "many" part is where I disagree. But I was mainly 
> considering current PHP, not future PHP syntax like the Records stuff, agreed.
> 
>> If function autoloading doesn't work out, I will need to take a different 
>> approach to that syntax (which is fine, but not something I want because I 
>> chose the syntax for a very good reason).
> 
> I know you do not want to discuss this here as it is off-topic but it kind of 
> feels the only advantage is to get rid of "new" in the usage of Records. But 
> I'll leave it at that as to per your request, we can revisit that once the 
> RFC hits the discussion stage.
> 
>> That being said, I'm not ready to discuss records here, so this is the first 
>> and last time I'll mention it on the thread. There is a Reddit post in r/php 
>> and a GitHub repo if you are interested in discussing records. There are 
>> very many things to work out still, and it is very much work-in-progress.
> 
> Also a bit off-topic but I still have to mention it, maybe worth another 
> thread:
> I understand where you are coming from but at the same time it feels a bit 
> worrying to me to use another medium (reddit) for a discussion about future 
> language features when we have this mailing list.
> 
> I hope this won't mean that questions/suggestions/concerns on this mailing 
> list won't be discredited because of discussions which happened elsewhere. 
> I'm sorry if I sound a bit paranoid here but I've been in this situation 
> before in other (not software related) aspects of my life before where I was 
> told that something was already decided and people were not willing to go 
> back on certain issues because of that.

FWIW, Rob asked me to review his ideas in email and I pushed him to open up a 
repo so that discussions could be captured and made public rather than lost to 
the ethers of private email.

The problem with discussing everything on the list from minute one is that the 
list has a habit of punishing those who bring ideas that are not fully-baked. 
It is very hard to brainstorm anything on the list without getting shot down by 
those who expect everything discussed on the list to already be fully fleshed 
out.  

Better to get a group of motivated individuals who all want to see a related 
RFC succeed and get them to work through the issues enough that when (and if) 
it is brought to the list there will not be obvious negative arguments against 
it to nip it in the bud when it otherwise could be something worthwhile.

Also, whereas only discussion happens on the list, in a repo you can actually 
start writing a potential implementation and crafting an eventual RFC, so it 
has the potential to be more productive. Finally, the list is the gatekeeper 
anyway, so if things are already decided that the list disagrees with, it still 
won't pass. 

So, if you feel you are a stakeholder on this idea, I'd suggest celebrating the 
idea of a repo and joining the discussion there. 

-Mike

P.S. As for using Reddit, I'm not as big of that as its has its own culture 
that can be just a difficult to incubate ideas as here on this list.

Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-23 Thread Mike Schinkel



> On Aug 23, 2024, at 9:07 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Fri, 23 Aug 2024, at 13:45, Mike Schinkel wrote:
>>> On Aug 23, 2024, at 8:33 AM, Rowan Tommins [IMSoP]  
>>> wrote:
>>> On 23 August 2024 13:04:22 BST, Mike Schinkel  wrote:
>>>> And how can it occur without an explicit `use 
>>>> AcmeComponents\SplineReticulator\Utilities\Text\Text` statement, which I 
>>>> proposed would override the automatic `use`, anyway?
>>> 
>>> I'm not sure what you mean. Right now, that's the function name that would 
>>> be looked up for your example code (other than a couple of unrelated typos 
>>> in your example). So if, for some reason, someone was relying on that, 
>>> their code would break with your "automatic use".
>> 
>> I must be missing something.  Can you give a specific example showing 
>> how the automatic use would conflict with something other than a root 
>> namespace?
> 
> You already gave the example yourself, you just misunderstood what its 
> current behaviour is. Here it is, with the typos fixed: https://3v4l.org/6eD3N
> 
> As you can see from the error message, it doesn't look up "Text\strlen()", it 
> looks up "AcmeComponents\SplineReticulator\Utilities\Text\Text\strlen()"
> 
> Or to be even clearer: https://3v4l.org/ojVcP

Thank you for clarifying. 

You got me there. 

And it is a good illustration why I continue to really dislike how namespaces 
work. Too many footguns that are too easy to misunderstand.  

But it is what it is, I guess. 

-Mike

Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-23 Thread Mike Schinkel
> On Aug 23, 2024, at 8:33 AM, Rowan Tommins [IMSoP]  
> wrote:
> On 23 August 2024 13:04:22 BST, Mike Schinkel  wrote:
>> And how can it occur without an explicit `use 
>> AcmeComponents\SplineReticulator\Utilities\Text\Text` statement, which I 
>> proposed would override the automatic `use`, anyway?
> 
> I'm not sure what you mean. Right now, that's the function name that would be 
> looked up for your example code (other than a couple of unrelated typos in 
> your example). So if, for some reason, someone was relying on that, their 
> code would break with your "automatic use".

I must be missing something.  Can you give a specific example showing how the 
automatic use would conflict with something other than a root namespace?

>> The only one of those that has a strong analog to existing PHP code is to 
>> "use the end of the current namespace" as people frequently do with explicit 
>> `use` statements.
> 
> True. I just don't love the context-sensitive nature of it.

Well, we frequently see things differently, which is what it is. 

Myself, I like the explicit nature of it that allows seeing at a glance that it 
is Text without having to look up through a long PHP file to find the namespace 
statement.  But as my dad says, to each his own, I guess.

Besides, I think there may be some better solutions discussed on this thread 
besides our dueling qualification syntax.

>> Lastly, no comment on `\\`?
> 
> Ah, yes, I forgot to say: I'm not keen on that because in other contexts it 
> means exactly the opposite: it refers to the absolute root in a context where 
> a relative name would be assumed.
> 
> For example, \\domain\username and \\server\fileshare on Windows, or 
> //example.com/foo in a URL

Fair point.  But then treating built-ins differently than userland globals may 
be the way to go that has the least BC breakage over either of our two 
proposals here.  

That said, having an automatic `use` would be nice for those who want to use 
it, even if it is not required.

-Mike

Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-23 Thread Mike Schinkel



> On Aug 23, 2024, at 7:50 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Fri, 23 Aug 2024, at 12:29, Mike Schinkel wrote:
>> namespace \AcmeComponents\SplineReticulator\Utilities\Text
>> 
>> function Foo():int {
>>  return Text\strlen("Hello World");
>> }
>> 
>> The above of course could result in BC breaks IF there happened to be 
>> existing code that referenced Text\strlen() where Text was a top-level 
>> namespace
> 
> It wouldn't be a top-level namespace that would cause a conflict, but a 
> nested one: currently the above code resolves the function name as 
> "AcmeComponents\SplineReticulator\Utilities\Text\Text\strlen" (note the 
> "...\Text\Text\...").

How often does that really occur in the wild?  

And how can it occur without an explicit `use 
AcmeComponents\SplineReticulator\Utilities\Text\Text` statement, which I 
proposed would override the automatic `use`, anyway?

> It's an interesting suggestion, but I'm not totally sold on "use the end of 
> the current namespace" being easier to remember than "use this symbol or 
> keyword".
> 
> return namespace\strlen("Hello World"); # current syntax, rather long and 
> unclear
> return _\strlen("Hello World"); # short, but maybe a bit cryptic
> return Text\strlen("Hello World"); # variable length, relies on current 
> context
> return NS\strlen("Hello World"); # shortening of current keyword
> return self\strlen("Hello World"); # maybe confusing to reuse a keyword?
> return current\strlen("Hello World"); # clear, but a bit long

The only one of those that has a strong analog to existing PHP code is to "use 
the end of the current namespace" as people frequently do with explicit `use` 
statements.

Yes, `self` has a weak analog to `self::`, but none of the others even come 
close, IMO. And adding `self\` may have unintended to the language, some slight 
BC concerns, and/or downstream consequences for other projects  vs. a simple 
automatic `use`.

Lastly, no comment on `\\`?

-Mike

Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-23 Thread Mike Schinkel
> On Aug 23, 2024, at 4:08 AM, Nick Lockheart  wrote:
> A third option, which I haven't seen come up on the list yet, is that
> unqualified functions that are PHP built-ins are treated as global, and
> using a function having the same name as a built-in, in a namespace
> scope, requires a fully qualified name to override the built-in.
> 
> It seems that if someone is writing `array_key_exists()` or similar
> they probably mean the built-in function, and in the rare cases where
> they do mean `\foo\array_key_exists()`, they can write it explicitly.
> 
> Functions that are *not* on the built-in function list could default to
> the local namespace.

I was going back and forth on this.

On one hand it could be confusing for developers to learn when to use `\` and 
when not to.

OTOH, once they learn it would create a clear indication of which functions are 
userland code and which are standard library, and I this could have significant 
benefit for readability and maintainability.

Yet OTOH, this would create a bifurcation between userland and standard library 
that is encouraged in some languages and discouraged in others, i.e. the latter 
being the "keep the language as small as possible and then let the standard 
library be implemented in the language no differently than any code a user 
could write" type of languages.  

Yet OTOH still, PHP does not allow core functions to be implemented in 
userland, at least without monkey patching so the bifurcation already exists. 

Go, for example, has both. Most of the standard library is just Go code anyone 
could replace with their own, but a handful of functions are special and built 
into the language, e.g. append, new, close, etc.  Basically anything in 
lowercase that can be used globally without qualification is special. And after 
using Go, I think it is a great design as it reserves future enhancements 
without BC concerns.

In theory it would be nice to open up PHP to allow overriding core functions, 
but that could also open a Pandora's box, the kind that makes Ruby code so 
fragile. At least in Go you have to omit the standard lib import and use your 
own import to override a standard library package.

So in practice PHP may never change to allow core functions to be overridden 
and thus pining for that to block this idea would be a missed opportunity. 
(That said, PHP could allow a userland function to be "registered" to be called 
instead of the core function, and if that were allowed then Nick's proposal 
would cause no problems. Of course I doubt internals would ever bless that 
idea.)  

Anyway — in summary — I think Nick's 3rd option has wings. And along with 
automatic `use` statements for each namespace might just be the best possible 
solution.

-Mike

P.S. If PHP ever added a set of standard library functions written in PHP to 
the core distribution, they should rightly IMO need to be namespaced, per this 
proposal. But here I digress. I only mention in hopes to keep this specific 
dream alive for some future day.




Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-23 Thread Mike Schinkel
Hi Rowan,

> On Aug 23, 2024, at 2:39 AM, Rowan Tommins [IMSoP]  
> wrote:
> On 23 August 2024 00:15:19 BST, Mike Schinkel  wrote:
>> Having to prefix with a name like Foo, e.g. Foo\strlen() is FAR PREFERABLE 
>> to _\strlen() because at least it provides satiating information rather than 
>> the empty calories of a cryptic shorthand.  #jmtcw, anyway.
> 
> I knew I'd regret keeping the example short. Realistically, it's not a 
> substitute for "\Foo\strlen", it's a substitute for 
> "\AcmeComponents\SplineReticulator\Utilities\Text\strlen".

And similarly, I too regret keeping my answer short. I was assuming what I 
omitted would be obvious. 

(And I am not being snarky, I literally thought about including this next but 
then felt I did not need to. Hindsight!)

So, long namespaces is why PHP has the `use` statement, making references in 
functions short and sweet, e.g:

namespace \AcmeComponents\SplineReticulator\Utilities\Text
use \AcmeComponents\SplineReticulator\Utilities\Text

function Foo():int {
return Text\strlen("Hello World");
}

(Of course, that is a lot of redundant boilerplate.)

> Another option would be to find a shorter keyword than "namespace" to put it 
> in front. "ns\strlen(...)" is an obvious step from what we have currently, 
> but it's not very obvious what it means, so maybe there's a different word we 
> could use.

So rather than all that boilerplate, and rather than yet another special set of 
characters developers would need to learn and remember — and tooling would need 
to adjust to — we could instead easily add an automatic `use` statement for 
every namespace, as long as no existing use statement conflicts with it. 

An automatic `use` would then give us the following, which provides a strong 
information sent and is really consistent with the nature of the PHP language:

namespace \AcmeComponents\SplineReticulator\Utilities\Text

function Foo():int {
return Text\strlen("Hello World");
}

The above of course could result in BC breaks IF there happened to be existing 
code that referenced Text\strlen() where Text was a top-level namespace, AND 
that code was not remediated when this change takes place. However, I am 
guessing those collisions would be pretty rare as both the namespace and the 
symbol would have to match to be in conflict.

> Having a syntax for "relative to current" is incredibly common in other 
> path-like syntaxes. The most common marker is ".", and ".\foo" is literally 
> how you'd refer to something in the current directory under DOS/Windows. But 
> unfortunately, we don't have "." available, so I wondered if "_" would feel 
> similar enough.

I'll be honest, the association with the relative path of `.\` did not occur to 
me when you presented `_\` so after you stating this I pondered if from that 
perspective. 

However, frankly, I am not sold on that perspective. Something about it does 
not feel right. I can't currently give any more objective arguments than that, 
so I will just leave it as #jmctw.

I will say if we were going with relative path, I think `\\strlen()` would be 
preferable to `_\strlen()`. Subjectively `\\` is easier for me to "see" and 
thus does not look so out of place to me. 

OTOH the objective arguments for `\\` over `_\` are it is much easier to type:  
slash+slash vs. shift-underscore+nonshift-slash. There is a precedent in URIs 
with `//`, albeit not exactly equivalent. And finally, it also does not use a 
sigil that could be better used elsewhere in some as-yet-to be agreed or 
envisioned future use. #fwiw

-Mike

Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local)

2024-08-22 Thread Mike Schinkel
> On Aug 22, 2024, at 5:32 PM, Rowan Tommins [IMSoP]  
> wrote:
> I was thinking about this earlier, and how the migration is pretty much the 
> same (and equally automatable) in either direction:
> 
> * If unqualified calls become always local, then every global function call 
> needs a use statement or prefixing with "\".
> * If they become always global, then every local function call needs a use 
> statement or prefixing with "namespace\".
> 
> But the first option probably requires changes in the majority of PHP files 
> in use anywhere; whereas the second only affects a small minority of code 
> bases, and a small minority of code in those.
> 
> BUT, if people already complain about "\" being ugly, having to write 
> "namespace\" is going to make them REALLY grumpy...
> 
> So maybe at the same time (or, probably, in advance) we need to come up with 
> a nicer syntax for explicitly referencing the current namespace.
> 
> Unfortunately, finding unused syntax is hard, which is why we have "\" in the 
> first place (and for the record, I think it works just fine), but maybe 
> something like "_\" could work? Giving us:
> 
> namespace Foo;
> 
> $native_length = strlen('hello'); # same as \strlen('hello')
> $foo_length = _\strlen('hello'); #  same as \Foo\strlen('hello')
> 
If having to type `\strlen()` is ugly — and I agree that is it — then having to 
type `_\strlen()` is what in university we would call "fugly," to emphasize 
just how much worse something was vs. just run-of-the-mill "ugly."

Having to prefix with a name like Foo, e.g. Foo\strlen() is FAR PREFERABLE to 
_\strlen() because at least it provides satiating information rather than the 
empty calories of a cryptic shorthand.  #jmtcw, anyway.

> If I had a time machine, I'd campaign for "unqualified means local" in PHP 
> 5.3, and we'd all be used to writing "\strlen" by now; but "unqualified means 
> global" feels much more achievable from where we are.
> 
If I had a time machine I would campaign for real packages instead of what 
namespaces turned out to me, and that used sigils that do not double as the 
escape character for strings, but then both of us digress. 

-Mike

Re: [PHP-DEV] State of Generics and Collections

2024-08-21 Thread Mike Schinkel
> On Aug 20, 2024, at 9:44 AM, Arnaud Le Blanc  wrote:
> 
> Hi Mike,
> 
> On Tue, Aug 20, 2024 at 2:45 AM Mike Schinkel  wrote:
>> It seems Java-style Generics are viewed as the proper archetype for Generics 
>> in PHP?  I would challenge the wisdom of taking that road considering how 
>> different the compilers and runtimes are between the Java and PHP.  PHP 
>> should seek out solutions that are a perfect fit for its nature and not 
>> pursue parity with Java.
> 
>> As PHP is primarily a web development language — vs. a systems language like 
>> C or Rust, or an enterprise application language like Java or C# — reducing 
>> code complexity for reading and understanding is a very important attribute 
>> of the language.
> 
>> PHP is also a unique language and novel solutions benefit a unique language. 
>> PHP should pursue solutions that result in less complex code even if not 
>> found in other languages. Your collections idea is novel — which is great — 
>> but there are probably even more novel solutions to address other needs vs. 
>> going full-on with Java-style generics.
> 
>> Consider if adding type aliases; or augmenting, enhancing, or even merging 
>> classes, interfaces, and/or traits to address the needs Java-style generics 
>> would otherwise provide. I would work on some examples but I think you are 
>> more likely to adopt the features you come up with on your own.
> 
> Part of the appeal for Java/C#/Kotlin-like generics is that they are
> well understood and their usefulness is not to be proven. 

Yes, they are well understood by programmers who develop in a significantly 
more complex language. So while I acknowledge that appeal, I think the 
complexity provides benefit for most PHP developers.

> Also they fit well with the object-oriented aspect of the language, 

Even more importantly, PHP is not Java and what works for a compiled and 
strongly typed language does not necessarily work for a interpreted language 
with looser typing and where only one file can be seen by the compiler at a 
time.

> and many PHP projects already use them via PHPStan/Psalm.

As an aside, it is an interesting data point that such as small percent of PHP 
developers actually use those tools. 

Could it be because of their complexity? I cannot say for certain that is why, 
but it surely is a factor to ponder.

> More experimental alternatives would be more risky.

Fair point

> I would be interested to see suggestions or examples, however.

Two examples were already shown and/or mentioned: the collections class and 
automatic interface implementation based on structural typing.  

I am sure they are more, and if I am able to identify any as the topic is 
discussed I will bring them up.

>> As for type-erasure, I am on the fence, but I find the proposed "how" 
>> problematic.
>> I can see wanting some code to be type-checked and other code not, but I 
>> think more often developers would want code type-checked during development 
>> and testing but not for staging or production. And if the switch for that 
>> behavior is in every file that means modifying every file during deployment. 
>> IMO that is just a non-starter.
> 
> The reason for this "how" is that type checking is also coercing, so
> disabling it "from the outside" may break a program that's not
> designed for that.

AFAIK if you are using type checking then the code is never correct if the 
types do not match, the errors just may go unreported. Thus I do not see how 
the code that uses code with types could not be designed for code with types; 
disabling if from the outside does not change that. 

Disabling type checking is not like changing the syntax that is allowed by 
strict mode, AFAIK.

> type checking is also coercing


However, I do not understand your claim here. Is there some form of typing that 
would modify code behavior if the types were erased? Would allowing that even 
make sense? Can you give an example of this?

> That's why this is something that should be enabled
> on a per-file basis, and can probably not be switched on/off depending
> on the environment.

I reserve my opinion on this awaiting your example(s).

>> P.S. Also consider offering the ability for a function or class method to 
>> "type" a parameter or variable based on an interface and then allow values 
>> that satisfy that interface structurally[1] but not necessarily require the 
>> class to explicitly implement the interface.
> 
> Unfortunately, I believe that structural types would be very expensive
> to implement at runtime. Static analysers could support this, however
> (PHPStan/Psalm support some structural types already).

But would it really be too expensive? Has anyone ever pursued considering it, 
or just dismissed it summarily? Seems to me it could handled rather 
inexpensively with bitmaps.

-Mike


Re: [PHP-DEV] State of Generics and Collections

2024-08-19 Thread Mike Schinkel
> On Aug 19, 2024, at 7:37 PM, Rob Landers  wrote:
> As an experiment, awhile ago, I went a different route for reified generics 
> by 'hacking' type aliases (which I was also experimenting with). Such that a 
> generic becomes compiled into a concrete implementation with a dangling type 
> alias:
> 
> class Box {
>   function __construct(T $thing) {}
> }
> 
> is essentially compiled to
> 
> class Box {
>   use alias __Box_T => ???;
> 
>   function __construct(__Box_T $thing) {}
> }
> 
> This just gets a T type alias (empty-ish, with a mangled name) that gets 
> filled in during runtime (every instance gets its own type alias table, and 
> uses that along with the file alias table). There shouldn't be any 
> performance impact this way (or at least, as bad as using type aliases, in 
> general; which is also an oft-requested feature).

From what I understand this is essentially how Go implements Generics.  So +1 
for considering this approach.

> FYI though, people seemed really turned off by file-level type aliases (at 
> least exposed to user-land, so I never actually pursued it).

Shame. Type aliases are super useful in practice in other languages, with many 
used for single-file scope in my experience.

-Mike

Re: [PHP-DEV] State of Generics and Collections

2024-08-19 Thread Mike Schinkel
> On Aug 19, 2024, at 1: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

Great job on providing so much detail in your blog post.

JMTCW, but I am less of a fan of boil-the-ocean generics and more of a fan of 
focused pragmatic solutions like you proposed with the Collection types.  The 
former can result in really complex to read and understand code  whereas the 
latter — when done well — results in easier to read and understand code.
 
It seems Java-style Generics are viewed as the proper archetype for Generics in 
PHP?  I would challenge the wisdom of taking that road considering how 
different the compilers and runtimes are between the Java and PHP.  PHP should 
seek out solutions that are a perfect fit for its nature and not pursue parity 
with Java.  

As PHP is primarily a web development language — vs. a systems language like C 
or Rust, or an enterprise application language like Java or C# — reducing code 
complexity for reading and understanding is a very important attribute of the 
language.

PHP is also a unique language and novel solutions benefit a unique language. 
PHP should pursue solutions that result in less complex code even if not found 
in other languages. Your collections idea is novel — which is great — but there 
are probably even more novel solutions to address other needs vs. going full-on 
with Java-style generics. 

Consider if adding type aliases; or augmenting, enhancing, or even merging 
classes, interfaces, and/or traits to address the needs Java-style generics 
would otherwise provide. I would work on some examples but I think you are more 
likely to adopt the features you come up with on your own.



As for type-erasure, I am on the fence, but I find the proposed "how" 
problematic. I can see wanting some code to be type-checked and other code not, 
but I think more often developers would want code type-checked during 
development and testing but not for staging or production. And if the switch 
for that behavior is in every file that means modifying every file during 
deployment. IMO that is just a non-starter.

If you are going to pursue  type-erasure I recommend introducing a file in the 
root — call it `.php.config` or similar — that contains a wildcard enabled 
tree-map of code with attributes settable for each file, directory, group of 
files and/or group of directories where one attribute is type-checked or other 
attributes are reserved for future use. This config file should also be able to 
delegate the `.php.config` files found elsewhere, such as config files for each 
package in the vendor directory. It would be much better and easier to swap out 
a few `.php.config` files during CI/CD than to update all files.

Additionally PHP could use an environment variable as prescribed by 12 Factor 
apps to identify the root config file. That way a hosting company could allow 
someone to configure their production server to point to 
`.php.production.config` instead of ``.php.development.config`. 

-Mike

P.S. Also consider offering the ability for a function or class method to 
"type" a parameter or variable based on an interface and then allow values that 
satisfy that interface structurally[1] but not necessarily require the class to 
explicitly implement the interface. 

This is much like how `Stringable` is just automatically implemented by any 
class that has a `__ToString()` method, but making this automatic 
implementation available to userland. Then these automatically-declared 
interfaces can cover some of the use-cases for generics without the complexity 
of generics.

For example — to allow you to visualize — consider a `Printable` interface that 
defines a `print()void` method. If some PHP library has a class `Foo` and it 
has a method with signature `print()void` then we could write a function to use 
it, maybe like so:

-
interface Printable {
   print($x any)void
}

// The prefix `?` on `Printable` means `$printer` just has to match the 
`Printable` interface's signature
function doSomething($printer ?Printable) { 
   $printer->print()
}

$foo = new Foo();
doSomething($foo);
-

Something to consider?  

[1] https://en.wikipedia.org/wiki/Structural_type_system


Re: [PHP-DEV] Should there be a `get_declared_enums()` function ?

2024-08-18 Thread Mike Schinkel
> On Aug 18, 2024, at 4:59 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On 18 August 2024 05:46:09 BST, Mike Schinkel  wrote:
>> I know that those functions can be called as a function and return a value 
>> like the following:
>> 
>> $return_value = include($path);
> 
> You are right that it has a return value, but wrong to put its argument in 
> parentheses. This will *not* do what you expect: 
> 
> $success = include($path) && somethingElse();
> 
> Because include is not actually a function, what is evaluated is `$path && 
> somethingElse()`, then either `include true` or `include false` (which will 
> of course fail).
> 
> You instead need to write this: 
> 
> $success = (include $path) && somethingElse();
> 
> I thought I'd added this example to the manual, but now can't find it.
> 
> Consequently, we can't just define optional parameters like we would a normal 
> function. We *could* extend the syntax to allow "include $path, $whatever;" 
> but it probably wouldn't feel very natural. It would be a syntax error to 
> write "include($path, $whatever)" just as "echo $foo, $bar" is valid, but 
> "echo($foo, $bar)" is not.
Hi Rowan,

Thank you for confirming the nature of include, et. al.

So, if the functionality to be notified via a callback for all symbols loaded 
is a desired feature by other than me and maybe Juliette then the best approach 
I've come up with is to add an `spl_autoload_callback()` function that can both 
get and set the callback to be called after include or its 3 other friends are 
called.  Anyone (else?) disagree?

-Mike

Re: [PHP-DEV] Should there be a `get_declared_enums()` function ?

2024-08-17 Thread Mike Schinkel
> On Aug 17, 2024, at 1:36 AM, Juliette Reinders Folmer 
>  wrote:
>> What if instead PHP were to implement an optional 2nd callback parameter to 
>> `include()` / `require()` / `include_once()` / `require_once()` to allow us 
>> to capture the symbols loaded and their paths? The callback function could 
>> return `void` and accept an array of `$symbols` with the following 
>> guaranteed minimum structure?
>> 
>> $symbols = array(
>>'classes' => [],
>>'interfaces' => [],
>>'traits' => [],
>>'enums' => [],
>> );
>> 
> Except `include()` and friends aren't function calls, but language 
> constructs/expressions and don't take parameters as such, so I don't see how 
> that would be possible without changing `include()` and friends to function 
> calls (along the lines of what happened for `exit` in PHP 8.4 with 
> non-parenthesized use still possible to mitigate the otherwise huge breaking 
> change),

I know that those functions can be called as a function and return a value like 
the following:

$return_value = include($path);

I was making an assumption that since they be called like a function they could 
also accept optional parameters, although I admittedly was only assuming and do 
not know for sure.  Do you know for a fact that they cannot take a 2nd 
parameter, or just assuming like I was?   

Does anyone else know for certain it is would be possible for `include()` 
et.al. to accept an optional 2nd parameter?

However, even if a 2nd parameter is not a viable option then this could be 
addressed by instead adding  a single new function with a signature of 
`spl_autoload_callback($fn callback):callback` where the callback has a 
signature of `function ($symbols array)` which could be used like so:

function loadFile($path)
{
   if (strpos(__DIR__, 'phar://') !== 0) {
 $path = realpath($path);
 if ($path === false) {
   return false;
 }
   }
   if (isset(self::$loadedClasses[$path]) === true) {
 return self::$loadedClasses[$path];
   }
   $prior_callback = spl_autoload_callback(function($symbols) use ($path) {
 foreach ($symbols['classes'] as $className) {
   self::$loadedClasses[$path]= $className;
   self::$loadedFiles[$className] = $path;
 }
   });
   include($path);
   spl_autoload_callback($prior_callback);
   return self::$loadedClasses[$path];
}

>> This approach would be a less disruptive than my prior suggestion
> Not so sure about that considering the above ;-)

Well then I think a single new function would be very low on the disruption 
scale, no?

> This probably needs some more bike shedding ;-)

Shedding of bike undertaken. :-)

-Mike


Re: [PHP-DEV] Should there be a `get_declared_enums()` function ?

2024-08-16 Thread Mike Schinkel
Hi Juliette,

> On Aug 16, 2024, at 9:25 PM, Juliette Reinders Folmer 
>  wrote:
> 
> On 17-8-2024 2:00, Mike Schinkel wrote:
>> To everyone on this thread and thus nobody in specific (hence my top post):
>> 
>> Given that get_declared_*() populates a new ZEND_HASH each time the function 
>> is called[1] — which for classes can easily be hundreds of strings — would 
>> there be any appetite to: 
>> 
>> 1. Add an optional parameter — e.g. `get_declared_classes($startingFrom)` — 
>> that can limit the number of symbols starting with "n"  where if n==100 then 
>> it would return array_slice($symbols,100), and 
>> 
>> 2. Add a function — `get_declared_class_count()` — that returns the current 
>> number of declared symbols of whichever kind of symbol, so we can get the 
>> "n" before calling `include`/`require` to use with get_declared_*() after 
>> calling  `include`/`require`?
>> 
>> 
>> This would cut down on creating hashes with 100+ strings that get 
>> immediately thrown away, and also cut down on memory fragmentation/garbage 
>> collector churn. 
>> 
>> -Mike
>> 
>> [1] 
>> https://github.com/php/php-src/blob/18d41502da0da1bb3928e60c41f1b821974c2c01/Zend/zend_builtin_functions.c#L1371
> 
> Mike,
> 
> While your suggestion does not directly relate to what triggered my mail to 
> the list, I very very much like the idea.

Excellent!

> It's as if you are reading my mind or rather, reading one of the autoloaders 
> [1] I need to maintain, in which your above outlined proposal should 
> definitely make for more efficiency.

Thank you for sharing that.  Yes, your use-case is very similar to mine. 

> Having said that, the same parameter + extra function would then also be 
> needed for `get_declared_interfaces()`, `get_declared_traits()` - and, if it 
> would be added, `get_declared_enums()`.

That was my assumption and intention, but I did not say so explicitly. I should 
have.

Thanks to Ayesh's excellent PR, I was able to recognize that all of those 
functions in-fact are implemented via one internal function 
`get_declared_class_impl()` so it only made sense — to me, at least — that 
modifying it would enable the same functionality for all four (4) userland 
functions.

> There is one problem I can see with this approach though: since PHP 7.4, the 
> return value of `get_declared_classes()` (and friends) does not guarantee any 
> particular order anymore [2].
> So, an `array_slice($symbols, $n)` may not get you the _latest_ classes 
> loaded, so I think this would only work if the order of classes is guaranteed 
> in some way.

That is a super relevant insight and one I was actually not aware of.

Do you happen to know if it was triggered by an explicit RFC to that effect, or 
if it resulted because of a side-effect of some other implementation change?  
From my perspective, that is definitely a BC break and one that I am surprised 
I never noticed before?  Do you also know if it is a case of "not guaranteed, 
but in-fact actual fact it always works that way, or not?"  

I have not used my lib that needs that functionality to work in a few years, so 
maybe it is broken now and those who are now maintaining those apps have had to 
deal with it?

Given that you see value in the same use-case I had which was an autoloader, 
maybe it would be better to achieve the functionality we need in a different, 
more efficient way?  

What if instead PHP were to implement an optional 2nd callback parameter to 
`include()` / `require()` / `include_once()` / `require_once()` to allow us to 
capture the symbols loaded and their paths? The callback function could return 
`void` and accept an array of `$symbols` with the following guaranteed minimum 
structure?

$symbols = array(
   'classes' => [],
   'interfaces' => [],
   'traits' => [],
   'enums' => [],
);

With that you could reimplement all that PHP code you linked — at least for 
versions of PHP supporting the callback — to look like this:

function loadFile($path)
{
   if (strpos(__DIR__, 'phar://') !== 0) {
 $path = realpath($path);
 if ($path === false) {
   return false;
 }
   }
   if (isset(self::$loadedClasses[$path]) === true) {
 return self::$loadedClasses[$path];
   }
   include($path, function($symbols) use ($path) {
 foreach ($symbols['classes'] as $className) {
   self::$loadedClasses[$path]= $className;
   self::$loadedFiles[$className] = $path;
 }
   });
   return self::$loadedClasses[$path];
}//end loadFile()

This approach would be a less disruptive than my prior suggestion which would 
have added four (4) new `*_count()` functions and new optional parameters for 
four (4) existing function vs

Re: [PHP-DEV][Discussion] Should All String Functions Become Multi-Byte Safe?

2024-08-16 Thread Mike Schinkel
> On Aug 16, 2024, at 8:02 PM, Rowan Tommins [IMSoP]  
> wrote:
> On 17 August 2024 00:25:13 BST, Mike Schinkel  wrote:
>> I am not sure I agree with you that adding Unicode support is the wrong 
>> angle, per se. 
>> 
>> A strong argument could be made that Unicode support is a necessary but not 
>> sufficient building block for "internationalization support."  IOW, if you 
>> want to get to the latter it is probably a lot easier to start with the 
>> former as the scope of the latter is by-nature larger. After all, perfect is 
>> the enemy of the good and waiting for a full-press effort for 
>> internationalization support could well push off Unicode support long down 
>> the road.
> 
> Again, that's not really what I intended to say, but I'm probably not 
> expressing myself clearly.
> 
> I was thinking about the way we frame the conversation, the words we focus 
> on, and how that shapes the conversation.
> 
> The example that keeps coming to mind is password_hash/password_verify. It 
> seems to me that for years, the conversation was framed around 
> "cryptographically safe hashing functions", and teaching users why and how to 
> use powerful but confusing functions like hash() and crypt(). Then it got 
> reframed from the point of view of a web developer wanting to implement 
> logins, and we ended up with fantastically easy to use functions. 
> 
> In the same way, I think "Unicode support" should be the awkward background 
> work that we do *because we're trying to solve specific problems involving 
> text*. 
> 
> In the case of this thread, I think the actual user story is "I want to allow 
> users to enter a wide range of characters, but restrict them in contextually 
> appropriate ways to ensure various types of safety and security". The 
> implementation of that involves a lot of technicalities about how Unicode 
> works, but ideally we want to find meaningful abstractions of those 
> technicalities, not just require every user to understand them.

We are in no real disagreement there.

-Mike

P.S. I do think we could reach the same end-goal by taking either direction 
since Unicode support is a building block of solving specific problems 
involving text, and thus needs to happen either way.

But, as I implied earlier, whichever road takes us there works for me so no 
need for me to further bikeshed it, as long as the road we take will not result 
in a dead-end.

Re: [PHP-DEV] Should there be a `get_declared_enums()` function ?

2024-08-16 Thread Mike Schinkel
To everyone on this thread and thus nobody in specific (hence my top post):

Given that get_declared_*() populates a new ZEND_HASH each time the function is 
called[1] — which for classes can easily be hundreds of strings — would there 
be any appetite to: 

1. Add an optional parameter — e.g. `get_declared_classes($startingFrom)` — 
that can limit the number of symbols starting with "n"  where if n==100 then it 
would return array_slice($symbols,100), and 

2. Add a function — `get_declared_class_count()` — that returns the current 
number of declared symbols of whichever kind of symbol, so we can get the "n" 
before calling `include`/`require` to use with get_declared_*() after calling  
`include`/`require`?

Used in a (very simplistic) example:

function autoload($class) {
   $startingFrom = get_declared_class_count();
   if (!file_exists("src/{$class}.php")) {
 return;
   }
   include_once "src/{$class}.php";
   foreach (get_declared_classes($startingFrom) as $class) {
 if (!method_exists($class,'init')) {
   continue;
 }
 $class::init();
   }
}

This would cut down on creating hashes with 100+ strings that get immediately 
thrown away, and also cut down on memory fragmentation/garbage collector churn. 

-Mike

[1] 
https://github.com/php/php-src/blob/18d41502da0da1bb3928e60c41f1b821974c2c01/Zend/zend_builtin_functions.c#L1371


> On Aug 16, 2024, at 7:13 AM, Christoph M. Becker  wrote:
> 
> On 15.08.2024 at 03:51, Juliette Reinders Folmer wrote:
> 
>> Should a `get_declared_enums()` function be added ?
> 
> Here we go:
> 
>function get_declared_enums() {
>$enums = [];
>$exts = get_loaded_extensions(false);
>foreach ($exts as $ext) {
>$re = new ReflectionExtension($ext);
>$classes = $re->getClasses();
>foreach ($classes as $class) {
>if ($class->isEnum()) {
>$enums[] = $class->name;
>}
>}
>}
>return $enums;
>}
> 
> Porting this to C is left as an excercise for the reader. ;)  Hint:
> 
> 
> Note that the terminating folding marker is backwards.
> 
>> And should the `get_declared_classes()` function be adjusted to exclude
>> enums ?
> 
> For reasons that have been stated elsewhere in this thread, I don't
> think so.
> 
> Cheers,
> Christoph


Re: [PHP-DEV][Discussion] Should All String Functions Become Multi-Byte Safe?

2024-08-16 Thread Mike Schinkel
Hi Nick,

> On Aug 16, 2024, at 6:11 PM, Nick Lockheart  wrote:
> 
> I wanted to reply generally to this and not to any person in
> particular, as I'm the one who started the thread.
> 
> I used the rather broad title "Should All String Functions Become
> Multi-Byte Safe" because there are many smaller related topics, but my
> intention was to discuss multi-byte in general, and see if there was
> some consensus on action items that could have a more limited scope/RFC
> for that task.
> 
> My overall intent and goal was to make PHP safer against multi-byte
> attacks by providing developers with tools that could become best
> practices for dealing with user input stings, the same way we had
> mysql_real_escape_string, and then PDO prepared statements for SQL.
> 
> There's a lot of potential pitfalls for dealing with Unicode input, and
> there are some best practices per the Unicode Consortium that I'm not
> sure how to implement in PHP, and it seems that since everyone needs
> them, they might be better as a shared library in core.
> 
> For example, there should be a function that removes unassigned code
> points.
> 
> There should also be a function that removes "scripts" (as defined by
> Unicode).
> 
> We should have an easy way to remove private use code points (unless
> you're running a Star Trek fan site and really do need Klingon).
> 
> And the default replacement character for `mb_scrub` shouldn't be `?`.
> 
> Each of these and other ideas could be part of an RFC, or we could
> brainstorm a Unicode built-in class that handles lots of the common use
> cases.
> 
> Having a team-built and audited Unicode class would benefit almost
> everyone using PHP.

My suggestion — take it or leave it — is to create a GitHub repo for your own 
RFCs and start writing your RFC there "in the open." Add the code for your 
implementation to the repo, add a discussion forum to allow really interested 
parties to participate, and send an invite on this list to those who are really 
interested to discuss, comment on the RFC, and even offer PRs. 

Then when everyone participating at your repo thinks the RFC is fully-baked, 
bring it back to the list here to discuss.  

Doing it that way will — unlike just discussing on the list — enable comments 
made in the forum a place to be captured and converted into text and 
implementation visible for everyone to see, and really motivated people can 
even submit PRs to your RFC in order to spread the load of writing a good RFC. 

#jmtcw #fwiw

-Mike

Re: [PHP-DEV][Discussion] Should All String Functions Become Multi-Byte Safe?

2024-08-16 Thread Mike Schinkel
> On Aug 16, 2024, at 3:36 PM, Rowan Tommins [IMSoP]  
> wrote:
> On 16 August 2024 19:44:22 BST, Mike Schinkel  wrote:
>> Let me see if I understand your argument correctly?  You are asserting that 
>> Unicode is "too complex" to be handled in the standard library so that 
>> complexity should instead be shouldered individually by each and every PHP 
>> developer who needs to work with Unicode text in PHP, which is many PHP 
>> developers if not eventually most. Is that your argument?
> 
> 
> Not really, no. I'm definitely in favour of including more Unicode-based 
> string handling functionality, by improving and extending ext/intl, or coming 
> up with new convenience wrappers for common tasks. 

Your prior reply came across to me as a closed-end slamming-the-door on the 
topic because of "what we can't do," which is why I commented on.

This most recent reply OTOH was an example of exploring "what we can do" to 
improve PHP. So kudos for this reply; big plus.

> What I'm always sceptical of is the idea that you could ever consider such 
> functionality "complete", or that "Unicode support" can ever be a single 
> deliverable, rather than an ongoing aspiration. (And consequently, I'm 
> sceptical of any language which says it has achieved that.)

To be clear I don't think anything can ever be considered "complete" unless you 
are talking something as limited in scope as numeric addition. And even then, 
supporting imaginary numbers might arise.  

So while it is not a problem to be explicit about it even if redundant, having 
it be an underlying reason to argue against useful functionality — if it is 
ever used in that way — seems counter-productive. Nothing precludes a follow-up 
RFC after an initially successful RFC is implemented and shipped.

> I also think "Unicode support" is probably the wrong angle to approach from; 
> it leads to features like IntlChar, which technically provides access to tons 
> of data from the Unicode standard, but practically has no use for 99% of PHP 
> developers. Instead we should be talking about "internationalisation 
> support", of which handling different writing systems is one (fairly big) 
> part.

I am not sure I agree with you that adding Unicode support is the wrong angle, 
per se. 

A strong argument could be made that Unicode support is a necessary but not 
sufficient building block for "internationalization support."  IOW, if you want 
to get to the latter it is probably a lot easier to start with the former as 
the scope of the latter is by-nature larger. After all, perfect is the enemy of 
the good and waiting for a full-press effort for internationalization support 
could well push off Unicode support long down the road.

Still, *if* "full" internationalization support can be achieved in the shorter 
term it would be bikeshedding for me to argue against it.

-Mike


Re: [PHP-DEV][Discussion] Should All String Functions Become Multi-Byte Safe?

2024-08-16 Thread Mike Schinkel
> On Aug 12, 2024, at 4:25 PM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On 12/08/2024 17:37, Mike Schinkel wrote:
>> A really standout paragraph from that link is:
>> 
>> "IMO, the whole situation is a shame. Unicode should be
>> in the stdlib of every language by default. It’s the lingua
>> franca of the internet! It’s not even new: we’ve been living
>> with Unicode for 20 years now."
> 
> I actually think that paragraph rather ignores everything else the article 
> has just explained.

You and I had different takeaways then.

> and it's not entirely clear what it should even mean.

I cannot speak for the author off the article, but I thought I had implied 
strongly enough what it would mean to me. Evidently I did not, so I will be 
explicit:

Pursue this RFC:  https://wiki.php.net/rfc/unicode_text_processing 
<https://wiki.php.net/rfc/unicode_text_processing>

> The main reason it's not *mandatory* for all builds of PHP, just "bundled", 
> is that the sheer complexity of Unicode means that the library is rather 
> large 

Let me see if I understand your argument correctly?  You are asserting that 
Unicode is "too complex" to be handled in the standard library so that 
complexity should instead be shouldered individually by each and every PHP 
developer who needs to work with Unicode text in PHP, which is many PHP 
developers if not eventually most. Is that your argument?

Imagine if PHP had taken the position that "It is too complex, so we'll just 
make userland developers deal with it" regarding cryptography and encryption? 
Or regular expressions?  Or image processing?  Or time and date manipulation? 
Or network and socket programming?

> "Putting Unicode in the stdlib" is an incredibly difficult task, and it's not 
> entirely clear what it should even mean.
> ...
> somebody (Rasmus, I think?) joked that relying on it for PHP 6 would have 
> made PHP a small library attached to the side of ICU.

You are comparing apples and oranges. 

Putting Unicode into an existing *language* and integrating with built-in data 
types in a backward compatible manner is a MUCH bigger lift than "putting 
Unicode into a standard library." The latter is just providing functions and/or 
an object and methods for the majority of tasks needed to process Unicode text. 

PHP already has some functions for Unicode in the standard library as have been 
mentioned, but not enough to reasonably handle most Unicode text-related tasks. 
A Unicode text processing class with the existing RFC as a starting point could 
unify that functionality and fill in the missing gaps.

BTW, I have done a significant amount of work with Unicode in Go — which 
handles code points natively, but unfortunately not grafemes — and handling 
Unicode effectively is not *that* hard. The rules are many, but they are 
straightforward. Certainly it is not harder than cryptography and encryption, 
which PHP addresses in core.

> We also have the "mbstring" extension, which was *not* designed around 
> Unicode, but was originally built for various encodings popular in Japan 20+ 
> years ago. It doesn't have the databases of codepoint information that ICU 
> does, so can't answer questions like "what script does this code point belong 
> to?" or "what is the uppercase equivalent of this grapheme, assuming a 
> Turkish locale?"

Interesting historical factoid, but how is that really relevant to including 
Unicode into the standard library?

-Mike

Re: [PHP-DEV] [DISCUSSION] Class Constant Enums?

2024-08-15 Thread Mike Schinkel
> On Aug 15, 2024, at 9:37 PM, Nick Lockheart  wrote:
> 
> Hi,
> 
> 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.
> 
> When dealing with state, it's nice to have a human readable const to
> represent that state, but I always feel like they should be grouped
> together.

Yes, I would very much like that.

-Mike
P.S. See related: https://externals.io/message/107995 





Re: [PHP-DEV] Should there be a `get_declared_enums()` function ?

2024-08-15 Thread Mike Schinkel


> On Wed, Aug 14, 2024, at 8:51 PM, Juliette Reinders Folmer wrote:
> Should a `get_declared_enums()` function be added ?

My answer is "very much, yes."

> On Aug 15, 2024, at 9:09 AM, Larry Garfield  wrote:
> Context: I can't remember the last time I used get_declared_classes() 
> (...it's a kinda pointless function)

Your experience is one data point. Another data point is my experience that it 
is fortunate that `get_declared_classes()` exists as I find it to be a very a 
useful function. The core library I use for most projects depends on it for 
class initialization. 

Your comment made me curious to see if others use it, and there are 8.1k uses 
on GitHub: 

- https://github.com/search?q=language%3Aphp+get_declared_classes&type=code

Here is how I have used, in a greatly simplified example:

function autoload($class) {
   $classCount = count(get_declared_classes());
   if (!file_exists("src/{$class}.php")) {
 return;
   }
   include_once "src/{$class}.php";
   foreach (get_declared_classes() as $class) {
 if (!method_exists($class,'init')) {
   continue;
 }
 $class::init();
   }
}

As an aside, for this use-case I have always wanted PHP to add both 1.) a 
`get_declared_class_count()` function and 2) optional parameters for 
`get_declared_classes()` that would allow requesting a subset of classes, such 
as just the newly added classes. How important this is depends on if PHP 
maintains that array internally and just returns a reference, or if it 
instantiates memory and populates the array of classes to return every time the 
function is called.

> , 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).

Add another parameter — or include as part of the args array — something like 
this (though I am sure this could be bikeshed to be better):

get_declared_classes(DeclaredClasses:ONLY_CLASSES, ['starting_from'=>174]);
get_declared_classes(DeclaredClasses:ALL, ['recently_declared'=>3]);

Or even:

DeclaredSymbols::get_classes([$args])  <-- returns only classes, not enums
DeclaredSymbols::get_enums([$args])
DeclaredSymbols::get_interfaces([$args])
DeclaredSymbols::get_traits([$args])
#fwiw

> On Aug 16, 2024, at 12:23 AM, Juliette Reinders Folmer 
>  wrote:
> Thanks for the response. It was exactly a (custom) autoloader situation which 
> caused me to start wondering about this.

Seems Juliette's use-case may be at least somewhat similar to mine.

-Mike

Re: [PHP-DEV] [DISCUSSION] C++ Enhancements in Zend API

2024-08-14 Thread Mike Schinkel
> On Aug 14, 2024, at 5:27 PM, Lanre  wrote:
> 
>> On Wed, Aug 14, 2024 at 2:32 PM Mike Schinkel  wrote:
>> > On Aug 14, 2024, at 3:05 PM, Arvids Godjuks  
>> > wrote:
>> > PHP has C as core and has allowed C++ for extensions. Expanding that 
>> > support is a no-brainer, especially since modern C++ has stepped up in 
>> > major ways and I don't think C sees a lot of development any more, so it 
>> > makes sense to move towards C++.
>> 
>> IF there is a serious consideration given to evolving PHP to be written in 
>> another language — vs. just a newer version of C — I think any reasonable 
>> analysis would indicate that none of the languages proposed in this thread 
>> would be appropriate; not Rust, not C++, and not Go.  Why not?
> Can you point out where either of us suggested writing PHP in another 
> language?

Arvids wrote "I don't think C sees a lot of development any more, so it makes 
sense to move towards C++." 

That statement was why I wrote my email.

> You might be mixing this up with the C11 thread, which has nothing to do with 
> this. 

No, not the case.

> All I'm proposing is improving the current C++ support in the engine. 

I was not replying to your email(s). I was replying to Arvids' email which was 
worded as if moving to C++ for PHP was a foregone conclusion.

> https://github.com/php/php-src/blob/master/Zend/zend_portability.h already 
> guarantees compatibility with c++ thanks to the BEGIN_EXTERN_C() and 
> END_EXTERN_C() macros defined right at the top and that are used all around 
> the engine. Notice how that macro compiles to nothing when C++ isn't being 
> used? I'm simply proposing more of those.

I made no comment pro nor con regarding that proposal.  

> All of this is moot, it would be a huge investment and a whole other 
> discussion to port PHP to another language. That has nothing to do with my 
> proposal.

I could be wrong as I am not an expert in either C or Zig, but from what I 
understand from others who have adopted Zig for C code bases it would not be a 
huge investment at all. Which is why I proposed it. 

> Again, I will reiterate that these proposed changes will not affect the 
> current course of PHP. Development will go on as usual and any bugs 
> introduced by this proposal will be contained to C++ extensions interacting 
> with the code. C devs can act like this doesn't even exist because as far as 
> the C compiler is concerned, it doesn't. On the other hand C++ devs won't 
> have to keep reinventing the wheel whenever they have to build an extension 
> with C++. What is a php extension if not a wrapper for a C/C++ lib?
> 
> IF I wanted PHP to be implemented in C++, I would simply fork it. How many 
> thousand RFCs do you think it will take to get anything reasonable done? I'm 
> baffled that I actually have to convince y'all to IMPROVE the current support 
> for C++, but calm down, no one wants you to quit.

Again, I did not comment on your proposal pro nor con. 

OTOH, as others discussed moving to Rust or C++ I wanted to ensure a more 
compelling alternative — Zig — was at least mentioned and considered, assuming 
a change is being/will be considered at all.

-Mike

P.S. BTW, didn't you already say this conversation was a waste of your time and 
imply that you were done with the thread? Then why would I be replying to you? 


Re: [PHP-DEV] [DISCUSSION] C++ Enhancements in Zend API

2024-08-14 Thread Mike Schinkel
> On Aug 14, 2024, at 3:05 PM, Arvids Godjuks  wrote:
> 
> I want to remind everyone on the thread that code does not only have to be 
> written, which is the "easy part", but it also has to be supported by 
> everyone into the future and chances that the original author sticks around 
> are not that high to do it.
> 
> The Rust thing is shitposting for the sake of shitposting and memeing on the 
> theme "rust solves everything" and "lets rewrite everything into Rust".
> Here's a link with the reminder of the hard rules php-src and internals have: 
> https://github.com/php/php-src/blob/master/docs/mailinglist-rules.md 
> And here's the wiki page on the internals etiquette: 
> https://wiki.php.net/email_etiquette_for_people_new_to_php_internals
> 
> PHP has C as core and has allowed C++ for extensions. Expanding that support 
> is a no-brainer, especially since modern C++ has stepped up in major ways and 
> I don't think C sees a lot of development any more, so it makes sense to move 
> towards C++.

IF there is a serious consideration given to evolving PHP to be written in 
another language — vs. just a newer version of C — I think any reasonable 
analysis would indicate that none of the languages proposed in this thread 
would be appropriate; not Rust, not C++, and not Go.  Why not?

1. Rust is vastly different from C and re-writing in Rust would require 
basically rewriting everything from ground up. The scope of such as project 
would likely make the failed effort toward PHP6 even look quaint. 

Yes, it is possible that one or a few individuals could on-their-own devote 1-3 
years to write PHP in Rust and then present to the community and the community 
could accept it as the next version of PHP. However, AFAIK there is no one 
individual or team who is currently or likely to do this, and having the 
community accept their work is even less likely. 

2. C++ is vastly more complicated to program in than C, and adopting C++ would 
further narrow the number of people who are both proficient enough in both C++ 
and motivated enough to contribute to PHP's codebase. That would likely be just 
a handful of people today and with not much prospect for more in the future.

3. While I would love it if PHP were written in Go, I just do not see it 
happening because it would take a mostly full rewrite like with Rust and even 
as a Gopher I am not sure Go is the language I would pick to develop PHP in if 
there were no existing constrains in large part because of its inability to go 
low-level enough (pun intended), especially related to memory management.

However, there *IS* a language I think the PHP should seriously consider — if 
we do seriously consider a new language at all— and that language is Zig. 

If you are not familiar with Zig — or have simply not explored it yet — I would 
highly recommend reading at least the first article if not all of them:

— 
https://www.infoworld.com/article/2338081/meet-the-zig-programming-language.html
— https://ziglang.org/learn/why_zig_rust_d_cpp/
— 
https://erik-engheim.medium.com/is-zig-the-long-awaited-c-replacement-c8eeace1e692
— 
https://sourcegraph.com/blog/zig-programming-language-revisiting-design-approach

For those who can't be bothered to visit any of the links but will read the 
rest of an email, here are pull quotes from the first article that are relevant 
to why Zig should be considered as a successor to C for PHP. I presented these 
quotes in order of relevance for PHP and not in order presented in the article:

— "Zig sports a high degree of interoperability with C and C++. ... Zig can 
compile C and C++. It also ships with libc libraries for many platforms. It is 
able to build these without linking to external libc libraries."

— "Zig attempts not only to supercede C with its own syntax, but actually 
absorb C into itself as much as possible." 

— "(Zig's developer) said “Zig is a better C/C++ compiler than other C/C++ 
compilers since it supports cross-compilation out of the box, among other 
things. Zig can also trivially interoperate with C (you can import C header 
files directly) and it is overall better than C at using C libraries, thanks to 
a stronger type system and language features like defer.”

— "There is no malloc keyword like in C and C++. Instead, access to the heap is 
handled explicitly in the standard library. When you need such a feature, you 
pass in an Allocator object. This has the effect of clearly denoting when 
memory is being engaged by libraries while abstracting how it should be 
addressed. Instead, your client code determines what kind of allocator is 
appropriate."

— "Making memory access an obvious library characteristic is meant to avoid 
hidden allocations, which is a boon to resource-limited and real-time 
environments. Memory is lifted out of the language syntax, where it can appear 
anywhere, and its handling is made more explicit."  

— "Zig also includes safety features for avoiding buffer overflows, and it 
ships wi

Re: [PHP-DEV] [DISCUSSION] C++ Enhancements in Zend API

2024-08-13 Thread Mike Schinkel
  
  

  
  
  

  
>   
> On Aug 12, 2024 at 4:13 PM,  mailto:lnearw...@gmail.com)>  wrote:
>   
>   
>  You’d have to be seriously naive to believe that “the entire industry is 
> actively trying to move AWAY from C/C++.”
>   
>   
  
  

  
Well, there is this:
  

  
 
https://media.defense.gov/2023/Dec/06/2003352724/-1/-1/0/THE-CASE-FOR-MEMORY-SAFE-ROADMAPS-TLP-CLEAR.PDF


  
-Mike
  
 

Re: [PHP-DEV][Discussion] Should All String Functions Become Multi-Byte Safe?

2024-08-12 Thread Mike Schinkel

> On Aug 12, 2024, at 5:45 AM, danielha...@gmail.com wrote:
> 
> After reading Rowan's last message, it feels appropriate to link to this:
> 
> "The Absolute Minimum Every Software Developer Must Know About Unicode in 
> 2023 (Still No Excuses!)"
> 
> https://tonsky.me/blog/unicode/ 
Good read!  Thank you for mentioning it.

A really standout paragraph from that link is:

"IMO, the whole situation is a shame. Unicode should be 
in the stdlib of every language by default. It’s the lingua 
franca of the internet! It’s not even new: we’ve been living 
with Unicode for 20 years now."

I'll just leave that right here. :-)

-Mike

P.S. Channeling Larry and Derick:  
https://wiki.php.net/rfc/unicode_text_processing 
 

Re: [PHP-DEV] [Discussion] Sandbox API

2024-08-06 Thread Mike Schinkel
> On Aug 6, 2024, at 2:09 AM, Nick Lockheart  wrote:
> 
> Sand Box: A first class API that allows unit testing of code with mocks
> and stubs of other classes or functions, without the need to modify the
> class under test.
> 
> This is an initial idea of how a Sand Box API could work:
> 
> $oSandbox = new SPLSandBox();
> 
> $oSandbox->MockFunction('\mocks\fopen','\fopen');
> $oSandbox->MockFunction('\mocks\fread','\fread');
> $oSandbox->MockFunction('\mocks\fwrite','\fwrite');
> $oSandbox->MockFunction('\mocks\fclose','\fclose');
> 
> $oFileManager = $oSandbox->GetInstance('MyFileManager');
> 
> $oFileManager->WriteFile('/path/to/file.txt');

On the surface, this sounds like a good idea.

This is already possible to do in userland, with a few edge-cases. The 
edge-cases are:

1. Anything that uses `self::class` or similar will break if it expects 
`MyFileManager` to be returned instead of something like `MyFileManager_4k2x8j`.

2. Anything that expects a static variable in `MyFileManager` to have a 
pre-existing value set but an earlier use of `MyFileManager` will not work as 
expected. However, expecting that would be against testing best practices so I 
don't see this as a real concern given your use-case.

OTOH, a userland implementation will also not be very performant when compared 
to a potential PHP core implementation, making it less than ideal for testing. 

However, doing a userland implementation would be a good proof-of-concept, 
allow others to try it, allow others to contribute to the exact syntax and 
semantics, and finally a userland implementation could reveal any potential 
hidden issues in the design before moving on to a proper implementation in C 
for PHP core.

-Mike

P.S. If you are unfamiliar with how to implement in userland you can use the 
same techniques I used in my proof-of-concept for Userland Packages:  
https://github.com/mikeschinkel/userland-packages. If that link is not enough 
and you instead want to ask specific questions about how to implement in PHP, 
feel free to contact me off-list.


Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-08-01 Thread Mike Schinkel


> On Jul 31, 2024, at 5:15 PM, Morgan  wrote:
> A problem is that MD5 should _not_ be one of the most commonly used 
> algorithms.

Tell that to:

- RFC 2846 - Internet Message Format (IMF) Extensions for Internet Mail
- RFC 3229 - Delta-Encoding in HTTP
- RFC 4151 - The Internet IP Traffic Archive, and 
- RFC 4964 - Use of MD5 for IP Version 4 and Version 6 Address Identification 


> Also, providing a dedicated function for an algorithm over and above others 
> that don't get such special treatment inflates use of that algorithm, making 
> it more commonly used. It becomes self-reinforcing.

Well that would be an easy fix: Provide special treatment for the preferred 
algorithms, i.e. their own specific function(s).

-Mike


Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-07-30 Thread Mike Schinkel
> On Jul 30, 2024, at 4:26 PM, Tim Düsterhus  wrote:
> The problem with adding standalone functions for every algorithm is that it 
> would result in a combinatorial explosion of available functions.

I commented on this but as it was probably missed in a longer reply so I will 
repeat.

There is no overwhelming benefit to having a dedicated function for *every* 
combination. However I can see a benefits to having a dedicated function for 
the most commonly used functions.

To decide which, follow the Pareto principle where ~20% of functions used ~80% 
of the time get their own function. Deciding which are the 20% can be 
determined by statistical analysis of public code bases, or where there is no 
existing evidence for new functionality, by voters opinions.

-Mike

P.S. BTW, I do acknowledge your earlier point about more functions == more 
documentation — the first I've heard anyone mention that, so kudos for shining 
a light on it — but I wonder if that effort might not be reduced by finding 
ways to shared duplicated information from a single source?

Maybe one way to address the effort required for docs is to provide incentive 
that could shift some of the burden of documentation onto those who want to see 
more added to core?  Maybe:

1.) Encourage docs to be prewritten for RFCs calling for more functions, to 
motivate people to do the docs work up-front by having a policy to vote against 
RFCs without pre-written docs, 

2.) Provide a prominent TODO queue of doc items needed with good-first-task 
tags that you can point people to on the list who argue for things requiring a 
lot of documentation while saying "Well, if you can't be bothered to update the 
current docs how do we know you'll help maintain the docs for what you are 
asking for?" (admittedly this would probably take a bit of coding to 
implement), 

3.) And finally host one or more "How to write docs for PHP" Zoom sessions that 
get recorded and posted to YouTube to empower more people to know how to do it 
and to provide links for discussions where you call for help 

(I, for one, really have no idea how to get started helping to clean up the 
docs, nor do I have any idea where the most need is.)

#jmtcw


Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-07-28 Thread Mike Schinkel


> On Jul 28, 2024, at 9:19 PM, Morgan  wrote:
> I, too, wish there was more willingness to add useful functions to core. 

:-)

>>> On Jul 27, 2024, at 6:14 PM, Morgan  wrote:
>>> Why a SHA2 algorithm? Why not a SHA3 one? How about standalone functions 
>>> for both, and then when SHA4 comes along (as it inevitably will) another 
>>> standalone function for one of its variants?
>> Yes. Yes, And Yes.
>> And ideally within a `\PHP` namespace.
> At that point you've got \PHP\sha3() instead of hash("sha3-?"), and now 
> you've (a) lost the word "hash" indicator of what's going on, and (b) hidden 
> the choice of "?" from the user. I'm not really seeing an improvement.

Well, your comments are based on assumptions that they would have to be 
implemented as you were envisioning when you wrote your reply. 

My "Yes. Yes. And Yes" was not intended to be full RFC that fleshed out all the 
considerations and proposed a specific implementation. IOW, there are 
definitely ways to address your criticisms if we are open-minded in what could 
be considered. :-)

> At that point you've got \PHP\sha3() 

I'm sure you will find it ironic in hindsight like I do that you chose `sha3` 
(vs. `md5`) as the function to illustrate your argument about not having the 
word "hash" given how SHA is an acronym for "Secure Hash Algorithm."  :-)

By the same token, we could complain about how parse_url(), urlencode() and 
urldecode() all lost the word "resource." :-o

Seriously though, some acronyms are well-known enough — or easily discovered 
enough — that we should be able to use them as function names without lamenting 
they are not spelled out.

But if the concern is they are not grouped together as hashing functions than — 
had we had a `\PHP` namespace as an option — we could easily have: 

- \PHP\Hashing\md5()
- \PHP\Hashing\sha1()
- \PHP\Hashing\sha256()
- \PHP\Hashing\sha3()
- etc.

Also, there is no reason we have to be exhaustive. The pareto principle is 
always one we should consider when deciding when anything should be elevated to 
having its own dedicated function.

> instead of hash("sha3-?")

The problem here is semantic information is encoded in a string rather than in 
a named symbol and thus is not recognized in the AST when parsing and requires 
a hack of diving into the string in order to validate. 

So typically, no type checking, no auto-complete, and potentially delayed error 
detection.

Using strings where symbols would be better is a common wart in PHP — such as 
PHP not having a first-class type for class, interface or function — so we have 
to pass around names as non-typesafe strings instead.  

BTW, I asked ChatGPT to opine on the problems caused with strings-as-symbols 
from computer science and software engineering perspectives, and this is what 
it gave me:

https://chatgpt.com/share/17d57881-c411-4b64-863a-d0692b4a4577 

> and (b) hidden the choice of "?" from the user. I'm not really seeing an 
> improvement.

What's wrong with something like?

use PHP\Hashing\sha3;
use PHP\Bits; 
...
$hash_224 =  sha3($data,Bits::224);
$hash_256 =  sha3($data,Bits::256);
$hash_384 =  sha3($data,Bits::384);
$hash_512 =  sha3($data,Bits::512);

The point I am trying to get across is that improving the developer experience 
is not a binary true or false endeavor. There are many ways to improve DX, but 
they all must start with a openness to consider doing it.

> On Jul 28, 2024, at 9:19 PM, Morgan  wrote:
> 
> Hey, all I'm doing is pointing out that the only reason those functions were 
> standalone to start with is because when they were added they were the only 
> ones around; they weren't introduced as "easier to use" alternatives to the 
> more generic case. If hash() had been added in PHP with half a dozen 
> different algorithms right at the beginning, would md5() and sha1() have been 
> given special treatment? Possibly: MD5 (and later SHA1) got all the publicity 
> at the time.
> 
> I haven't seen an explanation of what makes them "easier to use": if you want 
> to use md5() (for whatever reason: I don't care) it's not that hard to write 
> hash("md5") instead. I just went through a file deduplication utility of mine 
> and did exactly that. Yes, I am using MD5 as a message digest algorithm.

But just because they were historical artifacts doesn't mean that they should 
be frowned on, or removed. `echo` is also a historical artifact, but no one is 
arguing we should get rid of this:

echo "Hello World";

And then require developers to use this instead:

fprintf(STDOUT, "Hello World"); 

¯\_(ツ)_/¯

-Mike


Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-07-27 Thread Mike Schinkel
> On Jul 27, 2024, at 7:24 AM, Christoph M. Becker  wrote:
> 
> Hmm, such soft deprecations should be a good thing, but I'm afraid they
> are not really reaching much of the user base.  Remember ext/mysql?
> That was soft deprecated for "centuries", but still support channels
> were burning when it actually had been deprecated, and even after it had
> been removed.  (interestingly  still
> says the package would have been moved to )
> 
> Maybe, just maybe, it might be a good idea to repurpose E_STRICT for
> such things.  Basically a three step deprecation: first document that a
> feature is obsolete, then trigger E_STRICT, and only then E_DEPRECATED.
> I haven't really thought this through, though.

Reading this I pondered why long soft deprecations do not really work and why 
there is still a crisis when the hard deprecation happens. Seems to me that as 
long as those who prioritize spend can put off doing things with no short term 
benefit then there is no tangible incentive to update. People will (almost?) 
always prioritize addressing a current crisis — or adding features that benefit 
them in the near term — than remediating something that is not causing them a 
current problem.

I wondered if it would not be possible to give code owners an incentive to 
remediate without actually forcing them to? The one thing that I came up with 
is reduced performance over time. 

Somehow I expect to get a firestorm of negativity for even suggesting this, but 
please hear me out.

Imagine we had another round of deprecation voting for md5(), sha1(), etc. and 
instead of it just being soft deprecated until PHP 10 then hard deprecated, 
what if we ADDED a sleep duration in each of those functions, and we escalate 
for each minor release. Start with 100 milliseconds delay per function call, 
and then add another 100 milliseconds delay each point release of PHP.  

This would allow all code to continue functioning but over time any code that 
uses the functions will get slower. The code owners — not the developers — will 
then be incented to prioritize a remediation sooner than later. And the longer 
they wait the worse performance will get assuming they keep upgrading their 
version of PHP. OTOH their code will continue to work no matter what,. so they 
can put off remediating until it becomes their priority.

This would certainly get lots of libraries to be motivated to remediate as 
their users would get annoyed with the delays, and commonly used libraries can 
affect large numbers of installations. And since performance topics drive 
eyeballs, lots of developer websites would be motivated to write articles about 
how and why people should remediate those functions.

Something to consider?

-Mike

P.S. Frankly, I really would not want to see md5() nor sha1() removed because 
there are valid use-cases for them. I would at least like to see them kept in 
some form, maybe in an `\Insecure` namespace, or renamed `insecure_md5()` and 
`insecure_sha1()` or maybe add a third optional bool parameter `$insecure_ok` 
that defaults to `false` — or ?enum flag parameter accepting 
Hashing::INSECURE_OK as its only value — thus allowing developers to explicitly 
opt-in to insecure use.

Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-07-27 Thread Mike Schinkel
> On Jul 27, 2024, at 8:36 AM, Rowan Tommins [IMSoP]  
> wrote:
> On 27 July 2024 00:58:17 BST, Morgan  wrote:
>> 
>> I'm not talking about the MD5 or SHA1 algorithms or whether they should or 
>> shouldn't be used. I'm just talking about the functions themselves. md5(), 
>> md5_file(), sha1(), and sha1_file(). They only exist because there wasn't 
>> the generic hash algorithm extension when they were created.
> 
> I understand what is being claimed (and you're not the only one claiming it), 
> I'm just not convinced it's true. I think they have standalone functions for 
> the same reason we added str_contains and str_starts_with - because it's 
> convenient to have straightforward functions for common use cases.
> 
> The hash() function is like a 60-piece set of interchangeable screwdriver 
> heads, which only professionals and enthusiasts need; md5() and sha1() are 
> like the flat-head and Phillips screwdrivers that everyone has in a drawer 
> somewhere.
> 
> The thing that always surprises me is that PHP *doesn't* have a standalone 
> function for SHA-256, which is the only other I've ever used. 
> 
> To continue the analogy, we're missing a Pozidriv screwdriver, so people are 
> misusing the Phillips one. The RFC is suggesting that we take away their 
> flat-head and Phillips screwdrivers, and leave them with the 60-piece set, 
> and no instructions. 
> 
> My suggestion is we instead give them a Pozidriv screwdriver, and write some 
> tips on how to use it correctly. 

I rise in support of this mindset.  

Some of us like to draw inspiration from other languages, and in that vein one 
of the things that makes Go such a joy to program in is the fact the Go team 
continues to add "convenience" functions with every new 6 month release. 

Many (all?) of the functions the Go team adds could have been written in 
"userland" but they represent such common use-cases that the Go team decided to 
make them easy and obvious. They even soft deprecate functions and structs that 
are not ideal and replace them with ones with better names and better 
signatures. If Go had started with the string and array functions PHP has today 
they would almost certainly replaced them by now, ~15 years into Go's tenure.

It is a shame that PHP's culture is so hostile towards adding functionality 
that could also be added in userland, especially when that functionality would 
simplify and standardize algorithms that are non-obvious and/or too easy to 
implement incorrectly. If the PHP culture embraced moving common use-cases into 
core it would make PHP much more pleasurable to program in and make it much 
less likely that PHP programs would have bugs and/or security vulnerabilities.

> On Jul 27, 2024, at 6:14 PM, Morgan  wrote:
> Why a SHA2 algorithm? Why not a SHA3 one? How about standalone functions for 
> both, and then when SHA4 comes along (as it inevitably will) another 
> standalone function for one of its variants?

Yes. Yes, And Yes.

And ideally within a `\PHP` namespace.  

-Mike

P.S. But as we know a standardized `\PHP` namespace is apparently never going 
to happen although for the life of me I still cannot understand why not — and I 
was here during the voting down of that RFC ~4 years ago — given how so many 
other languages had done the equivalent.


Re: [PHP-DEV] Explicit callee defaults

2024-07-27 Thread Mike Schinkel
> On Jul 27, 2024, at 3:19 AM, Rob Landers  wrote:
> There’s nothing stopping you from doing that, except your autoloader. If you 
> wanted to have every class ending with Arg load the same class without arg; 
> so QueryArg and Query are usually in the same file (but can be in separate 
> files too), you could do something like this:
> 
>  function customArgAutoloader($className) {
> if (substr($className, -3) === 'Arg') {
> $baseClass = substr($className, 0, -3);
> $filePath = __DIR__ . '/' . $baseClass . '.php';
> 
> if (file_exists($filePath)) {
> require_once $filePath;
> } 
> }
> }
> 
> spl_autoload_register('customArgAutoloader');
> 
> (Untested, but you get the idea)

Sure, but that is non-standard, so it would be swimming against the current to 
use it, and no one else would write code that way.

Still, the reason for my comment was to ask we consider a first-class args type 
which would enable being able to pass parameters like `{foo: 1, bar: 2}` 
instead of  `new QueryArgs(foo: 1, bar: 2)`, not to discuss autoloaders.

-Mike



[PHP-DEV] Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4 — Use a carrot, not a stick.

2024-07-26 Thread Mike Schinkel
> On Jul 26, 2024, at 9:11 PM, Mike Schinkel  wrote:
> 
> Kudos to Tim Düsterhus for identifying 
> https://www.phptutorial.net/php-tutorial/php-csrf/ and 
> https://www.php-einfach.de/php-tutorial/die-wichtigsten-php-funktionen/ but 
> his takeaway for an action item was less inspiring.  He argued those articles 
> support deprecations when it seems to me the more obvious takeaway after 
> finding those articles would be to reach out to those websites — as well as 
> others publishing insecure information — and provide them with updated 
> content to replace the content they are currently publishing with content 
> that is promotes secure practices. Getting those websites updated is likely 
> to have far more positive impact for new PHP developers learning to do things 
> "the right way" then forcing them to update their code where they'll likely 
> just use hash("md5").

As a quick follow up:

https://www.phptutorial.net/contact/

And:

https://www.php-einfach.de/author/nils/ 
https://www.nils-reimers.de/contact/ 

-Mike

[PHP-DEV] Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4 — Use a carrot, not a stick.

2024-07-26 Thread Mike Schinkel
> On Jul 26, 2024, at 6:03 AM, 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]

People who work in emergency rooms think that motorcycles are the ultimate evil 
and should be banned, because emergency room workers are the ones who see all 
of the carnage of the small percent who wreck their motorcycles, and they see 
none of motorcycling's upsides.

Similarly, security experts see everything through the lens of security issues, 
because they see the problems FAR more often than everyone else. And as 
security expertise, they don't see code through other lenses where security is 
not an issue.

Not saying the input of a security experts is not useful, but one man's input 
is only one side of the story, just like emergency room workers vs. motorcycles.

> Yet again the PHP community doesn't care about security of its users, current 
> and future, and just prefers the convenience of needing to type less 
> characters and not go back fix some code for better design.

Explicitly stated, that is a straw man argument, which Rowan already called out.

Different people weight risks, costs, and benefits differently, and just 
because you might feel your approach for addressing security concerns should 
eclipse anyone else's approach and all other concerns does not mean your 
approach exists at the peak of the moral high ground.

Every time PHP deprecates software it places the burden and the cost of 
remediation on anyone and everyone who continues to use the software that 
requires the deprecated items. Those who are zealously security-first generally 
dismiss those burdens and cost of remediation — because they do not have to be 
burdened by then nor pay the costs — and so they shift them to everyone, 
including those who are using functions properly.

Those more pragmatic balance that burden and cost with the potential burden and 
costs that deprecating can impose. And in the case of md5() where public code 
on GitHub shows almost 1 million uses, that imposed burden and cost is pretty 
large.

But ignoring the burden and cost, is it strongly arguable that deprecating 
md5() wouldn't even fix the security problems in most cases as those you most 
want to force to fix things will the ones more likely to just create a polyfill 
and move on. As many has already stated on this thread.

Kudos to Tim Düsterhus for identifying 
https://www.phptutorial.net/php-tutorial/php-csrf/ and 
https://www.php-einfach.de/php-tutorial/die-wichtigsten-php-funktionen/ but his 
takeaway for an action item was less inspiring.  He argued those articles 
support deprecations when it seems to me the more obvious takeaway after 
finding those articles would be to reach out to those websites — as well as 
others publishing insecure information — and provide them with updated content 
to replace the content they are currently publishing with content that is 
promotes secure practices. Getting those websites updated is likely to have far 
more positive impact for new PHP developers learning to do things "the right 
way" then forcing them to update their code where they'll likely just use 
hash("md5").

Further, rather than shift the burden of remediation to everyone else, why not 
write a crawler that can automatically and proactively submit PRs to all the 
code out there using md5(), etc. so that most people only need to accept the PR 
to update their code, and make is available as a CLI for internal use? I know 
it is not that simple to remediate, but who do you expect will know how to do 
that better than those on PHP internals. Certainly not most GitHub repo owners. 
Besides, the PR could say "Review your code we are proposing the change, and if 
you are confident that your uses are secure then do not apply this PR. But if 
you are not sure they are secure then just apply the PR, test it, and then 
you'll certainly be safer."

Rather than just take a low-effort, feel-good action for security theater, if 
the PHP community REALLY cares about security for its users it would take a 
pro-active, higher-effort approach to addressing the concern. The WordPress 
community implemented at least one successful technology-supported "marketing" 
campaign to move its user base in the past, one of which was the "Serve Happy" 
campaign to get people to update their version of PHP (how ironic!): 

https://make.wordpress.org/core/features/servehappy/

Why not create a working group to promote a "SERVE SECURELY" campaign modeled 
after WordPress's "Serve Happy" campaign, and do your best to help people 
remediate their security issues? Hell, imagine the free press and industry-wide 
exposure that such as campaign would provide as a way to educate PHP 
programmers on the dangers of misusing md5() and other insecure approaches?

It is also strongly possible you could even get 

Re: [PHP-DEV] Explicit callee defaults

2024-07-26 Thread Mike Schinkel
> On Jul 26, 2024, at 6:42 PM, Christoph M. Becker  wrote:
> 
> I have only skimmed your suggestion, but it sounds quite similar to
> .

I would really love to hear from some of those who voted "no" ~9 years why they 
did so, and if they still feel the same.

> On Jul 26, 2024, at 5:54 PM, Bilge  wrote:
> When writing a function, we can specify defaults for its parameters, and when 
> calling a function we can leverage those defaults implicitly by not 
> specifying those arguments or by "jumping over" some of them using named 
> parameters. However, we cannot explicitly use the defaults. But why would we 
> want to?
> 
> Sometimes we want to effectively inherit the defaults of a function we're 
> essentially just proxying. One way to do that is copy and paste the entire 
> method signature, but if the defaults of the proxied method change, we're now 
> overriding them with our own, which is not what we wanted to do. It is 
> possible, in a roundabout way, to avoid specifying the optional parameters by 
> filtering them out (as shown in the next example). The final possibility is 
> to use reflection and literally query the default value for each optional 
> parameter, which is the most awkward and verbose way to inherit defaults.
> 
> Let's use a concrete example for clarity.
> 
> function query(string $sql, int $limit = PHP_INT_MAX, int $offset = 0);
> 
> function myQuery(string $sql, ?int $limit = null, ?int $offset = null) {
> query(...array_filter(func_get_args(), fn ($arg) => $arg !== null));
> }
> 

Yes, I run into that issue all the time.  So much so that I adopted an 
"optional args" pattern which itself has many downsides but in my code it has 
had fewer downsides than doing it other ways.

So for your example I would write it like this (though I hate having to 
double-quote the names of the optional args):
function query(string $sql, array $args = []);

function myQuery(string $sql, array $args = []) {
query($sql, $args);
}

myQuery("SELECT * FROM table;", ["offset" => 100]));

This is very flexible and a pattern that served me well for 10+ years. 

But of course this has none of the type safety nor code-completion benefits of 
named parameters, which I would sorely like to have.


> In this way we are able to filter out the null arguments to inherit the 
> callee defaults, but this code is quite ugly. Moreover, it makes the 
> (sometimes invalid) assumption that we're able to use `null` for all the 
> optional arguments.
> 
> In my new proposal for explicit callee defaults, it would be possible to use 
> the `default` keyword to expressly use the default value of the callee in 
> that argument position. For example, the above implementation for myQuery() 
> could be simplified to the following.
> 
> function myQuery(string $sql, ?int $limit = null, ?int $offset = null) {
> query($sql, $limit ?? default, $offset ?? default);
> }
> 
> Furthermore, it would also be possible to "jump over" optional parameters 
> without using named parameters.
> 

To me, while nice I feel it is very much like only a quarter step in the right 
direction.

I do not meaning to highjack your thread; feel free to ignore this if you feel 
committed to pursing only your stated approach and are not interested in what I 
would like to see.  But I mention in hopes you and others see value in a more 
complete approach:

To begin, we can already currently do this (although I do not see many people 
doing it in PHP; fyi this approach is the norm for many Go programmers):

class QueryArgs {
   public function __construct(
 public ?int $limit = 100,
 public ?int $offset = 0,
   ){}
}

function myQuery(string $sql, QueryArgs $args = new QueryArgs()) {
   query($sql, $args);
}

myQuery("SELECT * FROM table;", new QueryArgs(offset:100));

I can only give my reasons for not doing it myself in PHP and speculate that 
others may have similar reasons and/or have never even considered it:

1.  Not having an easy and consistent way to declare the "args" class in the 
same file where the functions that use it are declared which keeps it 
out-of-sight and makes it harder to keep updated than it needs to be.

2. Having lots of visually annoying boilerplate that obscures a clear use-case.

What would be great IMO would be if PHP could elevate this concept to first 
class and add syntax and features to streamline and empower its use.  Imagine 
if we could instead:

1. Define an "args" type which would be based on a class like enum is based on 
a class:

args QueryArgs {
 public ?int $limit = 100;
 public ?int $offset = 0;
}

2. Declare a function to use those args, using your `default` keyword when they 
are optional:

function myQuery(string $sql, QueryArgs $args = default) {
   query($sql, $args);
}

3. And finally, allow a streamlined syntax to pass args:

myQuery("SELECT * FROM table;", {offset:100});

(I do not think we can or even should try to tackle the PSR-4 "every symbol

Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-07-25 Thread Mike Schinkel
 
 

 
 
 
 
 
 
 
 

 
 
>  
> On Jul 25, 2024 at 6:02 PM,  mailto:li...@ageofdream.com)>  
> wrote:
>That's a good point. What if there were crypto functions that worked
>  
>  
>  like password_hash() in that they had one generic function name, but 
> magically used the new/better "best practice" algorithms as time went by 
> without the need to update any calling code? Maybe there should be three 
> generic-named functions: fast_hash() // not secure, makes UIDs quickly 
> secure_hash() // uses best practice one-way hash algo secure_crypt() // uses 
> best practice reversible encryption. Then the developer signals their 
> *intent* by choosing a function name, and the algorithm magically works 
> underneath (perhaps with the option of an ini override to make those 
> functions work in different environments). 
>
>  
 
 
 
 
 

 If those _were_ added, I would bikeshed their names to make sure their intent 
was 100% clear: 
>  
 
 
 

 
 
insecure_hash() // not secure, makes UIDs quickly
 
secure_oneway_hash() // uses best practice one-way hash algo
 
secure_reversible_hash() // uses best practice reversible encryption.
 

 
-Mike
 
 
 

Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-07-25 Thread Mike Schinkel
 
 

 
 
 
>  
> On Jul 25, 2024 at 5:35 PM,   (mailto:imsop@rwec.co.uk)>  wrote:
>Rather than force people to use functions that we acknowledge are hard  
>  
>  
>  to use, surely the logical thing is to make the "right" code *easy* to use? 
> Which means if we want people to use SHA-256, let's add a sha256() function 
> to make it easy. This is what password_hash() and password_verify() did 
> right: the functionality was already there in crypt(), but it's hard to use, 
> and harder to use correctly. Providing clearer functions, even though they do 
> the same thing, helps new developers "fall into the pit of success". 
>
>  
 
 
 
 
 

 Yes!1000% *THIS*.

 
-Mike
 

 
>  
>  
>  The hash() function isn't quite as confusing as crypt(), but according to 
> the manual, it currently supports 60 different algorithms, most of which I 
> have never heard of. I'm aware that "sha256" is better than "sha1", but 
> should I be aiming higher, and using "sha384", or maybe one of the four 
> flavours of "sha3"? Then there's the fun-sounding "whirlpool", the faintly 
> rude-sounding "snefru", and a bewildering fifteen flavours of "haval". A new 
> user being told "don't use sha1(), use hash() and pick from this list" is 
> more likely to say "ah, there's sha1, jolly good" than spend an afternoon 
> reading cryptography journals. There's no pit of success to fall into. 
> Regards, -- Rowan Tommins [IMSoP] 
>
>  
 
 

Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.4

2024-07-24 Thread Mike Schinkel
> On Jul 23, 2024, at 12:26 PM, Larry Garfield  wrote:
> 
> 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.

I do not see this use-case as compelling.

`mixed` is perfectly sufficient and using `_` for a data types just gives two 
ways to do the same. Not that multiple ways to do the same thing is necessarily 
wrong, but I think it needs a better justification than just to save 
characters.  Besides, it has the potential to confuse people as to its exact 
meaning whereas `mixed` does not.

OTOH, if you really want to say characters — albeit not as many — then choose 
`any`, which is certainly less likely to be confusing and has an analog in Go, 
TypeScript, and Python, at least.

Also, AFAIK, few (no?) other languages actually allow for using `_` for types, 
they only allow using them for variables.  I know that to be the case for Go, 
and if I understand the docs correctly it is also true for Rust, Zig, Haskell 
and Swift, with caveats for Rust.  

- Rust allows underscore for type inference, e.g.:  let x: _ = "Hello, world!";
- Also for a Generics' type placeholder, e.g.:  let vec: Vec<_> = vec![1, 2, 3];
- But as for Rust pattern matching, the underscore is only used for values, not 
types.

For any other languages, I cannot say.

> 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');

This is actually where a "blank" variable represented by `_` actually makes a 
lot of sense.  It is also how Go and Zig use them and effectively also how 
Rust, Haskell, and Swift use them.  

Unlike for types where we have `mixed`, there is no current globally consistent 
alternate to using a blank variable in PHP. The only option is to use an 
arbitrary name that other developers won't know the intention of unless the 
developer adds comments to the effect.

In summary, although I don't have strong feelings about deprecating classes 
named `_`, I do not think the arguments made for disallowing them actually have 
any analog in any other languages so I question if there is valid justification 
for the deprecation. #jmtcw #fwiw

-Mike

Re: [PHP-DEV] [RFC] Static class

2024-07-12 Thread Mike Schinkel
> On Jul 11, 2024, at 8:14 PM, Bilge  wrote:
> 
> On 25/06/2024 16:17, Derick Rethans wrote:
>> we shouldn't be encouraging static classes as 
>> a bag of static functions, that ought to be just namespaced functions.
>> 
>> cheers,
>> Derick
>> 
> Can someone clue me in as to why grouping related functions in a file with 
> nothing but a namespace is strictly better than those same related functions 
> grouped as members of a class? It doesn't have to be Larry or Derick, because 
> even though they have expressed this view, I am aware they are not the only 
> ones whom hold it. Anyone who can shed some light on this perspective is 
> welcome to comment.

I cannot answer your question as posed but I can give you a counter-reason, one 
supporting the use of static classes as a bag of static functions, at least 
with the feature set of PHP 8.4 and prior.  

If a developer needs to hide global state — and there are valid reasons for 
maintaining global state using static classes along with a related set of 
static functions. Minimally, when using streams with include*()/require*() e.g. 
include("myprotocol://${handle}") namespaces simply do not have the necessary 
visibility scoping features and thus are not an option.

I am currently working on a PoC for packages in userland that uses static 
classes exactly in this way. I will hopefully be able to share working code for 
that soon.

-Mike

P.S. None of include*()/require*() accept a stream context AFAICT. If they did 
a developer could pass in a dependency object as a context, but currently 
(again, AFAICT) there is no way to associate a dependency object with an 
include*()/require*() call. The only approach I have been able to identify to 
allow access to retrieve and update a dependency object is to use a key into a 
array in a private static property with public static get/set methods.  

If context were added to include*()/require*() and/or visibility scoping where 
added to symbols within namespaces then this use-case would no longer be an 
argument for static classes. But unless and until then, static classes are the 
only way to go. #fwiw

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-11 Thread Mike Schinkel


> On Jul 11, 2024, at 10:32 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Thu, 11 Jul 2024, at 12:26, Mike Schinkel wrote:
>> Let me use an analogy.  Envision two people on a city council of a small 
>> town.  One proposes the city should
>> implement a water, power and sewer grid so anyone who wants to build a new 
>> home or business in the city 
>> would be able to do so easily. 
> 
> This is a terrible analogy, IMHO. Here's a more pertinent one:

Sure, we can go back and forth and discredit each others analogies, but that's 
not going to change your mind nor likely mine.  

The crux of our disagreement is I see value on infrastructure services and you 
evidently do not.

> If you want to solve autoloading in WordPress, this is the wrong forum. 
> 
> Firstly, anything you do in core will not be adopted by WordPress, because it 
> will be 5+ years before their minimum PHP version is high enough to use it. 
> You're going to have to write a userland polyfill anyway.

That is what you are missing on this point. 

If PHP supported a cascading class map autoloader then a developer could build 
their sites and their plugins for that version of PHP without having to depend 
on WordPress changing to support it. And if they are distributing plugins they 
could build fallback mechanisms for earlier versions of PHP plus also recommend 
to their users that they upgrade to the newer versions of PHP. 

It is about empowering individuals developers, not about empowering WordPress. 

But, like I said, since anyone could no it, evidently no one will.

> Secondly, mapping namespaces to directories isn't the hard part for 
> WordPress. The hard part is integrating into their existing plugin installer 
> system - which already has a system for metadata, it doesn't need a new 
> config file - and persuading plugin authors to actually use it.

No, integrating into the plugin system would actually be quite easy per the 
class map design we've been discussing. I know the internals of that system 
well, I've probably debugged through it literally hundreds of times.

And sorry, the existing metadata system in WordPress has no information about 
plugin dependencies and is inadequate for that purpose. It only has an ini-like 
plugin header with basic information and is not suitable for dependencies. 
Also, "persuading plugin authors to actually use it" won't change a thing 
because they are already using it effectively, generally speaking.

> Maybe you also need Composer to make some changes to control it without the 
> CLI, so plugins can list their requirements and have them installed centrally.

That well could be.

> That's also not a subject for this list.

And we disagree, yet again.

Anyway, I am trying to avoid this thread so I can instead invest time in 
research and proof-of-concept work. Please don't pull me back in.

-Mike

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-11 Thread Mike Schinkel
Preface:  I am going to bow out of this conversation now (unless pulled back 
in) and come back after 8.4 settles.

In the mean time I'll be working on two proof-of-concepts.  One is a totally 
userland PoC for packages being able to load same-named symbols, and the other 
will be working out how to use multiple symbol tables in PHP core. And as I 
have never modified php-src before, that is going to take some learning.

However, below are responses to Rowan and Larry.


> On Jul 10, 2024, at 8:33 AM, Rowan Tommins [IMSoP]  
> wrote:
> 
> On Wed, 10 Jul 2024, at 07:38, Mike Schinkel wrote:
>> The request is to add class maps with a PHP-standardized format into 
>> PHP core so that when a library of code needs to register classes to be 
>> autoloaded they can contribute to a cascading of class maps where ONE 
>> internal function checks the single union of all class maps for a 
>> mapped symbol before turning over control if no such symbol is found in 
>> the map to the procedural autoloaders that are currently available. 
>> That way *any* PHP code could register its own class map without having 
>> to get the core app to rearchitect itself to allow that to happen.
> 
> Everything you've just described is possible, today, with no changes to PHP 
> core.

I described a **standardized format** that would be processed by PHP,

How exactly can any one individual implement a standardized format on their 
own, today?  One that anyone can depend on to be recognized and processed by 
any version of PHP after the one that first implemented it?

Rhetorical question. Of course.

> So let's step back a second, and look at the pros and cons of implementing it 
> in core:
> 
> Pros:
> - Possibly a bit faster if the C code can be optimised
> - "Blessed" by the PHP project, which makes it a standard of sorts

Or — without the blessing of a standard — as we sometimes say in the USA: 
"Besides that Mrs Lincoln, how was the play?"

Let me use an analogy.  Envision two people on a city council of a small town.  
One proposes the city should implement a water, power and sewer grid so anyone 
who wants to build a new home or business in the city would be able to do so 
easily. 

The other argues that anyone wanting to build can set up their own generator, 
dig their own well, and dig their own septic tank so why should the city 
provide such a grid? After all, anyone who is motivated enough can build 
"today," right?

Clearly that latter argument ignores the value of a central authority providing 
infrastructure others can just depend on existing, minimizing their cost, 
effort and risk. It also ignores that without that infrastructure most simply 
won't build there.

In PHP some bits like nice-to-have functions are easy enough to relegate to 
userland — although str_starts_with() and str_ends_with() sure are nice to just 
have like a community center in that city which all residents can use. OTOH, 
for infrastructure services, PHP benefits itself and others by providing them 
even if someone could build the functionality themselves.  

To be clear, the fact something is an infrastructure service itself is not 
sufficient to argue it *must* be included in PHP core — the need for service 
itself should stand on its own. 

However, it is enough (IMO) to show "you can do it yourself today" is not a 
valid argument against an infrastructure service. 

So can we please instead focus on the pros and cons of having such an 
infrastructure service instead of using the canard "you can build it yourself" 
as an argument against roads, power, and sewers?

If yes, we should discuss your list of pros and cons. 

HOWEVER, I think it is probably best to postpone any additional discussion 
until after 8.4 is released and any initial bugs are worked out so anyone 
interested could focus on the reasoning.

> On Jul 10, 2024, at 10:07 AM, Larry Garfield  wrote:
> 
> 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 handl

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Mike Schinkel
> On Jul 10, 2024, at 5:50 AM, Jordi Boggiano  wrote:
> 
> On 2024-07-09 05:24, Mike Schinkel wrote:
>> 
>>  
>> And this sentence is why I chose to reply to your message.  That assumption 
>> itself blocks the needs of user-managed apps.
>> 
>> (Did you happen to read my compare-and-contrast of user-managed vs. 
>> developer-managed apps from a few days ago?)
>> 
>> I feel it is likely those who have never worked professionally in PHP on 
>> user-managed apps like WordPress  — which I assume describes you accurately? 
>> — are probably just simply unaware of the problems that your assumptions 
>> cause for user-managed apps. And yes, some developers have no empathy for 
>> others who have different circumstances, but I honestly don't think you 
>> (Rowan) are in the category. 
>> 
> Just one note here: You keep saying user-managed apps but from what I can 
> tell, these problems really only apply to WordPress.

There are numerous others, such as Joomla, Phalcon, CMS Made Simple, 
TextPattern, OpenCart, ExpressionEngine and ProcessWire. 

But yes, the fact that WordPress has well over 50% marketshare of CMS and 
dwarfs all the others by well over an order of magnitude makes it appear that 
it only really applies to WordPress.

Which, given the number of users for each, it kinda does. But that also begs 
the question if dismissing the PHP app with by-far the largest user base is the 
smartest approach?

> There are others like Contao CMS who decided as a project they wanted 
> user-managed plugins but also wanted to rely on Composer and its ecosystem of 
> packages, and they made it happen [1]

I just scoured the Contao website and the websites of a few of their 3rd party 
extensions and after quite a bit of detective work I found how Contao allows 
user-managed plugins, per se.  They did not make it obvious on their site how 
to do it, though.

First you have to download and install a `.phar file called Contao Manager[1] 
and install it on your server. Which yeah, a developer could do for an 
end-user, but most end-users are going to be blocked by this. 

Second, to use Contao Manager you have to have a PHP installation that allows 
using the functions proc_open()/proc_close() and allow_url_fopen() which AFAIK 
most responsible web hosts lock down on a shared server, which is the majority 
of WP hosting. The reason those are required is Contao Manager is just using 
Composer on the backend via CLI to install and manage plugins. 

So while yes, Contao does allow users to manage plugins, that was not what I 
meant when I made a distinction between user-managed and developer-managed 
apps. To me, Contao is squarely in the developer-managed app category.

> So while I have some sympathy for all developers stuck maintaining WP sites, 
> and plugin authors not willing to do everything themselves and deciding to 
> bundle a vendor dir with Composer-installed dependencies.. It feels like 
> you're all kinda held hostage with the choices of the WordPress project, 
> which sucks for sure but saying it is unfixable is not helping.

How are you envisioning it be fixed?   

If there are ways to fix things that do not require WordPress to make a change 
with major BC breakage nor require users upgrade web hosts to support dedicated 
features I would be very happy to find out what those are.

And yes, to concur by also clarify, developers are held hostage by the 
*combined* choices of the WordPress and the PHP projects. It is kinda like 
being a kid with needs but also with feuding parents. ¯\_(ツ)_/¯

-Mike

[1] https://docs.contao.org/manual/en/installation/contao-manager/


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Mike Schinkel
> On Jul 10, 2024, at 2:56 AM, Jordan LeDoux  wrote:
> 
> On Tue, Jul 9, 2024 at 11:42 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> [snip]
> 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.
> 
> While Larry was very blunt (and I don't really fault him for that either), 
> that should not be your only takeaway. The short version was that he was 
> telling you, and the other people in this thread, to stop pontificating and 
> to do something that resembles developing/researching a solution.

Why support a claim that assumes I have not been developing/researching a 
solution when you have absolutely no knowledge of what I have been doing? (I 
have in-fact been researching and developing a PoC. Full time for the past 
week, actually.)

> A lot of the people who actually have experience working on the engine are 
> literally ignoring this conversation right now (and may come back to it next 
> month) because it's just too much noise and nonsense right when we're near 
> feature freeze.
> 
> Your focus and intent to drive this discussion towards trying to duplicate 
> composer reduces its usefulness. I get that you do not like 
> PSR-4/composer/whatever. I honestly cannot wade through the 15,000-ish words 
> you've sent in these threads to nail down the specifics. But I know for a 
> fact that an attempt to redesign composer is:

You claim "my focus and intent" is to "duplicate composer" and yet you claim 
you "honestly cannot wade through the 15,000-ish words?"  

If you haven't read my email, then how exactly do you know what my focus and 
intent has been?

In fact, my focus and intent has *not* been to duplicate composer. FULL STOP.

But since I already fully explained my focus and intent then — other than the 
fact you didn't read it — it would do a disservice to everyone to repeat it.

> 1. Orthogonal to PHP modules (they have nothing to do with each other from a 
> design perspective).
> 2. Doomed to failure. 
> 
> Your one useful takeaway, that Larry gave you specific steps for, is to focus 
> on the feature the original proposer of the thread was trying for, instead of 
> continuing to derail it into composer-related nonsense.

If you wanted to quiet a thread that obviously annoys you for some reason it 
would seem the last thing you to do is immediately knee-jerk a reply with three 
(3) different straw man accusations — each of which can easily be disproven by 
reading my email to which you replied — when just ignoring the email was your 
option.

-Mike

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-09 Thread Mike Schinkel
> On Jul 9, 2024, at 1:15 PM, Larry Garfield  wrote:
> On Sat, Jul 6, 2024, at 1:12 AM, Mike Schinkel wrote:
>> WordPress differs from the apps many *(most?)* developers on PHP 
>> Internals work with in the following way:
>> 
>> WordPress = *User-managed app*
>> Most = *Developer-managed apps*
>> 
>> In a* Developer-Managed app* developers choose which 3rd party 
>> functionality will be incorporated into their sites whereas with a 
>> *User-managed app* users choose which 3rd party functionality will be 
>> incorporated into their site. And that is the KEY difference. 
>> 
>> So I am wondering if we can get people on this PHP Internals list who 
>> dismiss the needs of WordPress developer BECAUSE it is WordPress to 
>> recognize that User-Managed apps ARE a class of PHP applications have 
>> needs that **deserve** to be addressed?  
>> *
>> *
>> Two (2)* unmet needs of User-Managed apps *that *"standard" *PHP 
>> currently does not address come to mind:
>> 
>> User-managed apps needs to be able to handle both:
>> *
>> *
>> 1. *User-added add-ons* *("plugins" in WordPress, "modules" in Drupal) 
>> *that have conflicting dependencies, and
>> 
>> 2. *Add-on directory structures *that do not follow a PSR-4 directory 
>> hierarchy.
>> 
>> As for #2, even if those apps could rearchitect their existing 
>> directory structure they cannot realistically be expected to do with 
>> because of the huge BC issues their users would experience. 
>> 
>> And newly created User-managed apps may still find that a PSR-4 
>> directory structure is not in the best interest of their project or 
>> their users. To elaborate, PSR-4 generally assumes that ALL code goes 
>> into ONE hierarchy and that any and all code that will be autoload gets 
>> placed in that hierarchy.
>> 
>> But with add-ons it makes a lot more sense to have the entire add-on 
>> contained in its own add-on directory. This is exactly where PSR-4 
>> breaks down with respect to User-managed apps.
>> 
>> Sure, you can have multiple PSR-4 autoloader root directories, but that 
>> does not scale well to websites with a large number of add-ons as many 
>> WordPress sites I worked on used. Some had over 100 plugins.  With a 
>> hierarchy of autoloader maps that Michael Morris is proposing WordPress 
>> could collect up all the maps and create one map every time a plugin is 
>> added, updated or deleted.
>> 
>> 
> 
> I am going to jump in here on this point specifically, because it seems to be 
> a mix of genuinely insightful observation (though not unique) and uninformed 
> FUD.
> 
> Some context: I haven't seriously used Wordpress in, ever.  However, I was a 
> Drupal lead developer for many years, and wrote, among other things, Drupal's 
> DBAL, Drupal's first autoloader, Drupal's PSR-3 implementation, was involved 
> in Drupal's file organization guidelines for Drupal 8+ (when Drupal adopted a 
> PSR-0/4 autoloader), and led the Drupal 8 "Modernize all the things" effort.  
> So I do have some non-trivial experience in this area.

Yes. I remember that about you as well, Crell.

> First, you're correct that there is an architectural difference between 
> "projects that assume the owner has CLI access" and those that do not.  You 
> are also correct that most of the Internals crowd comes from the former.  
> 
> However, I don't think it's fair to say that's why Internals folks "dismiss" 
> Wordpress generally.  

No, I said you dismiss the concerns of user-managed apps *because* you dismiss 
WordPress, which we know because you just gave a list of why you dismiss 
WordPress.

What I was hoping was to make the distinction that user-managed apps — 
regardless of if they are WordPress, are some other user-managed app — have 
needs that are unfair to demonize simply because you have contempt for the 
poster-child of user-managed apps.

> And yes, I fully agree that any module/package/thing needs to take into 
> account the needs of both types of projects.  As Rowan has repeated, that 
> means keeping the impact of any changes minimal, so that the Composer 
> ecosystem and WP ecosystem can TYPO3 ecosystem can build their own tooling on 
> top of it.
> 
> You'll note I did not list Drupal there.  That's because modern Drupal is 
> composer-based, and has been for many years.  I was the one that pushed hard 
> for adopting Composer, its autoloader, and PSR-4 for Drupal 8 in the first 
> place.  While much of the transition happened after I left the project, the 
> gr

Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-08 Thread Mike Schinkel
> On Jul 8, 2024, at 12:03 PM, Alexandru Pătrănescu  wrote:
> Managed to simplify it like this and I find it reasonable enough:
> function strtok2(string $string, ?string $token = null): string|false {
> static $tokenGenerator = null;
> if ($token) {
> $tokenGenerator = (function(string $characters) use ($string): 
> \Generator {
> $pos = 0;
> while (true) {
> $pos += \strspn($string, $characters, $pos);
> $len = \strcspn($string, $characters, $pos);
> if ($len === 0)
> return;
> $token = \substr($string, $pos, $len);
> $characters = yield $token;
> $pos += $len;
> }
> })($token);
> return $tokenGenerator->current() ?? false;
> }
> return $tokenGenerator?->send($string) ?? false;
> }
Hi Alexandru,

Great attempt. 

Unfortunately, however, it seems around 4.5 slower than strtok():

https://3v4l.org/7lXlM#v8.3.9 <https://3v4l.org/7lXlM#v8.3.9>


> On Jul 8, 2024, at 2:23 PM, Claude Pache  wrote:
>> Le 6 juil. 2024 à 03:22, Mike Schinkel  a écrit :
>>> On Jul 5, 2024, at 1:11 PM, Claude Pache >> <mailto:claude.pa...@gmail.com>> wrote:
>>> * About strtok(): An exact replacement of `strtok()` that is reasonably 
>>> performant may be constructed with a sequence of strspn(...) and 
>>> strcspn(...) calls; here is an implementation using a generator in order to 
>>> keep the state: https://3v4l.org/926tC <https://3v4l.org/926tC>
>> Well your modern_strtok() function is not an _exact_ replacement as it 
>> requires using a generator and thus forces the restructure of the code that 
>> calls strtok(). 
> 
> Yes, of course, I meant: it has the exact same semantics. You cannot have the 
> same API without keeping global state somewhere. If you use strtok() for what 
> it was meant for, you must restructure your code if you want to eliminate 
> hidden global state.

Hi Claude,

Agreed that semantics would have to change. Somewhat. 

The reason I made the comment was when I saw you stated it was an "exact 
replacement" I was concern people not paying close attention to the thread may 
see it and and think: "Oh, okay, there is an exact, drop-in replacement so I 
will vote to deprecate" when that same person might not vote to deprecate if 
they did not think there was an exact drop-in replacement. But I did my best to 
try to soften my words so it did not come off as accusatory and instead just 
matter-of-fact. If I failed at that, I apologize.

Anyway, your comments about needing to change the semantics got me thinking 
that addressing the concern when remediating code with strtok() could be much 
closer to a drop in replacement than a generator, assuming there is a will to 
actually tackle this. And this it small enough scope that I might even be able 
to learn enough C-for-PHP to create a pull request, if the idea were blessed.

Consider this simple code for using `strtok()`:

$token = strtok($content, ',');
while ($token !== false) {
$token = strtok (',');
}

Now compare to this potential enhancement:

$handle=strtok($content, ',', STRTOK_INIT);
do  {
$token = strtok($handle);
} while ($token !== false);
strtok($handle, STRTOK_RELEASE)

This would be much closer to a drop-in replacement, would allow PHP to keep the 
fast strtok() function, AND would address the reason for deprecation.

See any reason this approach would not be viable?

-Mike



Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Mike Schinkel
> On Jul 8, 2024, at 5:41 AM, Rowan Tommins [IMSoP]  
> wrote:
> I agree. I wrote most of the below a couple of days ago, but I don't think it 
> posted correctly, so apologies if some people see it twice: 
> 
> Autoloading is just a way to load files later, by the engine telling you when 
> a class is first needed. PHP does not, and should not, make any assumptions 
> about how files are laid out on disk; an autoloader doesn't actually need to 
> load any files at all, and if it does, it uses the same include or require 
> statements which have been in PHP for decades.

I think maybe you are replying to an earlier iteration by Michael Morris and 
have not seen the more recent iteration?  

There he explored adding an additional function to named `spl_autoload_map()` 
where the difference from `spl_autoload_register()` is that while the latter 
uses procedural code to determine what should be loaded the former would use a 
declarative map to determine what should be loaded. Then Composer and/or other 
tools could/would generate that map for PHP.

With an `spl_autoload_map()` PHP would not need to make any assumptions about 
how files are laid out on disk. Instead, PHP would use a schema of a 
yet-to-be-determined data representation format to discover  declaratively 
where files needed to be laid out on disk.

> Likewise, installing packages and defining version schemes is a completely 
> separate problem space that can probably be served by a few small tweaks to 
> Composer once the language provides the underlying functionality.
> 
> The core of the problem you seem to want to solve is this: if you have two 
> files foo_1.php and foo_2.php, which both define a class \Acme\Foo, how do 
> you load both of them, so that you end up with two differently named classes? 

That is one (1) of the core problems, yes.

> In JS, that's easy, because functions and object constructors (and "classes") 
> exist as objects you can pass around as variables, they don't need to know 
> their own name. In PHP, everything is based on the idea that functions and 
> classes are identified by name. You can rewrite the name in the class 
> declaration, and in direct references to it, but what about code using 
> ::class, or constructing a name and using "new $name", and so on? How will 
> tools using static analysis or reflection handle the renaming - e.g. how does 
> DI autowiring work if names are in some sense dynamic?

This is one of the unfortunate  aspects of PHP never makes types a first-class 
data type. But I digress.

> You've also got to work out what to do with transitive dependencies - if I 
> "import 'foo_1.php' as MyFoo", but Foo in turn has "import 'guzzle_2.php' as 
> MyGuzzle", what namespace do all Guzzle's classes get rewritten into? What 
> about dependencies that are specifically intended to bridge between packages, 
> like PSR-7 RequestInterface?

Which is a direct result of the other problem you mentioned, i.e. IOW without 
attempting to address the prior problem this would not be a problem. #fwiw

> My advice: start with the assumption that something has already installed all 
> the files you need into an arbitrary directory structure, and something is 
> going to generate a bunch of statements to load them.

And this sentence is why I chose to reply to your message.  That assumption 
itself blocks the needs of user-managed apps.

(Did you happen to read my compare-and-contrast of user-managed vs. 
developer-managed apps from a few days ago?)

I feel it is likely those who have never worked professionally in PHP on 
user-managed apps like WordPress  — which I assume describes you accurately? — 
are probably just simply unaware of the problems that your assumptions cause 
for user-managed apps. And yes, some developers have no empathy for others who 
have different circumstances, but I honestly don't think you (Rowan) are in the 
category. 

Developer-managed apps use a build tool to put all vendor code in a single 
hierarchical set of namespaces and then load needed code from there. But that 
really does not work for user-managed apps like WordPress or Drupal.  Or at 
least not as they exist today, and probably not even if they were rearchitected 
for the start.

What works for user-managed apps is that each `add-on` (`plugin` in WordPress, 
`module` in Drupal) is stored in its own self-contained directory containing 
its own vendor code — where some of the vendor code could easily be duplicated 
in another add-on — and then the user-managed apps itself manages loading of 
all add-ons itself without a PSR-4 autoloader. As it exists, there are no 
standard for how add-on filenames and directory structures much be named nor 
how they are to load their dependencies so it is impossible for WordPress or 
Drupal to take on that role using PSR-4 for them. 

Michael Morris' idea to add an `spl_autoload_map()` function would allow 
addressing the needs of user-managed apps that treat each add-on as a 
self-contain

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-07 Thread Mike Schinkel
> On Jul 6, 2024, at 8:01 PM, Michael Morris  wrote:
> 
> Some context from where I'm coming from.  I have been working exclusively in 
> React, NodeJS and Go up till about a year ago, and in Drupal before that - it 
> being 10 years since the last time I looked at WordPress. I need work though, 
> and I was offered a job where about two-thirds of my workload is a massive 
> WordPress site that has grown well outside the scope WordPress does best.  So 
> I've been getting used to it again and added some ulcers along the way.

Yes, a university semester could be filled with the dynamics of open-source 
when a project's user base and those overseeing its governance diverge. #fwiw

BTW, you don't happen to be working for my last WordPress client, are you? 😲

> 
> ...
> Many (most?) people on PHP Internals view WordPress coding standards as bad 
> and some even view addressing WordPress developers needs as bad for PHP
> 
> I really don't want to get into that crossfire. WordPress is the 800lb. 
> gorilla of the PHP app world having more server market share that is dominant 
> - how dominant depends on who you ask. The most conservative estimate I've 
> seen is about half of PHP sites are running WordPress, and the most pro-WP 
> quote I saw claimed it has around 80% share.

The reality is it does not matter if you want to or not, by arguing for a 
feature on PHP Internals that is needed more by user-managed apps like 
WordPress than developer-managed apps, you have stepped into said crossfire.

You do not get to pick your reality, your reality picks you.

>>   B/ = './path/to/B/'
> 
> It is not clear to me what a trailing slash means, and especially why it is 
> needed on the left-hand side?
> 
> This is taken from the JavaScript importmap specification, but it exists to 
> cordon off direct file includes from directory includes. Original spec here: 
> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap
>  
> And why slash here when namespaces use backslash?
> 
> Because it's the end of a path and unless you're on Windows directories are 
> delimited with /. They aren't the same thing
>  
> Also, as someone raised on DOS and then Windows only "converting" in 2009, I 
> still get confused in *nix when to use a trailing slash and when to not, so 
> this trailing slash worries me, if only for that reason alone.
> 
> I understand.  Here it's to call out that the key references a directory, not 
> a file. The value must explicitly be a directory, not a file, and a trailing 
> slash is the way that is done.  Files are not *required* to have extensions 
> after all.
> 
> Using the `@` here feels cryptic, and hard to discover and remember.
> 
> Perhaps, but this file is meant to be assembled by composer or some other 
> automated means - not by hand.  @ as a package operator is used in Node.js to 
> mark package namespaces - essentially the vendor of the package is marked 
> with @.  

I can tell your design here have been heavily influenced by your stated 
extensive experience with Node.js. Node.js' conventions probably seem second 
nature to you and thus easy for you to understand.

But for those us not steeped in Node.js, they are rather cryptic. Any time 
language designers chooses cryptic over obvious they place a large burden on 
learners and relatedly also on the experienced to deal with, correct and 
educate learners. For the languages targeting larger user bases like PHP — vs, 
say Haskell — the negative impact of cryptic can be widespread and costly in 
time spent and user base lost.  

So even if Node.js made the regrettable decision to choose cryptic over obvious 
I would implore anyone considering additions to PHP to side with obvious over 
cryptic. Even when said additions will often be automated, unless they will 
*always* be automated, such as the OpCache.

What does "obvious" mean here?  Assuming `.ini` files are use, then sections 
names that define usage, not special sigils.

> I think this would be infinitely easier to follow if packages were just 
> included in a `[packages]` section.
> 
> Packages will need to have some special handling though. 

Which does not preclude a special section for [packages].

> If, as Larry Gafield has stated, the engine cannot be made to maintain 
> multiple symbol tables, then the packages must be bound onto the master 
> symbol table.  

I have heard that repeatedly, but I have yet to hear *why*.  

PHP is just a C program, and clearly a C program can have multiple data 
structures.  Linux had a similar problem with filesystems and thus UnionFS was 
created. I'd really like to know why an equivalent architecture cannot be 
achieved with PHP's symbol table.

(If the reason why PHP "cannot be made to maintain multiple symbol tables" has 
been stated already, I could have easily missed it. If so and someone has a 
link to externals.io with the explanation, it would really appreciate that 
link.)

> But the legacy code in the package its

Re: [PHP-DEV] [RFC] Static class

2024-07-07 Thread Mike Schinkel
> On Jul 7, 2024, at 4:08 PM, Bilge  wrote:
> 
> On 24/06/2024 00:10, Bilge wrote:
>> Hi Internals!
> I am excited to announce the final implementation for Static Class is ready 
> for review at  and includes a 
> brief summary of the key semantics of the feature.
> 
> Furthermore, the 1.3 (presumed) final version of the RFC is now published at 
> .

Congrats on getting it to this point.

I support this in all but the RFC's restriction on `abstract`, as I have 
previously mentioned on the list.

-Mike

> Naturally, if there are any further weighty comments or criticisms to be 
> levied against either one of these, they may still be subject to changes as 
> appropriate.
> 
> Tomorrow the minimum period elapses before the vote may be started. 
> Discussions on this topic have been quiet for about a week as well, so if 
> there are no major concerns outstanding, I expect to announce the vote to 
> start very soon.
> 
> Kind regards,
> Bilge



Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-05 Thread Mike Schinkel
> On Jul 5, 2024, at 1:47 PM, Michael Morris  wrote:
> I went to sleep thinking about this post, on import maps in general and how 
> Composer works, specifically when you use a class map instead of the PSR-0 or 
> PSR-4 schemes.  In that mode, Composer does pretty much what I've described.  
> This got me to thinking, could setting an import map be an alternative to 
> setting an autoload function?  Would having the PHP runtime load the file be 
> faster than mucking with some userland code to do the same? And would the 
> engine be able to do anything that can't be done in userland?  I think so.

I very much like this direction of thought.

For context, when I worked with WordPress for about a decade I only ever used 
only Composer for websites but never for my own plugins, and I almost never 
used namespaces nor PSR-4 autoloaders for anything except when a plugin used 
them.  I almost exclusively used naming convensions for "namespacing" and 
classmaps for autoloading. 

Why? Was it because I was a "bad" programmer?  No, it was because when in Rome, 
you do as the Romans do.  And also because when I tried to use Composer and 
PSR-4 I was always fighting when them to do things in the way that worked best 
for WordPress.

Or to use a more modern analogy to PHP and WordPress, even though you may be 
landlocked by the country of Italy, if you are within the borders of Vatican 
City you follow the laws and conventions of Vatican City when they conflict 
with those of Italy.

> So first, I agree that supporting two formats, while convenient, increases 
> the maintenance burden, so let's just go with ini.  As far as the installing 
> function - a better name is this.

Obviously I agree with having only one format, but not sure I concur with the 
use of .ini. However, me debating against `.ini` would be me bikeshedding and 
thus I will demure here.

> spl_autoload_map( string $filepath );

Adding an `spl_autoload_map()` function and feature really resonates with me.  
As I said, I (almost?) always used class maps with WordPress so if I were to 
build another WordPress site with a future PHP that made an 
`spl_autoload_map()` available, I would TOTALLY use it.



Reading this however caused me to ponder things certain people has said 
recently — and many people have said for years on this list — and I think I am 
recognizing something that I have always known but never put the pieces 
together before.

Many (most?) people on PHP Internals view WordPress coding standards as bad and 
some even view addressing WordPress developers needs as bad for PHP. And in 
general I concur that those people are reasonably justified in their belief 
WordPress' coding standards are not the standards that PHP developer who want 
to do professional level software engineering should aspire. 

And since many (most?) PHP Internals members generally do not experience the 
issues that WordPress developers have they do not recognize that they are 
issues; IOW, "out of sight, out of mind." 

I also think some list members tend to dismiss WordPress developers pains as 
unimportant and/or think that addressing those pains have will harm PHP. 

(BTW, I recently had a dialog off-list with someone who wrote in an email that 
"Wordpress is an exception, but nobody these days treats WordPress as a valid 
example to do anything. It is an ancient piece of legacy code that has no 
bearing on modern situation and it's their problem to deal with." So I am not 
just erecting a straw man here.)

But I think what most may not consciously recognize is that WordPress is a 
different type of web app than an app build using Symfony or Laravel and 
deployed by its developers, or by some other professional developer. 

WordPress differs from the apps many (most?) developers on PHP Internals work 
with in the following way:

WordPress = User-managed app
Most = Developer-managed apps

In a Developer-Managed app developers choose which 3rd party functionality will 
be incorporated into their sites whereas with a User-managed app users choose 
which 3rd party functionality will be incorporated into their site. And that is 
the KEY difference. 

So I am wondering if we can get people on this PHP Internals list who dismiss 
the needs of WordPress developer BECAUSE it is WordPress to recognize that 
User-Managed apps ARE a class of PHP applications have needs that deserve to be 
addressed?  

Two (2) unmet needs of User-Managed apps that "standard" PHP currently does not 
address come to mind:

User-managed apps needs to be able to handle both:

1. User-added add-ons ("plugins" in WordPress, "modules" in Drupal) that have 
conflicting dependencies, and

2. Add-on directory structures that do not follow a PSR-4 directory hierarchy.

As for #2, even if those apps could rearchitect their existing directory 
structure they cannot realistically be expected to do with because of the huge 
BC issues their users would experience. 

And newly created User-managed apps may st

Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-05 Thread Mike Schinkel

> On Jul 5, 2024, at 1:11 PM, Claude Pache  wrote:
>> Le 25 juin 2024 à 16:36, Gina P. Banyard  a écrit :
>> https://wiki.php.net/rfc/deprecations_php_8_4
> 
> 
> * About strtok(): An exact replacement of `strtok()` that is reasonably 
> performant may be constructed with a sequence of strspn(...) and strcspn(...) 
> calls; here is an implementation using a generator in order to keep the 
> state: https://3v4l.org/926tC 
Well your modern_strtok() function is not an _exact_ replacement as it requires 
using a generator and thus forces the restructure of the code that calls 
strtok(). 

So not a drop-in — search-and-replace — replacement for strtok(). But it is a 
reasonable replacement for those who are motivated to do the restructure.



Just out a curiosity for the performance of your modern_strtok() function so I 
benchmarked it and found it takes — on rough average — about ~2.5 times as long 
to run compared to when using strtok():

https://3v4l.org/AMECf#v8.3.9 

That makes yours the fastest alternative I have benchmarked, but significantly 
still slower than strtok().

I was curious to see if I could improve its performance by avoiding the 
generator, but that just made it slightly worse, e.g. taking — on rough average 
— ~2.75 times as long to run as `strtok()`:

https://3v4l.org/ZVS5Md#v8.3.9 

#fwiw

-Mike

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Mike Schinkel
> On Jul 4, 2024, at 9:16 PM, Michael Morris  wrote:
> On Wed, Jul 3, 2024 at 11:11 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> So I've had more time to mull this over, and some research, and I think I 
> have an approach.
> 
> First, instead of 'import', use 'require_module'.  The parsing rules for 
> require_module differ from require how the file is parsed, a subject for 
> another time.  Also, it's parallel to what is to follow.

+1 

> Speaking of new functions, let's start with these
> 
>   spl_set_include_ini_map('importmap.ini');
>   spl_set_include_json_map('importmap.json")

Those are a mouthful! 

> The json file is pretty much identical to the JavaScript importmaps. The ini 
> file looks like this
> 
>   root = "/absolute/path/to/application/root"
> 
>   [imports]
>   square = "./path/to/square.js"
>   circle = "./path/to/circle.js"
>   other/ = "./path/to/other/"
> 
>   [scopes]
>   \A[square] = './path/to/square/in/namespace/A/a.js'

I assume rather than `.js` you mean `.php` files in your example?

Also, I am not following how these imports and scopes will relate to the actual 
PHP code that would be affected/using packages.

> Whichever format is used is a matter of personal preference. The file can be, 
> and likely should be, written by composer or some future package manager.

Part of me likes the flexibility of two formats. The other more pragmatic part 
of me says stick with one format for fewer related bugs and to reduce the 
effort to support it for internal code and by 3rd parties.

Unless it can be fully cached by opcache I would think it would need to be the 
format that can be parsed the fastest, which could be binary like a Protobuf 
file.

> The root attribute in the map sets the root for all relative paths given in 
> the map.

Are you saying that a publisher of a package would need to write the absolute 
path to their `importmap.*` file. How will that work?  Even for a bespoke app 
Composer may not have enough access to the server to know this, and 3rd party 
packages will definitely not know it for their users. At least I don't think so.

Also, at this point trying to keep track of all your ideas is impossible, at 
least for me. Have you reconsidered putting it in a repo or at least a Gist yet 
so it is easier to see the scope of your current ideas about packages?

-Mike



Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Mike Schinkel


> On Jul 4, 2024, at 3:05 PM, Chuck Adams  wrote:
> 
>> On Jul 4, 2024, at 12:02 PM, Mike Schinkel  wrote:
>> 
>> The point being that PHP is free to choose how they are defined with respect 
>> to PHP.
>> 
>> To which I will add "as long as the terms are used consistently.”
> 
> ...but whatever makes sense for PHP is what’s best. 

Definitely.

-Mike


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-04 Thread Mike Schinkel
Hi Chuck,

> On Jul 4, 2024, at 11:05 AM, Chuck Adams  wrote:
>> On Jul 3, 2024, at 6:16 PM, Michael Morris  wrote:
>> 
>> Hello all. Hitting reset again as the primary problem at hand has become 
>> clear.  Let's recap it.
>> 
>> Autoloading is great for loading packages, but it can't load different 
>> versions of the same package at the same time.  Why would you want to do 
>> that?
>> 
>> When you don't have full control of the code.in 
>> 
>> For example, consider Drupal.  It is running Twig at some version of 3 at 
>> the moment. Suppose Twig 4 is introduced with significant backward 
>> compatibility breaks (Not saying the authors would do such a thing) but also 
>> wonderful features.
>> …[snip]...
>> This is why I advocate a new keyword for this - import.  Import’s behavior 
>> is most similar to require_once, but it doesn't have to be the same.  Since 
>> it is a new entrypoint into the engine the way the engine considers the code 
>> can be different - whether slightly different or radically different is a 
>> debate for another time. I'm going to stick with only those changes that 
>> make sense in the context of package links.
> 
> 
> I’m seeing a lot of conflation of ‘module’ and ‘package’ in these 
> discussions, and to me they mean different things:
> 
> * A module is a sort of “first class namespace” that can export symbols and 
> import others.  Think ES5 or python modules.  If you don’t want it 1-1 with 
> files, think Perl modules.
> 
> * A package is an “installable” unit that provides modules, among other 
> things.  Packages have metadata, the most important piece of which is a 
> machine-readable version.

Your definitions are language-specific.  For example, in Go the definitions for 
those terms are the opposite of how you defined them.

The point being that PHP is free to choose how they are defined with respect to 
PHP.  

To which I will add "as long as the terms are used consistently."

-Mike

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-03 Thread Mike Schinkel
> On Jul 3, 2024, at 10:31 PM, Michael Morris  wrote:
> 
> On Wed, Jul 3, 2024 at 9:56 PM Mike Schinkel  wrote:
> 
> There are ~6300 uses of the keyword `import` on GitHub:  
> 
> https://github.com/search?q=import+language%3APHP+symbol%3A%2F%5Eimport%24%2F&type=code
> 
> That's a lot of BC breakage for some people.
> 
> No worse than PHP 7's keyword introductions.

True. 

OTOH, if you don't actually have to break BC for discretionary changes, then it 
would be better not to.

>> Import's behavior is most similar to require_once, but it doesn't have to be 
>> the same.  Since it is a new entrypoint into the engine the way the engine 
>> considers the code can be different - whether slightly different or 
>> radically different is a debate for another time. I'm going to stick with 
>> only those changes that make sense in the context of package links.
> 
> When you first proposed modules I was understood (wrongly?) that you were 
> proposing imports to be a statement that imported into file scope and then at 
> the end of loading the file PHP would flush those symbols just like how (I 
> think?) JavaScript imports work (I am ignoring the complexity closures add to 
> simplify our discussion here.)
> 
> That was the first iteration, yes.  I am adjusting to the feedback on the 
> list.  JavaScript does imports the way it does because of how files scope, 
> and how the module system itself scopes, which isn't readily retrofitted onto 
> PHP.

I think it *can* be retrofitted to PHP, but that is a different issue and I 
won't derail your discussion to suggest it in this thread.

> Also, at the time I was toying around with the format and had yet to hit upon 
> the situation where it could be useful, that being versioned files.
>  
> This sounds like you are saying `import` would (instead?) be dynamic like 
> `include*` and `require*` and any symbols loaded with `import` would continue 
> their lifetime until the program is finished or the page is loaded, depending 
> on how the program is run?
> 
> Yes, because that is how PHP itself does work under the hood, at least for 
> php file includes. How it would go about doing this when resolving .so or 
> .dll extensions is another matter.  Does it have to be this way? That's the 
> hint I've gotten from the feedback but only a core contributor with 
> experience working on the engine could say for sure.
>  
> I ask because when I was envisioning page scope being added to PHP I was also 
> envisioning that PHP could perform more optimizations if the new symbols only 
> affected the currently loaded page. If you are proposing beyond-page lifetime 
> then that precludes this optimizations which is not a deal killer but is a 
> disappointment.
> 
> Whether the optimizations affect the file on load depends on what's being 
> optimized to be honest. There is still an opportunity here.

Where do you see opportunity for optimization — assuming your vision of imports 
— that is not already a potential for optimization?

>  
>> Now we have \B\foo();  This makes it relatively easy to have two different 
>> versions of the package running since in our own code we can always 
>> reference the foo in the B namespace. But while that allows limited package 
>> versioning, it doesn't solve the multiple extensions wanting to use the new 
>> stuff problem outlined above.
> 
> Consider the following parts of an application:
> 
> 1. Bespoke app
> 2. "Enterprise Reports" library
> 3. Twig v3 used by "Enterprise Reports"
> 4. "ProductsPro" library
> 5. Twig v4 used by "ProductsPro"
> 6. "PP2ER Connector" library
> 
> Given your scenario I guess you assume Enterprise Reports would import Twig 
> v3 as maybe `ER\Twig` and ProductsPro would import Twig v4 as maybe 
> `PP\Twig`, right?
> 
> Correct.
>  
> 
> How does the PP2ER Connector use Twig?  
> 
> Depends on which one it wishes to use, \ER\Twig or \PP\Twig
>  
> Does it create it own `PP2ER\Twig`?  What if the connector needs to use the 
> `ER\Twig\Environment` from ProductsPro with the 
> `Twig\Loader\FilesystemLoader` from Enterprise Reports where those classes 
> have private and protected properties that are simple not composable, and 
> especially not across versions.
> 
> I've never seen cross version mixing like you're describing so I didn't take 
> it into account. That said, the extant copies of those classes will be 
> variables, and hopefully not global variables.

I have with WordPress plugins. 

I wish I could say exactly what, where and when, but sadly that knowledge was 
lost to the mists of time.

> Or what 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-03 Thread Mike Schinkel
> On Jul 3, 2024, at 8:16 PM, Michael Morris  wrote:
> Can PHP support multiple packages without rewriting the whole engine?  I 
> think so, but it isn't trivial, and the side effects need to be cordoned off 
> so that those who need this complexity can have it while the beginning and 
> intermediate coders can ignore it just like they ignore strict comparison 
> operators and strict typing unless a library they are trying to use foists it 
> on them.
> 
> This is why I advocate a new keyword for this - import. 

There are ~6300 uses of the keyword `import` on GitHub:  

https://github.com/search?q=import+language%3APHP+symbol%3A%2F%5Eimport%24%2F&type=code
 

That's a lot of BC breakage for some people.

For this proposal, would one of these not be acceptable instead (assuming that 
the compiler could handle `import` in this way w/o it being a new reserved 
word)?:

```
include "file.php" as import
use import "file.php"
```

> Import's behavior is most similar to require_once, but it doesn't have to be 
> the same.  Since it is a new entrypoint into the engine the way the engine 
> considers the code can be different - whether slightly different or radically 
> different is a debate for another time. I'm going to stick with only those 
> changes that make sense in the context of package links.

When you first proposed modules I was understood (wrongly?) that you were 
proposing imports to be a statement that imported into file scope and then at 
the end of loading the file PHP would flush those symbols just like how (I 
think?) JavaScript imports work (I am ignoring the complexity closures add to 
simplify our discussion here.)

This sounds like you are saying `import` would (instead?) be dynamic like 
`include*` and `require*` and any symbols loaded with `import` would continue 
their lifetime until the program is finished or the page is loaded, depending 
on how the program is run?

I ask because when I was envisioning page scope being added to PHP I was also 
envisioning that PHP could perform more optimizations if the new symbols only 
affected the currently loaded page. If you are proposing beyond-page lifetime 
then that precludes this optimizations which is not a deal killer but is a 
disappointment.

> Now we have \B\foo();  This makes it relatively easy to have two different 
> versions of the package running since in our own code we can always reference 
> the foo in the B namespace. But while that allows limited package versioning, 
> it doesn't solve the multiple extensions wanting to use the new stuff problem 
> outlined above.

Consider the following parts of an application:

1. Bespoke app
2. "Enterprise Reports" library
3. Twig v3 used by "Enterprise Reports"
4. "ProductsPro" library
5. Twig v4 used by "ProductsPro"
6. "PP2ER Connector" library

Given your scenario I guess you assume Enterprise Reports would import Twig v3 
as maybe `ER\Twig` and ProductsPro would import Twig v4 as maybe `PP\Twig`, 
right?

How does the PP2ER Connector use Twig?  Does it create it own `PP2ER\Twig`?  
What if the connector needs to use the `ER\Twig\Environment` from ProductsPro 
with the `Twig\Loader\FilesystemLoader` from Enterprise Reports where those 
classes have private and protected properties that are simple not composable, 
and especially not across versions.

Or what it he app itself needs to use the functionality of both in a way that 
requires access to `private` and/or `protected` property values or methods 
across the two versions?

> So we have to call out the version in code, like so.
> 
>   import 'file.php v1.0.0';

Where will PHP be able to get the version number in a performant manner, 
remembering that the problem to be solved is dependencies of dependencies so 
you cannot rely on a strict directory structure with version numbers unless a 
non-PSR4 autoloader format is introduced and widely adopted?

Will packages need to ship `composer.lock` and developers deploy them? Will 
that be performant and secure enough?

What about libraries and packages that do not use Composer?  How will WordPress 
handle this with plugin dependencies?

-Mike



Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-03 Thread Mike Schinkel
> On Jul 3, 2024, at 8:24 PM, Michael Morris  wrote:
> On Wed, Jul 3, 2024 at 7:52 PM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> Me personally, the opinions that I do not like are the one-symbol-per file 
> assumption, which is also a key issue I have with PSR-4. 
> 
> That's a PSR-4 issue, not an autoloader one. Autoloaders, even in composer, 
> can use class maps to discover which file must be loaded to make the symbol 
> accessible, even if multiple unused symbols in that file come along for the 
> ride.

My statement you are commenting on was about `spl_autoload` and PSR-4, full 
stop.

> 2. Symbol encapsulation — Allowing symbols to be hidden from code that should 
> not use them.
> 
> Uhm, I'm not formally trained so that one got by me - could you please give 
> an example of this? I might have posted one already without realizing it.

Which part?  Symbol, or Encapsulation?

If Symbols, that is just the collective name for classes, interfaces, enums, 
functions, constants and variables.

If Encapsulation, then that means symbol hiding.  PHP offers only limited forms 
of symbol hiding with `private` and `protected`.  Currently it is not possible 
in PHP to have a top-level symbol in a namespace — vs. just a function, 
property or constant enclosed in and as part of a class — that a developer can 
disallow other developers from accessing via regular access methods, e.g. 
instantiating the class, implementing the interface, using the constant, 
calling the function. etc.

Does that answer?

-Mike

Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-03 Thread Mike Schinkel
> On Jul 3, 2024, at 7:17 AM, Stephen Reay  wrote:
> 
> Sent from my iPhone
> 
>> On 1 Jul 2024, at 23:33, Mike Schinkel  wrote:
>> 
>> Autoloading runs userland code. This means it has the potential conflict 
>> between different packages with different autoloaders
> 
> *Can* run userland code. It doesn't *have to*; FYI  spl_autoload 
> (https://www.php.net/manual/en/function.spl-autoload.php 
> <https://www.php.net/manual/en/function.spl-autoload.php>) has existed since 
> php5.1 and works amazingly well. 

Excellent point!  

It has been so long that I have seen anyone use that, however, I actually 
forgot it exists. 

> On Jul 3, 2024, at 10:47 AM, Stephen Reay  wrote:
> Neither of which is the point I was making - someone claimed that autoloaders 
> are implicitly userland code. The point is they don't *have* to be, and there 
> is a perfectly useable one built in to the SPL extension; if it's "too 
> opinionated" (or the opinions are ones you don't like), it's hardly the most 
> in-depth of functions, and it already *has* configurable parts, so adding in 
> more control shouldn't exactly require a rocket scientist to add, for 
> example, the ability to use the original case of the class name.

Me personally, the opinions that I do not like are the one-symbol-per file 
assumption, which is also a key issue I have with PSR-4. 

#fwiw.


> On Jul 3, 2024, at 12:51 PM, Matthew Weier O'Phinney 
>  wrote:
> I'm following the packaging threads closely, and the one thing I've failed to 
> see a solid argument for is _what problems_ the current approach of using 
> namespaced code doesn't address. I can definitely see a need for marking 
> things as package private (i.e., not part of the publicly consumable API), 
> but that also feels like something we could address in other ways. 

Understanding that the thread has been a brainstorming thread more than a 
proposal thread — ignoring whether or not it is effective to brainstorm on this 
list because of interpersonal list dynamics — my two cents in answer to the 
question of "What problem(s) are we trying to solve?"

1. Side-by-side symbol loading — PHP currently makes it difficult if not 
impossible to use different versions of the same library as dependencies of 
higher-level dependencies.

2. Symbol encapsulation — Allowing symbols to be hidden from code that should 
not use them.

3. Multiple symbols per file — Finding an approach that would be able to gain 
wide adoption for multiple symbols per file— without effectively requiring an 
app to load all source on each page load — to better support locality of 
behavior.

See: https://htmx.org/essays/locality-of-behaviour/

4. Unified loading — Currently constants, variables, functions, are the 
have-nots of the autoloading realm. Providing a manner for loading them, and a 
unified manner across all symbols would be even better.

5. Community buy-in — While not a goal in and of itself, ideally there would be 
a solution that would gain broad support over time so the approach does not get 
dismissed by the majority of developers simply for reasons such as it is not 
what they are already familiar with. Having official PHP endorsement would go a 
long way to address this.

-Mike



Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-01 Thread Mike Schinkel
> On Jul 1, 2024, at 5:07 PM, Rob Landers  wrote:
> 
> On Mon, Jul 1, 2024, at 18:22, Mike Schinkel wrote:
>> > On Jul 1, 2024, at 7:57 AM, Arvids Godjuks > > <mailto:arvids.godj...@gmail.com>> wrote:
>> > 
>> > TL;DR: As a userland developer, in my opinion, this is just a downgrade 
>> > from what we have now. Enhance namespaces to have the ability to have 
>> > internal/private classes, interfaces, enums and constants. That's about it.
>> 
>> Please note my comments that follow do not mean I am in support of this 
>> package proposal as presented. 
>> 
>> > Autoloading is one of the best killer features of PHP - love it or hate it 
>> > - it's your personal preference.
>> 
>> Two really solid reasons to hate autoloading as implemented in PHP:
>> 
>> 1. Autoloading runs userland code. This means it has the potential conflict 
>> between different packages with different autoloaders, it means there can be 
>> buggy autoloaders, and it means that when using XDEBUG every time a new 
>> symbol is found when the developer is single-step debugging the developer 
>> will be dropped into the autoloader and then best case they then immediately 
>> trace out. All of these aspects a major PITA and time waster and make 
>> debugging more exhausting than it needs to be.
> 
> FWIW, (in Intellij at least), you can set it to skip those files.

I just went and looked again, and after having requested the feature in 
PhpStorm over a decade ago, it appears they finally have added it. I had given 
up that they ever would, and must have missed it when they added it. Thanks for 
prodding me to look for it.

Of course that doesn't help if the source of the bug is in the userland 
autoloader code, but is an improvement much of the time otherwise.

-Mike

Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-01 Thread Mike Schinkel
> On Jul 1, 2024, at 4:54 PM, Jordan LeDoux  wrote:
> On Mon, Jul 1, 2024 at 11:09 AM Mike Schinkel  <mailto:m...@newclarity.net>> wrote:
> 
> > and I'm fairly certain after keeping up with the thread that it is almost 
> > universally not what people want. Most people just want the toolbox be 
> > "finished" so to speak, not get a completely new one in addition that has 
> > no compatibility with the old one.
> 
> I get it. I am no longer proposing an alternative to the autoloader. PHP 
> developers are comfortable with autoloading and that is that.
> 
> But that does not mean that I cannot tell you and others the emperor has no 
> clothes in hopes that people eventually see that there can be better 
> alternatives.
> 
> -Mike
> 
> I'm not sure that constantly reiterating a point that everyone already knows 
> but simply disagrees with is productive for the list, considering that the 
> objection boils down to "but I don't like it" instead of "here are the 
> concrete technical drawbacks". All of the objections you had seemed to be 
> from the perspective "but what if the developer is only allowed 100 files on 
> disk and only uses notepad to edit the code?" I don't think those are 
> technical drawbacks personally, I think those are developers that need to at 
> least start programming like they are living in 2005.

Given the paragraph I wrote that started with "I get it..." I was planning on 
not making comment on topic.

>  All of the objections you had seemed to be from the perspective "but what if 
> the developer is only allowed 100 files on disk and only uses notepad to edit 
> the code?" I don't think those are technical drawbacks personally, I think 
> those are developers that need to at least start programming like they are 
> living in 2005.

However, since you GROSSLY mischaracterized my argument, I am going to call you 
out on that bit of attempted demonization of my argument on your part.  

But I won't repeat the argument because, why bother?

-Mike

Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-01 Thread Mike Schinkel
> On Jul 1, 2024, at 1:07 PM, Dusk  wrote:
> 
> On Jul 1, 2024, at 09:22, Mike Schinkel  wrote:
>> 2. Autoloading effectively necessitates that every symbol be in its own 
>> separate file.
> 
> How so? While Composer "recommends" PSR4 autoloading with one class per file, 
> other configurations are entirely possible,

I spoke inartfully, sorry. 

The culture of projects throughout the PHP ecosystem has resulted in most 
projects being one class per file, and there have not evolved any 
defecto-standard tools for creating those classmaps further ensuring PSR4 
ubiquity.

> either with Composer's autoload.classmap (which uses a precomputed class -> 
> filename table), or with a custom autoloader.

And, refer back to reason  #1 to hate autoloading in PHP.

> On Jul 1, 2024, at 1:28 PM, Arvids Godjuks  wrote:
> 
> But that is why interoperability in PHP world is so high. When it was 
> introduced, it allowed enabling autoloading for most code bases out there 
> regardless of what their structure was and still is. Sure, you have to be 
> careful how you do it, but that is also not really a userland concern - most 
> of those have been implemented once and then almost never touched :) The 
> community has settled on a general approach since naturally and that's how 
> vast majority of people write their code. Buggy code is buggy code, it really 
> has not much to do with the autoloading and with how people write buggy code 
> :) You are blaming the hammer for user trying to nail the screw into wood :) 

Two things can be true at the same time.  Something can have a historical 
benefit but not be ideal moving forward when compared to potential future 
alternatives.

The major benefit that autoloading has today is inertia. Yes, that's a huge 
benefit. But that does not make autoloading beneficial.

> You can already sidestep autoloader by adding a require statement to any file 
> and loading everything without triggering autoload. 

There is not a standard way to sidestep the autoloader that has majority 
support in 3rd party packages. It's a roll-your-own thing.

> It's far more powerful in userland because it allows people to do whatever 
> they want with it if they do not like the standard autoloader(s). 

The only reason people think about how they want autoloading to work is because 
they have to. Technology is supposed to evolve to eliminate rote and low-value 
add tasks.

By the same token I could say we should introduce the ability in userland for 
people to modify the implementations of standard library functions so people 
could do whatever they want with it if they do not like the standard 
implementations. 

But clearly that latter would be crazy talk.

> That's just how PSR-4 standard was written and works, and it's a good default 
> for a reason. On small projects - sure, I can see it being overkill. But I 
> haven't worked on a small project in a decade and I rarely have that little 
> code in one file that I would want to stuff all together in one file. I do 
> use PHPStorm, so it is very adapted to how most PHP projects are and provides 
> excellent navigation abilities that fit the PSR-4 and that way of structuring 
> projects. Vast part of the community uses it. It's a standard in a lot of 
> companies for a reason.

Again, I will say this is Stockholm syndrome.

> See my reply to autoloading things above - you can eliminate the autoloader 
> triggering easily in probably 15-30 minutes flat. 

But to do so there is not one single way that is reality standard. So I have to 
own maintenance of that low-value code.

> There are aspects to this that go beyond just technical aspects. Wherever 
> when implementing autoloading people were secret geniuses, stumbled into it 
> accidentally or just had practical needs themselves that they just 
> implemented in this way - it has been a major turning point in PHP's life and 
> has transformed the ecosystem into what it is today together with the rise of 
> the composer package manager. I have seen people talk about visibility in 
> namespaces, package concept and all that, but every time it was building upon 
> existing autoloading mechanics - some adding capabilities to them, modifying 
> them, having new type of autoloader. But I have never encountered anyone in 
> this community in 20 years i have been an active part of it to propose a 
> radical change like this 

That is probably because you all have been working mostly in PHP and not 
experiencing better alternatives. BTW, NodeJS/Javascript is NOT a better 
alternative, IMO.

Besides, what I proposed earlier was not a "radical change." Characterizing 
something as "radical" is just a rhetorical tactic used to discredit said 
thing. What I proposed was very incremental and 

Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-01 Thread Mike Schinkel
> On Jul 1, 2024, at 9:00 AM, Larry Garfield  wrote:
> 3. Using URLs as the package naming system is the dumbest thing Go ever did.  
> Let's not replicate that. :-)

This is probably the wrong thread and maybe even the wrong list to discuss 
this, but having programmed in PHP for a decade and then half a decade also in 
Go I think using URLs as the package naming system to be one of the smarter 
things Go ever did. 

So I would really like to hear objective arguments as to why you think Go using 
URLs for packages is dumb. Feel free to take this to another thread, to a 
private email, or elsewhere if not appropriate for here.

-Mike

Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-01 Thread Mike Schinkel
> On Jul 1, 2024, at 7:57 AM, Arvids Godjuks  wrote:
> 
> TL;DR: As a userland developer, in my opinion, this is just a downgrade from 
> what we have now. Enhance namespaces to have the ability to have 
> internal/private classes, interfaces, enums and constants. That's about it.

Please note my comments that follow do not mean I am in support of this package 
proposal as presented. 

> Autoloading is one of the best killer features of PHP - love it or hate it - 
> it's your personal preference.

Two really solid reasons to hate autoloading as implemented in PHP:

1. Autoloading runs userland code. This means it has the potential conflict 
between different packages with different autoloaders, it means there can be 
buggy autoloaders, and it means that when using XDEBUG every time a new symbol 
is found when the developer is single-step debugging the developer will be 
dropped into the autoloader and then best case they then immediately trace out. 
All of these aspects a major PITA and time waster and make debugging more 
exhausting than it needs to be.

2. Autoloading effectively necessitates that every symbol be in its own 
separate file. This needlessly bloats number of files and directories by more 
than an order of magnitude — see my numbers from recent discussion — and that 
also mean related code is located farther away from other related code. This 
can be worked around but the workarounds I've seen are all fragile and unable 
to be generic, and few 3rd party packages do this.

> I've seen a sizeable chunk of developers that come from other languages 
> discover PHP's autoloading and their minds just get blown.

It is unclear to me if by saying their "minds just get blown" if that means you 
think they see it as a positive or negative?

As a developer who spent a decade in PHP and then branched out and added Go to 
my repertoire I can tell you one of the nicest differences I experienced was 
not having to deal with an autoloader during debugging, and not being so 
constrained was to have to create a new file for every symbol. Go projects need 
an order of magnitude fewer files. It is just so much easier to grok the source 
code of a Go project compared to a PHP because of this one simple fact. Now 
when I program in PHP I find myself constantly cursing the fact that I have to 
deal with the autoloader.

BTW, I know Go is a pre-compiled language unlike PHP, but that does not 
necessarily preclude PHP from having a better solution for code loading and 
organization.

> Performance has not been an issue for a long time due to opcache and all the 
> optimizations that have been done to it and ability to preload bytecode. Then 
> there are things like  FrankenPHP, Swoole, ReactPHP and others that entirely 
> sidestep that issue. And then there's the active development of JIT engine - 
> just let the people working on the implementation time to cook.

This reads to me like Stockholm syndrome, e.g. "My captors still hold me 
captive, but they no longer beat me every day."

> It works, worked for a long time and there are not so many things wrong with 
> it to entirely upend the whole ecosystem and split the language. Here's your 
> HARD REMINDER about Python 2 => Python 3 and how that went and is still 
> somewhat ongoing.

Totally agree on that.

-Mike

  1   2   3   4   5   6   >