Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125180 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 qa.php.net (Postfix) with ESMTPS id A07381A00BD for ; Sat, 24 Aug 2024 12:32:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1724502882; bh=JqQtowyXAdGcDdAkpuXYJUqy0JWpH83bGui064MgZlQ=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=CCpHzN2UthXTu80sn4YzyWRlXGX3/ec8q4CSMixKpqxQtBujRFTW27MWM2YkB2oX8 0somFnE5cFbVOilEgS2OHHebH6tgfkdwTZabRGd+wW0MXBylg5yaEjjsHT27HIh4rx XUlIAupDumYles0WAGoUhCHX1bkxY2+jLI3yDKOv2lPR9GaA4SE2EmOe+A7aZBf1Hf mcjpc70M64awdNvsRSCaVY8a7OELNq/GUU6V3NAf0d3bBz2Whgsz1pevRg8LCN4eE2 z4kWZ3jVv6epszlOQty4gPhOj+XeGbz/J+g3uGa5Ug/G5SvddZHSVhIc0/qf9JXkYs N0jJFDYO4VNiQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id AD78D180071 for ; Sat, 24 Aug 2024 12:34:41 +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=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fout1-smtp.messagingengine.com (fout1-smtp.messagingengine.com [103.168.172.144]) (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 ; Sat, 24 Aug 2024 12:34:41 +0000 (UTC) Received: from phl-compute-03.internal (phl-compute-03.nyi.internal [10.202.2.43]) by mailfout.nyi.internal (Postfix) with ESMTP id 04780138FD0D; Sat, 24 Aug 2024 08:32:49 -0400 (EDT) Received: from phl-imap-09 ([10.202.2.99]) by phl-compute-03.internal (MEProxy); Sat, 24 Aug 2024 08:32:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:cc: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=fm2; t=1724502769; x= 1724589169; bh=+T27N5Kq5wxS5QQZ2Qmex+gZs0Avr8308RzcdBbroDI=; b=i GOVIA4Q4uD+5edvnLDeqgJajt2Cc14DAUY/YNp2+TcwFpyTAXTL83Sig0td6PJip x0+kGVTcR7Wz0kBAry2ssaaqmrD/CNxaRQcM7Si1j+p4zDAdURqdP9UGH+VvGDRb CXbCnGPC3gxYaBvKrvg9YBX4bfsTZQKSIwrDUrBHiJg0KjNPzLaQ8hI/xrO+4obF hYsPf0SLUtGiIzEbJGYApJLW3m4yPdtImJ3AMmtS3jARyjkOKHy3XmVOpQHBBicP Xl2tCP57yIoyAC2W2rUNWevW8rh5T7kezajdD/CX67RpGO6AX7vtEWfzFhIhSc8u EJv7H7tF8TaidupaUmCmw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc: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-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; t=1724502769; x=1724589169; bh=+T27N5Kq5wxS5QQZ2Qmex+gZs0Av r8308RzcdBbroDI=; b=BD45WtNB01pXj1CgirFdHeMe71Vx25zf7YJMdSPeCpr2 FSde6hAFNlCuHf419CnJcJ9rHX5SGt4ksx9NzyuvYDZ1lnNBfp3pP50Ctn6/7G05 YsDnqq8Ww1pTzTSQcAn3afmAfH7m5Hz8Vj4i7yYkHNMsXrkLrRUrFwBfUwtITY/k 3iFNTnbuJckrgem2N06B2ZNof1g2YSWUPk4SkauN07f0RZ+lcsYW8rgApFKx1ucg YqLe1gTFgTsOKucfc9G2DYCOWx/2NtKrwQVlwq2H9XCcnvHcMmg35MsOrHmBTIFw J4StOQ8W5jHabizLzZRnIZ5c1FOqVRmOJOb0LkUZ0A== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddruddvgedgheegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucenucfjughrpefoggffhf fvvefkjghfufgtsegrtderreertdejnecuhfhrohhmpedftfhosgcunfgrnhguvghrshdf uceorhhosgessghothhtlhgvugdrtghouggvsheqnecuggftrfgrthhtvghrnhepieeute ehvddvfeejhffgieehleehhedthfefkeejffelgfevvdekudetjeejtddtnecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprhhosgessghothhtlh gvugdrtghouggvshdpnhgspghrtghpthhtohepvddpmhhouggvpehsmhhtphhouhhtpdhr tghpthhtohepphhhphdqlhhishhtsheskhhorghlvghphhgrnhhtrdgtohhmpdhrtghpth htohepihhnthgvrhhnrghlsheslhhishhtshdrphhhphdrnhgvth X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 9D326780065; Sat, 24 Aug 2024 08:32:48 -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 Date: Sat, 24 Aug 2024 14:32:28 +0200 To: "Stephen Reay" Cc: internals@lists.php.net Message-ID: In-Reply-To: <773F5AF4-DE89-4952-BE1A-16FE5326B239@koalephant.com> References: <3e8eaf60-1778-4579-b058-e0849a7b7106@app.fastmail.com> <773F5AF4-DE89-4952-BE1A-16FE5326B239@koalephant.com> Subject: Re: [PHP-DEV] [Concept] Flip relative function lookup order (global, then local) Content-Type: multipart/alternative; boundary=e5840cf64ec64ecaba4e901cec1a9f71 From: rob@bottled.codes ("Rob Landers") --e5840cf64ec64ecaba4e901cec1a9f71 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sat, Aug 24, 2024, at 13:59, Stephen Reay wrote: >=20 >=20 > > On 24 Aug 2024, at 16:24, Rob Landers wrote: > >=20 > > In other words, if you want to autoload a global function, you need = to call it fully qualified. >=20 > When I said this thread reads like an April fools joke that wasn't a c= hallenge you know. >=20 >=20 > Are you seriously suggesting that unqualified function lookups should = be global first, then local, except if it's to be autoloader and then th= e global ones *have* to be fully qualified? More like it only supports autoloading locally namespaced functions when= unqualified. So, everything else works exactly the same. Here's a table that might help (note, just typed it up off the top of my= head so may have errors) for a global-first behavior: | defined | qualified | type | from | autload | name | example= | |---------|-----------|--------|--------|---------|------------|--------= -------------| | true | true | global | N/A | false | N/A | \strlen= ('hello') | | false | true | global | N/A | true | \myfunc | \myfunc= ('hello') | | true | false | global | global | false | N/A | strlen(= 'hello') | | true | false | global | ns | false | N/A | strlen(= 'hello') | | false | false | global | ns | true | ns\strlen | strlen(= 'hello') | | false | false | global | global | true | \strlen | \strlen= ('hello') | | true | true | ns | N/A | false | N/A | \ns\myf= unc('hello') | | false | true | ns | N/A | true | ns\myfunc | \ns\myf= unc('hello') | | true | false | ns | ns | false | N/A | myfunc(= 'hello') | | false | false | ns | ns | true | ns\myfunc | myfunc(= 'hello') | With "local-first": if your autoloader receives a name "ns\strlen" then = you should look for ns/strlen. An optimized autoloader will have a funct= ion map (similar to class map) that can quickly determine if that functi= on exists in the project or not and where to load it from. For example, = in my tests, I have a function map that breaks up the map into a special= ized trie that appears to faster than an array for an arbitrary number o= f functions. In this case, it would know to drop it after about 1-2 step= s into the prefix tree, return and let it look up the global. With global-first, the autoloader never even gets called for something l= ike strlen; instead it will be resolved in the global scope. Now let=E2=80=99s look at the case if you want to have a written functio= n called "myfunc()" in the global namespace. You want it to be autoloade= d. Now, in some namespace ("ns"), the developer writes calls "myfunc()" = unqualified, which is yet to be defined. The autoloader will be called (= in both implementations) with the name "ns\myfunc" and it will be up to = the autoloader implementation what to do about this. It can first walk t= he trie and decide there is nothing to do here, which is the most perfor= mant option. Alternatively, it can get the basename of "ns\myfunc" (whi= ch would be "myfunc") and walk the trie again. Say it does that and find= s your function. Now when we return from the autoloader, we have to chec= k the function table for both, again. If we only allow autoloading from the current namespace for unqualified = calls, we simplfiy autoloading implementations and speed up things for e= veryone. Someone can come along and amend this with an RFC in the future= , but it would be much harder to go the other way around. Further, you can always call your global function, like "\myfunc()" and = it would "just work." =E2=80=94 Rob --e5840cf64ec64ecaba4e901cec1a9f71 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable

=
On Sat, Aug 24, 2024, at 13:59, Stephen Reay wrote:

<= br>
> On 24 Aug 2024, at 16:24, Rob Landers <rob@bottled.codes> wrote:

> In other words, if you want to autoload a= global function, you need to call it fully qualified.
When I said this thread reads like an April fools joke that = wasn't a challenge you know.


Are you seriously suggesting that unqualified function lookups should b= e global first, then local, except if it's to be autoloader and then the= global ones *have* to be fully qualified?
More like it only supports autoloading locally namespaced f= unctions when unqualified. So, everything else works exactly the same.

Here's a table that might help (note, just t= yped it up off the top of my head so may have errors) for a global-first= behavior:

| defined | qualified= | type   | from   | autload | name   = ;    | example       &= nbsp;     |
<= span class=3D"font" style=3D"font-family:menlo, consolas, monospace, san= s-serif;">|---------|-----------|--------|--------|---------|-----------= -|---------------------|
| true    | true      | globa= l | N/A    | false   | N/A   &nb= sp;    | \strlen('hello')    |
| false   | true &= nbsp;    | global | N/A    | true &nb= sp;  | \myfunc    | \myfunc('hello')  &nbs= p; |
| true  =   | false     | global | global | false &n= bsp; | N/A        | strlen('hello')&n= bsp;    |
| true    | false     | global | n= s     | false   | N/A   &nb= sp;    | strlen('hello')     |=
| false   | false&= nbsp;    | global | ns     | true&nbs= p;   | ns\strlen  | strlen('hello')   &nbs= p; |
| false  = ; | false     | global | global | true  &n= bsp; | \strlen    | \strlen('hello')    |<= /span>
| true  &nbs= p; | true      | ns     | N= /A    | false   | N/A    &n= bsp;   | \ns\myfunc('hello') |
| false   | true    &nb= sp; | ns     | N/A    | true &nb= sp;  | ns\myfunc  | \ns\myfunc('hello') |
| true    | false &nbs= p;   | ns     | ns    = | false   | N/A        | m= yfunc('hello')     |
| false   | false     |= ns     | ns     | true &nb= sp;  | ns\myfunc  | myfunc('hello')     |<= /span>

With "local-first": if your autoload= er receives a name "ns\strlen" then you should look for ns/strlen. An op= timized autoloader will have a function map (similar to class map) that = can quickly determine if that function exists in the project or not and = where to load it from. For example, in my tests, I have a function map t= hat breaks up the map into a specialized trie that appears to faster tha= n an array for an arbitrary number of functions. In this case, it would = know to drop it after about 1-2 steps into the prefix tree, return and l= et it look up the global.

With global-first= , the autoloader never even gets called for something like strlen; inste= ad it will be resolved in the global scope.

Now let=E2=80=99s look at the case if you want to have a written functi= on called "myfunc()" in the global namespace. You want it to be autoload= ed. Now, in some namespace ("ns"), the developer writes calls "myfunc()"= unqualified, which is yet to be defined. The autoloader will be called = (in both implementations) with the name "ns\myfunc" and it will be up to= the autoloader implementation what to do about this. It can first walk = the trie and decide there is nothing to do here, which is the most perfo= rmant option. Alternatively, it can get the basename of  "ns\myfunc= " (which would be "myfunc") and walk the trie again. Say it does that an= d finds your function. Now when we return from the autoloader, we have t= o check the function table for both, again.

If we only allow autoloading from the current namespace for unqualified= calls, we simplfiy autoloading implementations and speed up things for = everyone. Someone can come along and amend this with an RFC in the futur= e, but it would be much harder to go the other way around.

Further, you can always call your global function, like = "\myfunc()" and it would "just work."

=E2=80=94 Rob
--e5840cf64ec64ecaba4e901cec1a9f71--