Re: [Concept] Flip relative function lookup order (global, then local)

From: Date: Sat, 24 Aug 2024 12:32:28 +0000
Subject: Re: [Concept] Flip relative function lookup order (global, then local)
References: 1 2  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message


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


Thread (112 messages)

« previous php.internals (#125180) next »