Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115660 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 7794 invoked from network); 8 Aug 2021 02:50:31 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 8 Aug 2021 02:50:31 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 1EBF01804D4 for ; Sat, 7 Aug 2021 20:20:23 -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.2 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE, URIBL_SBL,URIBL_SBL_A autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-qk1-f174.google.com (mail-qk1-f174.google.com [209.85.222.174]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sat, 7 Aug 2021 20:20:22 -0700 (PDT) Received: by mail-qk1-f174.google.com with SMTP id a19so14603554qkg.2 for ; Sat, 07 Aug 2021 20:20:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=newclarity-net.20150623.gappssmtp.com; s=20150623; h=mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=u/pVzHUVmBU0vWqDPtvi0ZomvCArFHPUreEHPsc2Pns=; b=f4VjW3gN/wnrv23u6Z0Wo+wiBPfXHittWFHD0V31RXxpoglW93VdWpM16wcOsxd1dW sdloKS9EB2QxPEkdUMZ1SCahkszCOn9fzOJ5/gYWp43TTIfEJD2DYybDTWvIyjfB2Ymm 97Ap3wwuS3v86GiyCiMzQ3BWejiCyhqPQrEefHCYUB3mzufwgcdOJSy3wa7dTAUOC362 aEfN52/eG/ke2FMw539BMKe5ZIIsJ9wGCE24oyfr/Co3xTkvlrKciiOrAkANxwfquwZa wNCzZo2ueVvbP6oWqJyxbR3FUxBzTxCiTgSKeCpSllbY3b9V+IBazaRLWRf0SRA09NgG oafQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=u/pVzHUVmBU0vWqDPtvi0ZomvCArFHPUreEHPsc2Pns=; b=g/2MEU+Qavq9oyZq0IBROUqIwIJWCekDPPGpbJ4MHKeRlW7IXaBomNKd2GhKtXjJNw HZ6gz7GaN3tscnH2UQnRa51V6R8HC8XUBwbQRipFDsk3yuxxMrUe+j0aueKOchmjpkuu Fv5DhsXLbfoW0ZQQij3rxLXZ0xzMrPii/NVwXVNd/sqp99S3odEgeLdM2tACYFlsBnDv mfmV8gR2mBul6qCWfH89NlcHTOX4ecwdsxhvGk3qy/KquF2Bhw1OBRSZz/PtJzHEy8i0 6uQ8a5JzkPVqL1OubMcGk5u7VnOWbhtWNFTROCG06KvbC9Lly/QGyDmxFRaQLaApb+Jz F2fQ== X-Gm-Message-State: AOAM530NMO/M7qi5RAD8S1gGbL81PKfmfSBlEu+EJezQ1ZHgEW/rWu5j X3CtRBm+v/jM3MWhux5zQfOy5sK6vydKzg== X-Google-Smtp-Source: ABdhPJxeSjt8Q0Jbf0GCcQ6COK100kz3rhtsEzOShhKG+eXBTiVxGF/UD00EMFDjuGNiPD3HAoAw9A== X-Received: by 2002:a37:58e:: with SMTP id 136mr657049qkf.286.1628392821548; Sat, 07 Aug 2021 20:20:21 -0700 (PDT) Received: from [192.168.1.10] (c-24-98-254-8.hsd1.ga.comcast.net. [24.98.254.8]) by smtp.gmail.com with ESMTPSA id 71sm5429293qta.25.2021.08.07.20.20.20 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 07 Aug 2021 20:20:20 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.7\)) In-Reply-To: <94696d46-c4e6-406a-b859-89144bff31bf@www.fastmail.com> Date: Sat, 7 Aug 2021 23:20:19 -0400 Cc: Scott Arciszewski , Larry Garfield , Dan Ackroyd Content-Transfer-Encoding: quoted-printable Message-ID: References: <94696d46-c4e6-406a-b859-89144bff31bf@www.fastmail.com> To: php internals X-Mailer: Apple Mail (2.3608.120.23.2.7) Subject: Re: [PHP-DEV] Revisiting Userland Operator Overloads From: mike@newclarity.net (Mike Schinkel) > On Aug 7, 2021, at 10:28 AM, Larry Garfield = wrote: >=20 > The downside is that 30 seconds after that, 15 other libraries would = do the same in subtly incompatible ways, and then both Laravel and = Symfony would release their own that are incompatible with each other, = and it would just be a total mess because you would have NFI what any = given operator is going to do. Then FIG would try to define a few to = standardize the madness, would take about 10-12 months to do so, but = both Symfony and Laravel would go on using their own instead because = they're big enough that they can do that, and we'll have a mess = basically forever. That is what my crystal ball tells me would happen. >=20 > So while this approach appeals to me personally, I think in the long = run it's probably a bad idea. My understanding is that many people = consider C++'s adoption of this approach a mistake, although I'm not a = C++ developer so cannot speak from first hand experience. I strongly echo Larry's concern here.=20 While I tend to be one who wants more language features, not less, the = availability of unconstrained operator overloading can beckon an = inexperienced and/or undisciplined developer to add operators for many = of the classes they implement, whether or not doing is actually = applicable or a good idea. I am even concerned about constrained operator overloading for the same = reason. Here [1][2] are a couple essays to argue against operator = overloading. Ruby has operator overloading, and one of the distasteful aspects I = found regarding in programming in Ruby was that everybody's Ruby code = you looked at felt like I was written in a slightly different language. = I would hate that to become the case with PHP, more than it already is. I am actually surprised that the last operator overload RFC came close = to passing because adding it seems like it would open a Pandora's box = and yet other proposals that are less Pandoric seem to be anathema on = this list. That said, I am not unsympathetic to the fact that operator overloading = may well have some extremely valid use-cases, just ones that I do not = personally seem to need on a day-to-day basis when writing code. Operator overloading seems to me to be of more value to those who are = essentially wanting to write DSLs (domain-specific languages.) If that = is indeed the case, and there are some DSL like features I wish we could = add to PHP that would generally be non-starters for non-DSL usage. I wonder if there is a way to limit to only DSL use-cases? I doubt = there is, but I had to pose the question in case someone else can = envision a way to do so. So my main questions are: =20 1.) What are use-cases where operator overloading would really be = valuable? =20 2.) Would it possible that instead of adding operator overloading we = could add classes that could be extended where PHP actually defines the = operators for those classes? =20 If we can do #2 we can really work through all the issues with = commutativity, associativity, etc. and also implement all and only the = operators that make sense for the use-case. > On Fri, Aug 6, 2021, at 3:18 PM, Scott Arciszewski wrote: >> My recommendation is to have a base interface for every operator that = can >> be overloaded, so that these can be composed together. >>=20 >> AddOverloadInterface { __overloadAdd(): self; } >> SubOverloadInterface { __overloadSub(): self; } >> MulOverloadInterface { __overloadMul(): self; } >> DivOverloadInterface { __overloadDiv(): self; } >> ModOverloadInterface { __overloadMod(): self; } >> LeftShiftOverloadInterface { __overloadLeftShift(): self; } >> RightShiftOverloadInterface { __overloadRightShift(): self; } >> XorOverloadInterface { __overloadXor(): self; } >> etc. >=20 > That would be roughly how Stringable/__toString works now. I'd be OK = with that, if it's going to be a language trend. If this is how it turns out, I would hope for consistent naming, e.g. = Addable vs. AddOverloadInterface, Subtractable vs. SubOverloadInterface, = and so on. > On Aug 7, 2021, at 1:48 PM, Dan Ackroyd = wrote: > On Fri, 6 Aug 2021 at 21:18, Scott Arciszewski = wrote: >> It's probably worth exploring whether common combinations are worth >> defining for convenience. > My understanding of the current consensus is "let's not". >=20 > That's based from the discussion on whether defining 'number' as 'int > | float' would be worth doing, mostly because adding aliases don't > provide much value,=20 While it may (or may not?) be consensus, I argue the counter which is = that adding `number` to PHP to mean `int|float` would provide the value = of: 1.) Standardization and=20 2.) interoperability between libraries that use `number`. =20 This argument *assumes* there would be a strong consensus that `number` = should actually mean `int|float` and not something else, or not some = other name. For clarity I am not arguing that number *means* int|float =E2=80=94 I'd = have to review the debate and see if there was strong consensus =E2=80=94 = but instead that *if* there is strong consensus that the term `number` = *does* unequivocally mean `int|float` then there is a value to adding = `number` as an alias to PHP, again for 1.) standardization and 2.) = interoperability. > and once you've started adding some, where do you > stop? e.g. if we defined 'number' why not also define 'scalar'? Yes, assuming there is strong consensus on what `scalar` should mean. I would use the same argument as above to support adding `scalar` as a = standardized union type. > The value for interfaces is even lower than other types, as it's > already possible in userland to define your own combination types: >=20 > interface MatrixMath extends __AddInterface, __AddSubInterface, > __AddMulInterface {} >=20 > as interfaces can extend multiple other interfaces at once. > On Aug 7, 2021, at 6:28 PM, Larry Garfield = wrote: >=20 > I would argue that the micro-interface approach has a far better = success rate in PHP, especially when it comes to "magic" behavior/engine = hooks. If we're going to adopt operator overloading, that is the safest = middle-ground to take. I think this it yet another argument for implicitly-implemented = interfaces as I mentioned last week[3]. Agreed, micro-interfaces are definitely a better approach, but having to = explicitly mention them limits their defacto-standardization and thus = adoption. One reason is two libraries are unlikely to both use a 3rd = party interface that forces a dependency, and thus they will often = create two potentially-conflicting interfaces. So the implementor of = their interfaces can often only implement an interface from one or the = other library, but not both and users of that interface has to choose = which one to accept in their variables and parameters as well as which = one to return with their functions and methods. OTOH, two differently named implicitly-implemented interfaces are = compatible if both have the same signature. A function that accepts as a = parameter an instance of a class from one library that implicitly = implements its own interface can accept an instance of a class from the = other library that implicitly implements its other = identically-signatured interface. Thus interoperability is improved, = defacto-standardization is more likely to occur and serendipity is born, = as has been shown to be true in the Go ecosystem. Implicitly-implemented interfaces give us a better way. The library = vendors after the first could write classes that are compatible with the = original libraries, even if they are competitors, without having to = force an external dependency on a (possibly competitive) library.=20 Laravel and Symphony would be more likely to see eye-to-eye on at least = a few of their interfaces even though their overall philosophies are so = drastically different. > Conversely, if you want to accept an object that is addable, = subtractable, and comparable, you can type it exactly like that: >=20 > function foo(Addable&Subtractable&Comparabie $var) {} That really begs for userland-definable types, e.g.: Additive[4] type Additive =3D Addable&Subtractable&Comparabie function foo(Additive $var) {} That's been discussed many times before but AFAIK is not moving forward = by anyone. (I would propose, but with so many RFCs that I would like to = propose I would not know how to implement.) Is there some prerequisite we need to achieve before we can pursue that? > To be fair, this approach would not prevent weirdos like me from = implementing __add() and using it as a Monadic bind operator or = something silly like that. However, I believe experience has shown that = a combined Arithmetic interface wouldn't stop me from doing silly things = either, given experience with ArrayAccess. Agreed. That is why (IMO) (almost?) all interfaces added to PHP should = either be individual, or an aggregate of other interfaces. =20 If ArrayAccess where simply the aggregate of these interfaces PHP = developers would be in a better position: interface OffsetExists {...} interface OffsetGettable {...} interface OffsetSettable {...} interface OffsetUnsettable {...} -Mike [1] = https://cafe.elharo.com/programming/operator-overloading-considered-harmfu= l/ [2] = https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/=20= [3] https://externals.io/message/115554#115603 [4] https://english.stackexchange.com/a/170247/1164