Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127288 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 665071A00BC for ; Mon, 5 May 2025 04:44:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1746420132; bh=+nFM7Ul5/VeBx5SP60m1FSSnhhkegMcmT+mWaDtLcT4=; h=Date:From:To:In-Reply-To:References:Subject:From; b=hDVHfBbATwfX2FwLB6UgQECGyB0FW0Zx5lV2hQIiEa1/4LB1I4/2UNCH3lC7gF4Cf 8yCf/0fL4xQ/OljjYqa9UlE5hxVrzAPHqIieGQBiFuOfhAnOrUwa3r6QFGKaT46c4P rIHFrc4H/m9cxdHfG1bs8QwjufDQMTV/51Xyu8xRU/9feVe+k4AY/ts8XnpnHh58hx KSN0WVJcAVQueBLGeY4QA8GRXYzGQy/w6yJXx7zBWHgbM7YzoGarGVqvydWsUkCYM3 QGLYCJ2IaJ6KUOG+aumGcoxKM5gKi2nNGwvNsoef8Y72WkyTHu84kcbS4EggFbHYoX TFpRsmcJoExkQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 32D1B180057 for ; Mon, 5 May 2025 04:42:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from fout-a7-smtp.messagingengine.com (fout-a7-smtp.messagingengine.com [103.168.172.150]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 5 May 2025 04:42:08 +0000 (UTC) Received: from phl-compute-10.internal (phl-compute-10.phl.internal [10.202.2.50]) by mailfout.phl.internal (Postfix) with ESMTP id C60C81380158 for ; Mon, 5 May 2025 00:44:22 -0400 (EDT) Received: from phl-imap-02 ([10.202.2.81]) by phl-compute-10.internal (MEProxy); Mon, 05 May 2025 00:44:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to; s=fm3; t=1746420262; x=1746506662; bh=yEVb45iRxERpMFrAW+X4W dBvhltmkMR78synkGO2ht4=; b=V77MCgpWuv2jdf4Q5gAxp7NR5lvQT7tTT6x/E hXHnYCd+Lfjk5S/eUsTycUHgzQIMJk84i3VXAMQzY0bX2tt3nzJsqYcIsW4v15mf KNdEoDFCM1b+Tc+Ci0or5DBK+6NhtBikfNSDh4hjou1vh/v66T5EVq3K0xh+XuOo 5+XdptlsJZrqVQ3CBPsGlV/CnEBjxez8CR1xKbpYuQDXQzbXZJ724PI3t+LtHXYh Ka3eruYs/OAVOMyLAfpEW92uv8XRWoMK2tQEIeuigmlt8hXrDZAl7HdVvzMTRJ+a Ql6NI5HabIxoGAtC76DCsH+bPCjVj9b5XTgj1ro1O6YUQCs1A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1746420262; x=1746506662; bh=y EVb45iRxERpMFrAW+X4WdBvhltmkMR78synkGO2ht4=; b=WeOVjQECSloO7oD0A 544QQp8419pO4vPISyZoqgFNyd7YkhGtUQhYh9bHK90sHH9cM9SzKfTLDWMZ8SEB YZly88P6i+JMQuWvEnRCQiw+pqNKH7BXqFwPGCHNmVSUEQz9/EDqEgiIX1ygNwqF UtOuIDSd01qRi1GsYMsRhnRBp8mSR3Tt52Y7ApL9OdEMrgvpvQcCzYV5IixirEXz fgj9lC0e/EDsjkyteJ+A0rmMW24xTze3MovVMeCL3TecWpB/776fFcA0WC+X2D9j P8i6G8hdr1Nd82XfBic9/tHTtjpqXPERLBoJQjPeFZPneUitzbhPARwIMyMR+7Zs fgQHw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkedtudeiucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpih gvnhhtshculddquddttddmnecujfgurhepofggfffhvffkjghfufgtgfesthhqredtredt jeenucfhrhhomhepfdfnrghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrh hfihgvlhguthgvtghhrdgtohhmqeenucggtffrrghtthgvrhhnpeehjeefvefgfeduteff ffdvheeiudekieefleevvdduiefgkeehvdevheffvdegteenucffohhmrghinhepghhith hhuhgsrdgtohhmnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhf rhhomheplhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhmpdhnsggprhgtphhtth hopedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehinhhtvghrnhgrlhhssehl ihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 6839CB0006A; Mon, 5 May 2025 00:44:22 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 X-ThreadId: T2a4bd2276428daf8 Date: Sun, 04 May 2025 23:43:29 -0500 To: "php internals" Message-ID: In-Reply-To: References: <9cbbe803-5fd1-4011-b42e-033d4ede3fe9@app.fastmail.com> <15a33d20-47c1-443e-aafd-f39bd8f367c1@app.fastmail.com> Subject: Re: [PHP-DEV] Modules, again. Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable From: larry@garfieldtech.com ("Larry Garfield") On Sun, May 4, 2025, at 5:40 PM, Michael Morris wrote: > On Sun, May 4, 2025 at 5:38=E2=80=AFPM Larry Garfield wrote: >>=20 >> > PHP Code ----------------------------------------------------------= ------------- >> > >> > namespace MyModule; >> > >> > yield function sum(a, b) { return a + b; } >> > >> > -------------------------------------------------------------------= ------------- >>=20 >> Every module author changes their code. (Which is reasonable.) > > Actually no. PHP Modules are only needed if the package author wants=20 > the functionality modules provide - specifically having an independent=20 > symbol table and autoload queue. Existing packages don't have to chang= e=20 > in any way. If a module includes one their symbols will be written=20 > into that module's symbol table. If two modules include the same=20 > package they each write it onto their own respective symbol tables. I thought it self-evident that I was referring to "every package author = that wants to expose their package as a module", not literally every own= er of a package on Packagist. (Though presumably over time those two ci= rcles will increasingly overlap.) But let me make that explicit. And, as noted, requiring the author of a package to introduce new syntax= in order to turn the package into a module is a reasonable expectation.= I have no issue with that. >> > PHP Code ----------------------------------------------------------= ------------- >> > >> > use require 'mymodule.php'; >> > >> > echo MyModule::sum(3, 4); >> > -------------------------------------------------------------------= ------------- >>=20 >> Every caller changes their code, to use `use require` and to use the = pseudo-class syntax to call the function. > > Again, if they want module functionality. No one *has* to do this - th= e=20 > new syntax was carefully chosen to let the existing syntax work as it=20 > always has. If my library is structured as a module, with yield and stuff, then how = exactly would someone use it without using the `use require` syntax at l= east? >> > PHP Code ----------------------------------------------------------= ------------- >> > >> > use sum require 'mymodule.php'; >> > >> > echo sum(3, 4); // 7 >> > -------------------------------------------------------------------= ------------- >>=20 >> Removes the pseudo-class syntax, but still has the "use sum require..= ." change for the consumer. >>=20 >> As described, the implication is that the millions of existing >>=20 >> use Some\Class\Here; >>=20 >> lines in code in the wild will... not work if the Some\Class package = becomes a module? =20 > > This is left up to the autoloader. When you call that use statement=20 > from the main thread the autoloader receives args ("Some\Class\Here",=20 > false). When you call that use statement from a module the autoloader=20 > receives arguments ("Some\Class\Here", "RequestingModule"). If the=20 > autoloader isn't rewritten it will ignore the 2nd argument and serve=20 > out the same code for both module and main thread. I believe you are grossly misusing the term "thread" here. There is no = separate execution thread involved, just scoped symbol tables. See note further down about the rest of the points raised here. > HOWEVER, modules can define their own autoloaders and those will be=20 > executed independent of the autoloader on the main thread. Furthermore= ,=20 > the autoloader on the main thread will not be used unless the module=20 > opts into using it. Nothing in your initial post discussed any of this, or even implied it. >> I think that's what's implied, but it's not clear. If that triggers = autoloading, how does the autoloader know how to find it? It needs to k= now the module name, which as described is the file name of the module, = not the class.=20 > > By convention the filename might be the module name, but that a=20 > convention of package management, autoloading, some future PSR-X that=20 > is far, far outside of scope here. The module's name is its namespace!= =20 > For a module a namespace isn't just a run time string replacement, it=20 > has a very real effect. The namespace will be the 2nd argument of ever= y=20 > autoload call made from the module or any file required/included in it= s=20 > scope. Existing packages don't need to be aware this is happening -=20 > but the module can have a custom autoloader that always loads version = 2=20 > of a popular package even if composer on the main thread is set to=20 > include version 3. =20 From the proposal: > use require 'mymodule.php'; > > echo MyModule::sum(3, 4); How exactly does MyModule get defined? That is not at all clear. >> Since the module name is the file name, that means if a module has 50= internal classes, it must be in the same file. Hence, giant files. > > I hope you can see why this isn't true now. The module entry file can=20 > simply yield out its public assets like so. > > namespace Vendor\Package; > require 'autoloader.php'; > yield { A, B, C } ... Nothing in your initial proposal suggested that in the slightest. I= t did not even include yield with brackets to list multiple options. > The above assuming that the autoloader knows where \Vendor\Package\A,=20 > \Vendor\Package\B and \Vendor\Package\C are located at. If an=20 > autoloader isn't used they'll have to be explicitly required before=20 > being yielded out. >=20 >>=20 >> If those reads of your post are inaccurate, then please show with exa= mples how they are inaccurate, because that is how I understood your pro= posal text at face value. >>=20 > > Ok, let's go over them in turn > >>> 1. Every module author to change their coding structure. > > No. Modules aren't replacing the current mechanism - just augmenting i= t=20 > when needed. The new syntax is only necessary when an independent=20 > symbol table is desired. Further, there's nothing stopping a package=20 > from having a standard require entry file that doesn't set up the=20 > symbol table and related protections, and one that does. =20 See above. >>> 2. Every consumer of a package to change their coding structure > > That depends on the package maintainer. They can certainly rewrite th= e=20 > package such that consuming code must use module syntax to access it,=20 > but this isn't required of them. And as mentioned above they can get=20 > clever and provide multiple entry points to their code if they desire=20 > just as JavaScript package devs have been doing to make sure their=20 > packages work whether the consumer uses ESM import or CommonJS import. > >>> 3. Devs to abandon "it just works" autoloading and explicitly import= packages. > > I don't know where you got that from - maybe the old thread from 9=20 > months ago? The proposal I made last night not only takes autoloading=20 > into account but also discusses how autoload functions will receive a=20 > second argument moving forward that lets them make decisions about wha= t=20 > code to supply to modules based on whatever logic they have which is=20 > well beyond the scope of this proposal. It came from the examples in the original proposal at the top of this th= read: > use sum require 'mymodule.php'; > > echo sum(3, 4); // 7 So if I want to call sum(), I have to explicitly `use sum require` it. = I cannot just let the autoloader sort it out. (Assuming we were talking= about a class or function autoloading ever happens, of course.) >>> 4. Abandoning 16 years of PSR-0/4 file convention in favor of "modul= e =3D file", which will almost certainly result in multi-thousand-line f= iles even for clean, well-factored code. >=20 > Again, I don't see this, at all. And I'm a little insulted you'd think=20 > that I'm dumb enough to propose something that outrageous. Modules=20 > simply have their own symbol table scope. They can import any package=20 > as they exist today without any modification into that scope. They can=20 > therefore pull a different version of the same package, which is=20 > desirable if they have a compatibility issue with the latest version o= f=20 > the package. Those autoloader are important, but out of scope. The implication from your original post is that if I want to import 3 sy= mbols from a module, I require a single file. That file has one or more= symbols that are `yield` ed. Implication: If I want 3 symbols in a mod= ule together, they have to be in the same file. Your response here about having a fronting file that yields symbols it d= oesn't define, on the assumption that an autoloader will figure it out i= n the backend, was never stated nor implied anywhere in your proposal. = Rather, it states that modules look like this: > yield function sum(a, b) { return a + b; } IE, like Javascript or Python libraries. That is the plain reading of y= our original post. And naturally means that whoever is authoring that f= ile needs to make changes to it, to at minimum add the "yield" keyword. So before you get indignant and call me a liar ("You're 4 for 4 on false= hoods"), perhaps consider how someone you know is "more intelligent" tha= n this can come away from your post understanding it so utterly differen= tly than what you intended. From your follow up statements, it seems that what you are proposing is = not "modules" in any sense used in any language I am familiar with. Rat= her, you're proposing a symbol table hack to get around PHP's inability = to load two symbols with the same name, and using module terminology to = inaccurately describe it. (And thread terminology as well.) That is, i= t seems your intent is that I can import arbitrary code from an arbitrar= y package and shunt it off to a separate symbol table. But it's not cle= ar if you intend for the package author to have to do anything to enable= that. Your answers seem contradictory. For a concrete example, I'll offer my AttributeUtils library: https://gi= thub.com/Crell/AttributeUtils/tree/master/src It has a whole bunch of interfaces, plus a few classes. We'll focus on = a subset of them for the moment. Analyzer.php (this is the main class someone uses) AttributeParser.php (this is an internal class used by Analyzer, you sho= uld never use it directly) FromReflectionClass.php (an interface that other libraries implement to = trigger certain functionality in Analyzer) Say I want to modularize this library, under your proposal. What would = I, as the library author, do exactly? Anything? How can I mark Attribu= teParser as internal-only and thou-shalt-not-use-if-you're-not-me? (Tha= t's the most common value of module systems, and the one most people in = PHP seem to think of, from what I've seen.) That library is used extensively by Serde (another of my libraries). If= I modularize AttributeUtils, then what changes does Serde need to make?= What would it get out of doing so? Code examples, please. --Larry Garfield