On 04/01/2016 16:34, Andrea Faulds wrote:
In Haskell, a purely-functional programming language, certain operators (and also certain math functions like abs()) are defined as part of "typeclasses", somewhat akin to interfaces in classical object-oriented languages like Java or PHP. These typeclasses group related operations together, and a conforming implementation of that typeclass must implement all the operations. [...] I think it would be more worth pursuing a Haskell-style approach in PHP, most likely with a hierarchy of magic interfaces.
For those not familiar with type classes, it's worth mentioning something you clarified to me over Twitter some time ago, about how they differ from interfaces (correct me if I go wrong). With an interface, the definition of GMP could include "implements NumLike", meaning that any instance of GMP "is a NumLike object"; there are only two entities to define: the interface, and the class which implements it. With a type class, GMP itself wouldn't implement NumLike, you would have a third entity, which was "an instance of NumLike for GMP objects"; GMP would "have a NumLike type class", defined externally to it.
This goes some way to addressing the question of which operand receives the message that an overloaded operator has been invoked - the implementation would not have a "$this". As I understand it, multi-parameter type classes even allow you to bridge between types that aren't aware of each other - e.g. define the result of gmp_init(42) + \Litipk\BigNumbers\Decimal::create(42)
Incidentally, my main exposure to operator overloading and custom operators is in PostgreSQL, which implements them as a special case of overloaded function despatch: you can have two functions "add(int, int)" and "add(float, float)", which will be selected between when a statement is compiled; you can then define the binary operator "+" for types "int, int" maps to function "add(int, int)", and it's dispatched the same way. Again, this removes the question of which operand should receive the message, because the operator (and its associated function) are not part of the type - if you want to add an int to a float, you can / must define both "operator + (int, float)" and "operator + (float, int)". Like in C++, though, Postgres's operators aren't intrinsically grouped, and it's up to you to use them in idiomatic ways, such as "||" for various types of concatenation (because SQL) and "@>" for "contains".
The major disadvantage to separating the implementation of the operator / type class from the class definition is that I can't see how it would work with autoloading.
Regards, -- Rowan Collins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php