Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:109376 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 36972 invoked from network); 27 Mar 2020 21:44:50 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 27 Mar 2020 21:44:50 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 921EF180088 for ; Fri, 27 Mar 2020 13:10:04 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=BAYES_20,SPF_HELO_PASS, SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS31103 84.19.160.0/19 X-Spam-Virus: No X-Envelope-From: Received: from mail.toneristzuen.de (mail.toneristzuen.de [84.19.169.162]) by php-smtp4.php.net (Postfix) with ESMTP for ; Fri, 27 Mar 2020 13:10:03 -0700 (PDT) Received: from maniacmansion.fritz.box (ppp-188-174-86-103.dynamic.mnet-online.de [188.174.86.103]) by mail.toneristzuen.de (Postfix) with ESMTPSA id 1A71249AFC; Fri, 27 Mar 2020 21:10:02 +0100 (CET) Message-ID: <7a83f950a31d94d5ff2307ac8219db3b7b6482b6.camel@schlueters.de> To: jan.h.boehmer@gmx.de, 'PHP internals' Date: Fri, 27 Mar 2020 21:10:01 +0100 In-Reply-To: <003701d6013c$9afe9750$d0fbc5f0$@gmx.de> References: <003701d6013c$9afe9750$d0fbc5f0$@gmx.de> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.28.5-0ubuntu0.18.04.1 Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] [VOTE] Userspace operator overloading From: johannes@schlueters.de (Johannes =?ISO-8859-1?Q?Schl=FCter?=) On Mon, 2020-03-23 at 18:58 +0100, jan.h.boehmer@gmx.de wrote: > Hi internals, > > I have opened voting on > https://wiki.php.net/rfc/userspace_operator_overloading, which allows > users to overload operators in their own classes. > I consider operator overlaoding in general a good feature (while PHP's overload for + on arrays is weird) However I don't like this design. Consider this case: Some library provides a type A without overloads. I then create a type B with overload: class B { static public __add($lhs, $rhs) { if ($lhs instanceof A) ... elseif($rhs instanceof A) ... else error } } as I want my type's addition to commutative I handle this with some if (probably dispatching. Now I can invoke it: new A() + new B(); // calls B::__add() new B() + new A(); // calls B::__add() as well Now the maintainer of A implements the feature request "A should allow addition with integers", I update my library and suddenly weird things happen. new A() + new B(); // calls A::__add() and explodes, as A doesn't know B new B() + new A(); // calls B::__add() works as before Now we could establish the best practice that one type's operator calls the other type's operator in case it can't handle a type. However that is no good option as it will lead to infinite recursion if neither type can handle both operands. The issue is that by forcing type declarations as part of the class, as members, this forms a closed set, but for many cases a strict closed set isn't what one wants. For mathematical types having operators working with integers (and other numeric values) is essential. Communativity often also is required. So a true closed set doesn't work, for an open set can't be created easily in today's PHP. Thus the RFC tries to tie this together, but this will fall apart and then cause legacy and BC reasons preventing future improvement. I believe the pre-requisit is having some form of function overloading, where operator functions for specific argument types can be defined. In https://news-web.php.net/php.internals/108425 Andrea created an idea, which is probably "ugly" but has less usage restrictions. I think spending time on function overloading (I believe, without proving it, this can be done with very little cost for non-overlaoded cases - by adding a flag "overloaded" along visibility flags and check that along with the visibility check, only in case of an overload to the "expensive" check, which still is cheaper done in the engine than if/else chains in userspace) and then take up operator overloading again, rather than this smart but limited approach. (For whoever does that: spend time in C++ and its function resolution rules incl. ADL, not to copy, but to learn) johannes