Opinion on function/method name overloading

php.internals

Dominic Grostate

10 years ago
Hi, As I understand it, using Java-like function overloading in PHP is undesirable due to hindrance in readability. However I'd like to get an opinion on whether it would be received more favourably if it could provide an actual performance enhancement over hand managed implementation's of detecting argument differences with variadic and func_get_args. On to a more subjective argument, "naming things" is hard, and I think many people would appreciate being able to reuse function/method names without sacrificing type safety. Any thoughts?

Derick Rethans

10 years ago
On Mon, 6 Jun 2016, Dominic Grostate wrote:
> As I understand it, using Java-like function overloading in PHP is > undesirable due to hindrance in readability.
Besides it impacting, readability, it will also create a large impact on performance. Right now, functions (and methods) are looked up by their name only. In order to support function overloading, the argument's types also need to be taken into account. In C++, it works by mangling function names by adding markers for types, such as: _ZN4HPHP34c_MongoDBDriverCursor_ni_getServerEPNS_10ObjectDataE which means: HPHP::c_MongoDBDriverCursor_ni_getServer(HPHP::ObjectData*) But unlike in C++, this needs to be done at runtime, and every time a function is called because PHP is dynamically typed, and not statically. For example: myOverLoadedFunction(string $s, long $l, Weather $w) could be: myOverLoadedFunction_s_l_cWeather or something like that. Doing these conversions would mean (in the most simple way), that for each function call, a string needs to be manipulated to create the mangled function name to lookup for in a hash, where right now, they only have to be strtolower()'ed (because of case insensivity). And then you need to do something sensible when *no* types have been defined. cheers, Derick

Christoph Becker

10 years ago
Derick Rethans wrote:
> On Mon, 6 Jun 2016, Dominic Grostate wrote: > >> As I understand it, using Java-like function overloading in PHP is >> undesirable due to hindrance in readability. > > Besides it impacting, readability, it will also create a large impact on > performance. > > Right now, functions (and methods) are looked up by their name only. In > order to support function overloading, the argument's types also need to > be taken into account. In C++, it works by mangling function names by > adding markers for types, such as: > > _ZN4HPHP34c_MongoDBDriverCursor_ni_getServerEPNS_10ObjectDataE > > which means: > > HPHP::c_MongoDBDriverCursor_ni_getServer(HPHP::ObjectData*) > > But unlike in C++, this needs to be done at runtime, and every time a > function is called because PHP is dynamically typed, and not statically. > > For example: > > myOverLoadedFunction(string $s, long $l, Weather $w) > > could be: > > myOverLoadedFunction_s_l_cWeather > > or something like that. > > Doing these conversions would mean (in the most simple way), that for > each function call, a string needs to be manipulated to create the > mangled function name to lookup for in a hash, where right now, they > only have to be strtolower()'ed (because of case insensivity). > > And then you need to do something sensible when *no* types have been > defined.
And we would run into similar issues as with the union types with regard to weak typing.
-- Christoph M. Becker

Rowan Collins

10 years ago
On 06/06/2016 11:32, Christoph Becker wrote:
> And we would run into similar issues as with the union types with regard > to weak typing.
This is probably the biggest hurdle, IMO - regardless of the internal implementation, you've got to define exactly how the feature would work in the language itself. A quick example off the top of my head (there are many other edge cases to cover): class A { public function foo($bar) { echo 0; } public function foo(string $bar) { echo 1; } public function foo(int $bar) { echo 2; } } class B extends A { public function foo(float $bar) { echo 3; } } (new A)->foo(1.5); (new B)->foo(1.5); Regards,
-- Rowan Collins [IMSoP]

Dominic Grostate

10 years ago
In your example, the output may be: 0 3 float, int and string all share the same row on an upside down pyramid, with $bar, being dynamic, at the bottom. With regards to union types, it could work exactly like the latest Multi-Catch feature. On 6 Jun 2016 11:57 a.m., "Rowan Collins" <rowan.collins@gmail.com> wrote:

Rowan Collins

10 years ago
On 06/06/2016 12:06, Dominic Grostate wrote:
> float, int and string all share the same row on an upside down pyramid, with $bar, being dynamic, at the bottom.
OK, so take away the dynamic case, and assume the caller is in weak mode. Now you have a second case where you need priorities between the types. Or consider this code, which is already valid: class A { function foo($bar) { echo "A: $bar"; } } class B { function foo(int $bar) { echo "B: $bar"; } } (new B)->foo(1.5); // B: 1 Or we could construct similar examples with parent and sub-classes as the type constraint of $bar. And so on. I tried to stress that this is an example of one detail among many that would need to be worked out; I wasn't looking for a single answer. Perhaps we would need to add a new keyword (or a native annotation?) to mark that a function was overloaded, so that existing inheritance didn't accidentally become overloading. To my mind, this would add a lot of complexity to the language, and I'm not convinced of the gain. If you want to avoid dynamically checking variable types, you can always just provide separately named methods for separate cases. Regards,
-- Rowan Collins [IMSoP]

