On Sat, Aug 24, 2024, at 13:59, Stephen Reay wrote:
>
>
> > On 24 Aug 2024, at 16:24, Rob Landers <[email protected]> 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