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