Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:108882 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 49312 invoked from network); 6 Mar 2020 09:57:32 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 6 Mar 2020 09:57:32 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id DC2DB1804D8 for ; Fri, 6 Mar 2020 00:17:20 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS8560 212.227.0.0/16 X-Spam-Virus: No X-Envelope-From: Received: from mout.gmx.net (mout.gmx.net [212.227.15.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 6 Mar 2020 00:17:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1583482638; bh=m3+XkjiuaGOpXzVHKthWjjxFpzdvnqeN750NzPp4Rdc=; h=X-UI-Sender-Class:Subject:To:Cc:References:From:Date:In-Reply-To; b=LQ21V4/Lg5tALgn2PbrI/Z2QvAdks2txAKL4GWlVl8gucLE6i6k2T4/XiezYmC6H1 vbMR0vbwYvrr33Dyp28xV9OIztqnbpQ8TgkyMFn5AwmT8h/E+DOQObkRHsyy/N7QyO 8Qrg+9oDGTrG6gwkSMKGgvCcdesJwxL1WPF7H9GY= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from [10.140.116.64] ([141.35.40.27]) by mail.gmx.com (mrgmx005 [212.227.17.190]) with ESMTPSA (Nemesis) id 1MrQEn-1jfw5q3urP-00oUKs; Fri, 06 Mar 2020 09:17:17 +0100 To: Nikita Popov Cc: PHP internals References: <005101d5edae$7b7c3e10$7274ba30$@gmx.de> Message-ID: <8776962f-71ac-0ee3-a1b8-42eb2926eef0@gmx.de> Date: Fri, 6 Mar 2020 09:17:17 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/alternative; boundary="------------0E952C50C3786B4B50FD13CD" X-Provags-ID: V03:K1:DNu9Ap7TnHh/+oGYF1GWriiJBuU1cE1I+29h1Lhb2I02PdYB0fi EF6KW4HRI+3sy40S1ZBPE+TJbBPKe9Xh0CpM/CJW+WTNrHpqB1w/n+T8a6VCiQnrWtODjH8 oKdzQ5DPoIJQXu0glYRX1mMY38oh6NvBcanvk3HCLaSfe4hkU9Me23cMebr6nzKN6EmLtTL Qf88hdVQ7KaF4TZHCrWRA== X-UI-Out-Filterresults: notjunk:1;V03:K0:mN2trQgeeH8=:C2LCyOxwHYKvVi6LlW9Sdo Y9goOmr/hBCnP8+guaJtPuwiHpURtnS4eNa8nALwKvUIywFw5E6rhOHcgy3DVC7y7bR1FxjRk SnO854GO4Y+XLVAH9cSeRL796FC/uWHaamRYM4RZCU9xqqcV/iUNbMTDJgwY2jOmSL28GWCio L4pzILwaB8KU2ADp74P2n7/xzbWacc0wfDMLF4CTxPieeEBAYQDm7dCG6tB4Y/31AqPmGLdKg Tkgx/IemHtAWZrgsj9Zoxv6Fw4fupAQaFNV8vHNJsdw6PaS125i27TMa8qEcW1Js1PU4uesQK 2eoKCsInW9t3UOaxrb3isvxNkRONr63SrdjgA5dcs/zT3jm8ZlJgBbhezB3kbKTGlFf5g60wh iuQYbt3dmRCWo06kan5W5tpgMBu48s60iuujDi3/81b/832Ngvz3oRkinfzymMXWsPXj7LhWA OhpRJAtyKfkNmjBG2Fyhe5uBE8be/SsE3JyCCbLr9mf+BwsGeDRdVrb2XmIsqshH2k3WwYDmO gdIFpWV8ZKUHnUkjbc16/M3x1mJeOCFc70YWWep0bFa0gHrPo9cJcK0guJXlJtMrWv1XfskNC GzzlZ2TyjZymE85ef9LS/lw6XqUMTimbZiF7uRPHbRq4goS0y7y3pSwZpCBhOAeEkecLEwJpN xRoGgtpO2JnJUBUYvXeX+3lbM1s0d+D1lKRkY78CooAAqaHU5XMOHcj/PDp1RU4h/fKJ0xSjU R4Ixvm7h9IZwyAVSImLxPcaVRwIibyJN8+vzCyrbJBWdO9wevwxYSRhrUM0V3N/EIkkugC4D4 WK/7MWnduUkmCmDbbqEQX0jZsMYX9Uyimi1FlYe7VVduTXtAs40uA7Br2fPjCj8DhN1q+tjpe Uacaj5X1do//loJVyT0vh+z7NZxXZBboXkODCJeCeS+2A4SV0afMM48N1FhK+a+xP8pe/hXtB OGcuAxFS+Qq4CuttOJY7WeP18vl2vuuqdLI1R418OmKFLHH5fcuK0OA7dueiE4dRJhPBe1i2H e30hu94GBUj3yTGJ2HXHPNDZwtXUyKCF81kKLuIs12ce2MPsEqvoBdAaK6FsQBElsj3mHDrSG C8wrr2WkAHI8EBnByS54x2Pkqa5Tp7bZggQdUGUUlmSp74NalBRKOSMQZumKnaAFFS4HicldU BV3tYOoNzWDliW/HP4EowzhhOjYmoNYcUHpKWA1Jwr5ZHn7YnbIhySOfjLwaWH2c7k7LthwYh jP8kiiuLGS+IhsmB+ Subject: Re: [PHP-DEV] Re: [RFC] Userspace operator overloading From: jan.h.boehmer@gmx.de (=?UTF-8?Q?Jan_B=c3=b6hmer?=) --------------0E952C50C3786B4B50FD13CD Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Am 02.03.2020 um 15:30 schrieb Nikita Popov: > On Thu, Feb 27, 2020 at 9:43 PM > wrote: > > On 15/02/2020 22:05, jan.h.boehmer@gmx.de > wrote: > > Hi internals, > > > > based on the discussions here > (https://externals.io/message/108300) and > here > > (https://github.com/php/php-src/pull/5156), I have created a > proper RFC > for > > userspace operator overloading: > > https://wiki.php.net/rfc/userspace_operator_overloading > > > > The main differences to my original concept, is the removed > __compare() > > method (comparison overloading is a complex topic and should be > handled in > a > > different RFC) and the possibility to signal that the operator > handler > does > > not support the given types (by typehints or returning a special > value). > > This way, only one of both objects has to know about the other > type. This > > should expand the use case of operator overloading compared to > my old > > concept. > > > > What do you think about the RFC? > > > > Some discussion points, I can think of, would be the naming of > the methods > > (maybe naming them after the operator symbol and not the > arithmetical > > operation they represent, e.g. __plus instead of __add) or > putting the > > methods inside of interfaces like done for ArrayAccess (But I > don=E2=80=99t see > any > > advantage in doing so, as it is very difficult grouping different > operators > > in a single interface usefully. Also, operators can accept and > return > > different types, so there is no real common interface between > classes you > > could rely on). > > Furthermore, maybe the idea of allowing operator overloading in > general > > should be discussed as it is sometimes considered an > anti-pattern (e.g. > the > > usage of '<<' for outputting a string in C++). On the other hand > there are > > many languages and libraries where operator overloading is used > successfully > > (e.g. numpy in Python). > > > > Regards, > > Jan B=C3=B6hmer > > I have changed the proposed names for the bitshift handlers to > '__lshift' > and '__rshift' (instead of __sl and __sr) to make more clear what > operator > is handled by the method (also the method names are now mostly > consistent > with the Python equivalents). > > How many of you would prefer a interface solution for operator > overloading? > I wonder if the RFC voting should include the option to choose betwe= en > either the magic method approach (with the syntax proposed in the > current > RFC version) or using interfaces. > For an interface version I would suggest these interfaces: > ArithmeticOperators (implements +, -, *, /), PowOperator (**), > ModuloOperator (%), ConcatOperator (.) and BitwiseOperators (~, &, > |, ^, <<, > >>). > What would be appropriate names for the interface methods? If we > just name > them after the operation (like add()), it will become difficult to > integrate > these interfaces into existing code, as add() is already a used > function > name in many cases, but uses a different signature (non-static > with one > argument, whereas the interface needs a static one with two > arguments). > > Regards, > Jan > > > Some notes: > > Naming: If we're already going for more verbose names, I'd prefer > __shiftLeft over __lshift. It may also make sense to use __bitwiseNot > rather than __not, as it's currently not obviously whether it > overloads the ~ or the ! operator. Similarly __bitwiseAnd could be > better than __and, to make it clear that this is about & and not && or > "and". Same for the other bitwise operators. > > > -$a is interpreted as (-1 * $a). > > As you mention this, for completeness: +$a is interpreted as (1 * $a). > > It may be worthwhile to give a more explicit list for a) operators > that can be indirectly overloaded (and their desugaring) and b) > operators that cannot be overloaded (like the boolean operators, > comparison operators, instanceof, probably others). > > > If the operator handler function declares typehints (e.g. public > static function __add(Vector3 $lhs, int $rhs)), the function handler > is not called if the operand types do not match the signature, and the > other operand's handler is tried to call. > > I'm somewhat skeptical about this. This smells of method overloading, > and we don't do method overloading. There is no other place in PHP > that would perform dispatching based on the method signature, even if > in this case it's not a choice between multiple methods on the same > class, but rather multiple methods on different classes. Some of the > usual problems of method overloading don't apply here (in particular, > one could make a reasonable argument that the method on the first > object should be chosen, even if there is a more specific signature > available on the second object), but I'm skeptical about introducing > this kind of special case in the language specification. > > Regarding interfaces: I pretty strongly think that using interfaces > for this purpose is not a good idea. Interfaces are about contracts, > and there is no way (within the current limitations of PHP's type > system) to define a useful contract here. > > I think others have already expanded on why it's not possible to group > operators in a meaningful way. The DateTime example is probably the > most pertinent there, in that DateTime + DateTime is illegal, while > DateTime - DateTime is legal. If we can't even require both + and - as > part of one interface, there is very little we can require. > > However, even if we split each method into it's own interface, what > we'll be left with is something like > > interface Add { > =C2=A0=C2=A0=C2=A0 public static function add($a, $b); > } > > What does this interface tell us? Pretty much nothing. It tells us > that there probably exists at least one type with which this object > can be added, but not what that type actually is or what the result > type would be. There is no way to build code on the contract of "the > object is addable with *something*". > > To make this useful, the interface would actually have to look > something like this: > > interface Add { > =C2=A0=C2=A0=C2=A0 public static function add(T1 $a, T2 $b): T3; > } > > and then DateTime would implement something like this: > > class DateTime implements > =C2=A0=C2=A0=C2=A0 Sub, > =C2=A0=C2=A0=C2=A0 Add { ... } > > That's a contract you could build code on, though it would be rather > cumbersome. But in the absence of generic types, having an Add > interface is not useful. > > The way I see operator overloading being used in PHP, I would expect > code to be typed against specific classes, not supported operators. > The vast majority of code will be interested in accepting a Money, not > an Add. > > Regards, > Nikita I have changed the names of the handlers like you suggested and added two tables which show what operators can be overloaded indirectly and which can not be overloaded at all. Thank you for your suggestion. I agree with your opinion with on interfaces, I think using magic methods is much more reasonable. Your point about the "smell of method overloading" is interesting. In my opinion this mechanism makes it a bit easier to use operator overloading as you dont have to do tedious typecheckings on your own in simple cases. But I agree that this behavior is a bit odd compared to other PHP features. That feature is not really needed for operator overloading, as you can use the PHP_UNKNOWN_OPERAND_TYPES const for signaling that the handler does not support the given types. If you (the internals developers) says that this does not fit into the concept of PHP, I will remove it from my RFC (or put it in a separate votation, if wished). Regards, Jan B=C3=B6hmer --------------0E952C50C3786B4B50FD13CD--