Re: Feature Discussion |
| From: | Rob Landers | Date: | Wed, 11 Jun 2025 06:56:44 +0000 |
| Subject: | Re: Feature Discussion | | ||
| References: | 1 2 3 4 5 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-127642@lists.php.net to get a copy of this message | ||
On Wed, Jun 11, 2025, at 08:31, Dmitry Derepko wrote:
> I see.
>
> The first thought is about extending the class definition: along with functions hashtable we
> would add virtual functions HT and lookup for the function will be another HT lookup.
>
> image.png
>
> That for sure is better than trap for cpu, but enlarge memory usage at the moment.
>
>
> ---
>
> Moreover, it allows us to keep both static and dynamic functions.
>
> function class::func(){} // static extension class:func()
> function class->func(){} // dynamic function $class->func()
>
>
>
> ---
>
> this functions can be found dynamically and it seems alright:
>
> // a.php
> use Models\User;
>
> function User::getName(){}
>
> // new User->getName is available here
>
> // b.php
>
> use Models\User;
>
> // new User->getName is NOT available here, because a.php wasn't loaded and here
> User::getName isn't available
>
> // c.php
>
> namespace Stuff;
>
> include 'a.php';
>
> // new User->getName here you can do it, because a.php was loaded and functions table was
> adjusted with getName function
>
> // d.php
>
> use Stuff\Smth;
> use Tools\Smth2;
>
> // if it's an app entrypoint
> // autoloader loads c.php because of Smth file is found there
> // c.php loads a.php
> // the extension function User::getName is also available here
>
> // either is this file an entrypoint or not
> // it stores the extension function in the class definition
> // so Smth2 now can use the extension function, because it was loaded "by parent"
>
> > Very much not. The
use construct has no bearing on
> > autoloading currently. Autoloading happens only for classes and class-like things (interfaces,
> > traits, enums). If a function is not found, PHP just crashes. Various solutions to this have been
> > discussed over the years, none of which ever made it as far as a vote.
>
> Is this covered by the texts above?
>
> > In fairness, I think with universal opcache, preloading, and the increasing use of
> > persistent processes, just skipping autoloading for functions and front-loading them via
> > composer.json's "files" block is fine for the 80% case. But it feels like I am in
> > the minority on that position.
>
> That's what we have now. Can't see any problems.
>
>
> On Tue, Jun 10, 2025 at 11:11 PM Larry Garfield <larry@garfieldtech.com> wrote:
>> On Tue, Jun 10, 2025, at 2:45 PM, Dmitry Derepko wrote:
>> > Thanks for participating, Larry.
>> >
>> > On Mon, Jun 9, 2025 at 10:29 PM Larry Garfield <larry@garfieldtech.com> wrote:
>> >> 2. Please link to a PR of your actual implementation. In context it looks like
>> >> your branch comparison link is to the version you said didn't work, so it's not that
>> >> helpful.
>> >
>> > Correct, I don't have another one. This is big feature, I need a lot of
>> > time to implement it. I don't want to waste my time if we decide that
>> > RFC won't pass at all.
>>
>> Understood.
>>
>> >> 3. The biggest question that has come up in the past (Ilija and I have discussed
>> >> it at length) is, naturally, autoloading. How if at all do you address that?
>> >
>> > In the original message I mentioned use extension
>> > construction. This
>> > should be enough for solution, isn't it?
>>
>> Very much not. The use construct has no bearing on
>> autoloading currently. Autoloading happens only for classes and class-like things (interfaces,
>> traits, enums). If a function is not found, PHP just crashes. Various solutions to this have been
>> discussed over the years, none of which ever made it as far as a vote.
>>
>> I toyed with the idea of having extension functions compile to a static method on a class
>> as a way around this, but of course then you end up with a file-per-function, and the file name has
>> to match not the function name, but whatever mangled class name gets generated. Not at all
>> intuitive.
>>
>> In fairness, I think with universal opcache, preloading, and the increasing use of
>> persistent processes, just skipping autoloading for functions and front-loading them via
>> composer.json's "files" block is fine for the 80% case. But it feels like I am in
>> the minority on that position.
>>
>> >> 4. The other big question was determining when to match a given "method"
>> >> call to an extension function, when the type of a variable is not always known at compile time. How
>> >> did you address this?
>> >
>> > Cannot understand the passage, could you explain more?
>>
>> <?php
>> // index.php
>>
>> function Point.area(): int {
>> return $this->x & $this->y;
>> }
>>
>> function doStuff($p) {
>> // At compile time, we don't know that $p is a Point. In fact, it may not be.
>> // The function will allow any value here, even a non-object, so it doesn't know
>> // if this should be compiled to Point__area($p) or left as is.
>> print $p->area();
>> }
>>
>> The only way I could think of to handle that is to have a method call "trap"
>> similar to class autoloading, that when hit checks at runtime "hey, this method didn't
>> exist, but is there a used function that would match based on the
>> runtime type of this value?" But Ilija felt that would be prohibitively slow. It would
>> certainly be slower than just a function/method call since the trap takes time.
>>
>> And then we get into questions of inheritance, and, well, it gets even messier fast.
>>
>> One possibility that we riffed on during the pipes discussion (mostly off list, I think)
>> was using +> for some combination of extension functions and Elixir-style first-arg pipe passing,
>> so that $p+>area() would signal to the engine (compile time or runtime) that area() wasn't a
>> method but a function that should get $p passed to it. That would solve the "trap"
>> problem, but still doesn't address autoloading, the lack of compile time type knowledge, or how
>> to differentiate between Point.area(), ShapeInterface.area(), Rect.area(), etc.
>>
>> --Larry Garfield
>
>
> --
> Best regards,
> Dmitrii Derepko.
> @xepozz
How does it handle late binding? (This is when a class extends/implements a class that doesn’t
exist yet; so the compiler postpones actually creating the class until runtime when it can run the
autoloader, if needed) should these functions also late bind in that case?
— Rob