Dominic Grostate

10 years ago
Yes, I can see what you mean. Should a float prefer a string or an int? I don't know. That would be a issue unless an additional method of prioritising were involved. Perhaps if attributes get in there will be a solution: <<Overloaded(1)>> function foo(int $a) {} <<Overloaded(2)>> function foo(string $a) {} Yet as complicated as overloading would be to begin with, this I feel would make it even worse lol. Just for clarifies sake I'll explain briefly what I feel the benefits are, and perhaps we can see if it's worth discussing further: - No need to conjure new names. A biggy IMO. - A new way of overriding. If you want to override a base class method by capturing an argument of lower bounds, you won't need to do an instance check and decide on super or alternative code. - Performance enhancement over emulated overloads such as __call, variadic and anonymous arguments. Regarding the last point, I've mocked up a basic benchmark to illustrate the difference in performance when comparing emulated overloading with alternative functions. I expect native support for overloading to be somewhere in between the results of the two tests. https://gist.github.com/orolyn/ff70f512efee36d402d1fc4fbc8f0521 On 6 Jun 2016 12:19 p.m., "Rowan Collins" <rowan.collins@gmail.com> wrote:

Andrew Faulds

10 years ago
Hi, Others have already raised good technical points (performance, how to distinguish when we have dynamic/weak typing), but I'd like to offer another argument against it, that is, that even if it were possible we might not want overloading anyway. From my perspective, function and method overloading in languages like C++ or C# is useful for mainly two reasons: allowing omitting unnecessary arguments (or, allowing providing additional, more specific arguments), and accepting multiple types for arguments. However, we already have solutions for both of these in PHP. PHP's functions and methods can have optional parameters for which you do not have to provide an argument, and because PHP is dynamically-typed, a parameter can accept an argument of any type (and within the function body discriminate between types) if it needs to. Also, PHP has fewer and more generalised types than some other languages do, so where a C# method might have overloaded versions taking a UInt8, UInt16, UInt32, SInt8, SInt16 and so on, an equivalent PHP method might only take PHP's single universal integer type. Of course, this doesn't perfectly cover all the use cases of overloading. You can't, for example, directly express in PHP that a function takes one argument or another, but not both. That said, however, I don't think this is necessarily a big problem: you can write two functions with different names. Having to write differently-named functions may well be a good thing, too, speaking from having had to deal with APIs in languages where a "single" method can have more than a dozen overloaded forms, each behaving differently, yet they all look confusingly similar at the call-site. Anyway, thank you for asking!
-- Andrea Faulds https://ajf.me/

Dominic Grostate

10 years ago
Thanks. I only wanted some quick input into whether it was worth pursing before I do something daft.. like build it :) All I wanted to know was, if the technicalities could be worked out, and a performance boost was possible, would people still dislike it. I'd still like to see it added, but I admit it was a long shot. Thanks, Dominic On 6 Jun 2016 1:10 p.m., "Andrea Faulds" <ajf@ajf.me> wrote:

Lester Caine

10 years ago
On 06/06/16 13:10, Andrea Faulds wrote:
> > However, we already have solutions for both of these in PHP. PHP's > functions and methods can have optional parameters for which you do not > have to provide an argument, and because PHP is dynamically-typed, a > parameter can accept an argument of any type (and within the function > body discriminate between types) if it needs to. Also, PHP has fewer and > more generalised types than some other languages do, so where a C# > method might have overloaded versions taking a UInt8, UInt16, UInt32, > SInt8, SInt16 and so on, an equivalent PHP method might only take PHP's > single universal integer type.
This used the be the reason PHP worked so well ... one did NOT have to worry about how a parameter was provided, and even today one is *NOT* providing a binary 'int' even if you 'type' the value to be such. The whole point of a compiled language being able to provide several versions of the same function but with different binary parameter sizes and types is hopefully something that will never trouble PHP? PHP is not building a binary parameter stack for the function call. function foo($a) {} is still the natural way of doing things if the FIRST validation step is '$a between 1 and 10' and adding the 'int' does nothing to change the work flow of handling $a in my book ... just loads the process with additional checks which often have to be duplicated internally anyway to maintain a proper flow through the process.
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Christoph Becker

10 years ago
Dominic Grostate wrote:
> As I understand it, using Java-like function overloading in PHP is > undesirable due to hindrance in readability. > > However I'd like to get an opinion on whether it would be received more > favourably if it could provide an actual performance enhancement over hand > managed implementation's of detecting argument differences with variadic > and func_get_args. > > On to a more subjective argument, "naming things" is hard, and I think many > people would appreciate being able to reuse function/method names without > sacrificing type safety.
Another issue besides what has already been mentioned in other replies is that PHP already has the concept of overloading[1]: | Overloading in PHP provides means to dynamically "create" properties | and methods. These dynamic entities are processed via magic methods | one can establish in a class for various action types. So at least another name would have to be chosen for either of both concepts. [1] <http://php.net/manual/en/language.oop5.overloading.php>
-- Christoph M. Becker