On Sat, Aug 24, 2024, at 13:59, Stephen Reay wrote:
> 
> 
> > 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 be 
> 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 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\myfunc('hello') |
| false   | true      | ns     | N/A    | true    | ns\myfunc  | 
\ns\myfunc('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 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 that breaks up the map into a specialized trie that appears to 
faster than 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 
let it look up the global.

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

Now let’s look at the case if you want to have a written function called 
"myfunc()" in the global namespace. You want it to be autoloaded. 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 performant option. Alternatively, it can get the 
basename of  "ns\myfunc" (which would be "myfunc") and walk the trie again. Say 
it does that and finds your function. Now when we return from the autoloader, 
we have to 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 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."

— Rob

Reply via email to