On Thu, Aug 15, 2024, at 20:40, Rowan Tommins [IMSoP] wrote:
> On 15/08/2024 16:22, Rob Landers wrote:
>> Hello internals,
>> 
>> I've decided to attempt an RFC for function autoloading. After reading 
>> hundreds of ancient (and recent) emails relating to the topic along with 
>> several abandoned RFCs from the past, and after much review, I've decided to 
>> put forth a variation of a previous RFC, as it seemed the least ambitious 
>> and the most likely to work:
>> 
>> https://wiki.php.net/rfc/function_autoloading4
> 
> 
> Hi Rob,
> 
> While brevity can sometimes be a virtue, I feel like there's a lot left to 
> the reader's interpretation here.
> 
> Specifically, one of the main issues that has come up in previous discussions 
> of the topic is the behaviour of unqualified function names, which check the 
> current namespace first, then fall back to global scope. Your RFC implies an 
> approach to this, but doesn't actually spell it out, nor discuss its pros and 
> cons.
> 

It doesn't go too much into details here on purpose, especially since there was 
some recent discussion on changing the order. That being said, while writing 
the reply below, I realized it simply wasn't clear enough. I've updated the RFC 
to be more clear, in regards to the current behavior.

> The fully qualified case is straight-forward: the autoloader is called, and 
> if still not defined, an error is thrown. But for the unqualified case, there 
> are multiple scenarios, and you only give the behaviour for one of them:
> 

To fill in your chart:

> Defined in current namespace? | Defined in global namespace? | Proposed 
> behaviour
> ------------------------------+------------------------------+--------------------------------------
> No                            | No                           | Prefixed name
> No                            | Yes                          | Prefixed name
> Yes                           | No                           | No change
> Yes                           | Yes                          | No change
> 
> The third and fourth cases (where the function exists in the current 
> namespace) are straight-forward, although it wouldn't hurt to spell them out: 
> presumably, the namespaced function is used as now, so no autoloading is 
> needed.
> 
> The complex case has always been the second one: the function doesn't exist 
> in the current namespace, but *does* exist in the global namespace. (Or, an 
> autoloader *defines* it in the global namespace.)
> 

This should have the same behavior as in the class autoloader. In my attempt to 
be vague (in case the loading order is changed, which I assumed would affect 
class autoloading as well), I wasn't very clear on this. Meaning if you create 
a class called "Fiber" and a function called "strlen" in the current namespace, 
in unloaded files, an autoloader should be given the opportunity to load them.

I should also probably define some vocabulary so this is all less confusing. 
and Done.


> In concrete terms, what does this code output:
> 
> spl_autoload_register( function($function, $type) { echo "$function..."; }, 
> type:SPL_AUTOLOAD_FUNCTION);
> 
> namespace Foo {
>    foreach (['hello', 'goodbye'] as $word) {
>       echo strlen($word), ';';
>    }
> }
> 
> a) "Foo\strlen...5;Foo\strlen...7;" (the autoloader is called every time the 
> function is encountered)
> b) "Foo\strlen...5;7;" (the autoloader is called once, then somehow marked 
> not to run again for this name
> c) "5;7;" (the autoloader is never run for this code)
> 

I believe the "most correct" answer is (a) -- and is what the current class 
autoloader does as well. Option (b) would make it impossible to do any kind of 
dynamic code generation or old-fashioned file-based deployments.


namespace global {
    spl_autoload_register(function ($function) {
       echo "$function...";
    });
}

namespace Foo {

    foreach (['hello', 'goodbye'] as $word) {
       if (!class_exists(Fiber::class)) {
          echo "Test...";
       }
    }
}

Since I foresee (based on previous conversations) about people being worried 
about performance:

I think this is best left to autoloader authors to manage. If there isn't a 
function autoloader, then there won't be any performance impact (or at least, 
minimal). However, if there is one, the author can take into account how their 
codebase works. For example, I highly suspect FIG will create a PSR for this 
(eventually), based on how they expect things to work. I suspect a project like 
WordPress could make use of it and implement things how they expect things to 
work, etc.

For the case where you have a file full of unqualified `strlen()`'s, the 
autoloader author could create an option "do not shadow global functions" where 
it just returns immediately for built-in functions and doesn't even try 
autoloading (I also suspect there will be someone who code-golfs this to death 
so this check is extremely efficient). Is there a performance impact there? 
Probably not as big as you'd think -- and there already is a performance impact 
by using unqualified global functions (as shown in a recent proposal to change 
the order). So, if you are doing that already; you likely don't care about 
performance anyway.

But I'm going to reserve any serious discussions about performance for when I 
have an actual implementation to play with (hopefully a PoC this weekend).

> Note that there is an open RFC implementing option (b) by Gina and Dan here: 
> https://wiki.php.net/rfc/core-autoloading Last I heard, Gina was still hoping 
> to get back to it.
> 

I went looking for this (I had sworn I had seen it last year), but 
unfortunately, I did not find it while searching the RFCs for prior work. I had 
thought it abandoned so I was looking in the wrong place. This RFC does not 
conflict with that RFC, if Gina/Dan were to pick it back up again. I may borrow 
the `function_exists()` change, which I just updated the RFC to do.

> On a different note, there is no mention of autoloading namespaced constants 
> in this RFC, unlike in some previous proposals. Is this a conscious decision 
> to leave them out of scope, or an oversight?
> 

I'm leaving them out on purpose to keep the scope tight. I've got a whole year 
ahead of me.

> 
> 
> Regards,
> 
> -- 
> Rowan Tommins
> [IMSoP]

— Rob

Reply via email to