Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:91051 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 79812 invoked from network); 1 Feb 2016 21:24:51 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Feb 2016 21:24:51 -0000 X-Host-Fingerprint: 140.146.203.10 unknown Date: Mon, 01 Feb 2016 16:24:49 -0500 Received: from [140.146.203.10] ([140.146.203.10:27080] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id C6/FA-07168-12DCFA65 for ; Mon, 01 Feb 2016 16:24:49 -0500 Message-ID: To: internals@lists.php.net References: <12.34.07292.41F9A865@pb1.pair.com> User-Agent: Pan/0.139 (Sexual Chocolate; GIT bf56508 git://git.gnome.org/pan2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Posted-By: 140.146.203.10 Subject: Re: RFC Operator Overloading in Userspace From: me@stephencoakley.com (Stephen Coakley) On Mon, 04 Jan 2016 16:34:21 +0000, Andrea Faulds wrote: > Hi Sara, > > Sara Golemon wrote: >> Patricio Tarantino has asked me to help him propose Operator >> Overloading in PHP 7.1 (based in part on my operator extension in >> PECL). I think we can expose this to usespace as magic methods with >> very little overhead (the runtime check and dispatch is already there, >> after all). >> >> I do think that the "Future Expansion" section bears following through >> with as well, but the basic set of methods already hooked for GMP would >> be a nice start. >> >> https://wiki.php.net/rfc/operator-overloading > > While I would like to see operator overloading in PHP, I don't > particularly like the approach this RFC takes. It seems to take the > approach C++, Python and so on use where you can simply overload any > operator as you see fit. While that is arguably useful, it is open to > abuse. In C++, for example, you can join two file paths by dividing > them, or write to a stream by bitwise shifting it left by another > stream. In Python, you repeat a string by finding the product of it and > an integer. Abusing operator overloading like this harms readability, is > not necessarily intuitive and is anyway unnecessary: a function or > method would work just as well in these situations. Also, I'm not sure > it's a good fit for a dynamic language to make operators do different > things depending on their operand types. That just creates the > possibility of unpleasant surprises at runtime, and PHP has enough of > these already without the possibility of users creating more. > > Luckily, C++ and Python's approach is not our only option. I am quite a > fan of Haskell's approach to operator overloading, which is less prone > to abuse. 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. For example, there is a > `Num` typeclass[0] for numbers, which defines the addition, subtraction, > multiplication, negation, absolute value, sign and > conversion-from-integer operations. Extending `Num`, there is a > `Fractional` typeclass[1] for fractional number types, which adds > fractional division, reciprocal and conversion-from-rational operations. > There are likewise similar typeclasses for non-numbers, and other > descendents of `Num` for other kinds of numbers. The approach Haskell > takes here is not as prone to abuse because you cannot simply implement > operations as you please: you must implement them as a set. (Though, > granted, Haskell also discourages overloading abuse by actually letting > you define custom operators.) With this approach Haskell also achieves > something else useful, in that you can use typeclasses as a type > constraint on function parameters and return types. I think it would be > more worth pursuing a Haskell-style approach in PHP, most likely with a > hierarchy of magic interfaces. > > All that aside, I have some other issues with the RFC. The set of > overloadable operators proposed is very small, and I'm surprised it > doesn't even include the full set of number operations. But > additionally, if you were to fill in that set, I wonder if it might be > worthwhile making some of the math functions overloadable as well, since > otherwise you have an incomplete set of operators: %'s complement is > intdiv(), not /, and the closest thing we have to a complement of / is > fmod(). Likewise, since abs() works on integers and floats, perhaps it > should work on all number types. I don't think GMP currently overloads > any of these, though, and there is the possibility we might create > confusion if overloading extended to math functions. > > Another concern I have is the possibility of having __assign_* > overloads. These would useful for avoiding having to instantiate a new > object, but there's potential for them to be implemented wrongly, or be > implemented without their corresponding normal operations. Since we > don't have any way to make PHP 4-style copy-on-write value classes at > the moment, I think we should just do the simpler thing and assume we're > dealing with completely immutable objects, and therefore not have > __assign_* methods. Similarly, I don't think should have overloads for > ++ and -- (the proposed /__(post|pre)_(inc|dec)/ methods). Heck, they're > probably not even that useful, because you could simply check in __add > or __sub if the operand's absolute value is 1. > > Regarding the possibility of comparison operators, again I think we > should go the simpler route. For <, <=, >, and >=, we only need one > overload method, perhaps __cmp, which returns the usual negative, zero > or positive value to indicate ordering. I can't see a benefit of having > a seperate methods for each of these, and it would introduce the risk of > them being implemented inconsistently, creating chaotic sorts. Similarly > for == and !=, we only need a single method, perhaps __is_equal, or > maybe we should not give them a separate method and group them with <, > <=, > and >= into __cmp, which would again have the benefit of > preventing inconsistent implementation. For === and !==, I would be wary > of letting them be overloaded, given they are currently "strict", and it > is useful to be able to check if two objects are the same instance, > something objects shouldn't need control over. == and !=, on the other > hand, compare content, which the objects themselves can probably decide > better than PHP's default behaviour. > > Anyway, I appreciate you making this RFC, if only to prompt discussion. > > Thanks. > > [0] > http://hackage.haskell.org/package/base-4.8.1.0/docs/Prelude.html#t:Num > [1] > http://hackage.haskell.org/package/base-4.8.1.0/docs/ Prelude.html#t:Fractional It looks like I'm late to the party for this discussion, but I feel like this is a similar concept to the already existing Comparable RFC , which in my opinion, has a much better interface. Is this slightly more in-line with what you're thinking with type classes? I'd say this RFC should address the Comparable RFC since they are in direct "conflict" (not quite the right word there). Perhaps instead group relevant operators into magic interfaces like Comparable, Arithmetic, or something along those lines. I'm in favor of operator overloading, but it really needs to be done with much care.