Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115659 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 99572 invoked from network); 7 Aug 2021 23:34:17 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 7 Aug 2021 23:34:17 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 0B7D01804AA for ; Sat, 7 Aug 2021 17:04:08 -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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS 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-lf1-f49.google.com (mail-lf1-f49.google.com [209.85.167.49]) (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 17:04:07 -0700 (PDT) Received: by mail-lf1-f49.google.com with SMTP id t9so26097842lfc.6 for ; Sat, 07 Aug 2021 17:04:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=KGl8l1oH3xneGCYloqZKLQWKXtJk7xrSHU2sTAUBaxM=; b=TkW+BM/U98IpS3WA/biGr6+cttJFW/wTecYXJ7xsE8WP/fgx0QG/Nr71Yegh+A6cLb jN9DMdPp4ayufAVaUqdATxyeHfMjaAw4z9OSoJXM6oDr6C7/KMC/L/TOzeP9UWRflV9W ASf3KCBgV7PrTRGA1fqiNMkpM6K+KEK7WnX5gNyHklGXULuuFrfl2rGq9KeEWFld4DX5 Fop0HTiGb2cPvMRrkl3QTu7rf4xT9/pCDY+H+ZTPd/cSX/ZPO0uWxlmnwGK2Pz4gS2cw 2a/cPse6awPR9SGRew2LZVWtJrnTA2qBxzb2FteXL4gUCZUaHtYZwPudGqC+Q+eA0rYs CKZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=KGl8l1oH3xneGCYloqZKLQWKXtJk7xrSHU2sTAUBaxM=; b=B9i3oMtn4ej7GRI/K+aV4WKywoOPja//3AXePBQW+HD+tXCF8r98I8/WghAZu3ph53 lOwGLuu5dAJUnjh84Rehn+6MLYsgm4Fwt7BTftQ6kMP+U3f+bGRKqWaBA5MD3Qq4rKk+ +F2JlhlbMMJZkG1DSVxMzirddCT4Ff4rtRbULgO9rk/tI401o+TCmsb8WGYRNcztDLZ1 3pDOETog8I9M+eMJiAlhY2ZgBJBSKsHc2bOO5+Y5jTH1piDT6EuRWNfa/ZV1DnVNqTSK J51GjEJq43SPzVruRyH9UWc0njS+rn6XfHDKVaUQozPLTlw4i2FDVsMmMWjX2nmnkJW4 vB4A== X-Gm-Message-State: AOAM531Z1bWQZRSh8XFlgLb0UxjeU1vr7OOPbqsWvMAJ8MkOq4XHqpgx RL4Rwwa0zB8oQ4BzQjAvb7m2OWRMHB/BZuKk/GRT6D7KzjPtzA== X-Google-Smtp-Source: ABdhPJzykP5aOMQ75qRsldls7Qe9cLSHH2b2NmQ/BKZwHZh8mcFM+weJFlkdlM0STSyCwphuFlxCE6CXKefj+1Gs1bg= X-Received: by 2002:ac2:5394:: with SMTP id g20mr11697312lfh.603.1628381045684; Sat, 07 Aug 2021 17:04:05 -0700 (PDT) MIME-Version: 1.0 References: <94696d46-c4e6-406a-b859-89144bff31bf@www.fastmail.com> In-Reply-To: <94696d46-c4e6-406a-b859-89144bff31bf@www.fastmail.com> Date: Sat, 7 Aug 2021 17:04:08 -0700 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary="000000000000c97bc205c9010176" Subject: Re: [PHP-DEV] Revisiting Userland Operator Overloads From: jordan.ledoux@gmail.com (Jordan LeDoux) --000000000000c97bc205c9010176 Content-Type: text/plain; charset="UTF-8" On Sat, Aug 7, 2021 at 3:29 PM Larry Garfield wrote: > > Side note: Please remember to bottom-post. > (trimmed message) > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > > Sorry about top-posting. :) Your arguments for why grouping is undesirable are very persuasive. While I don't think that having exceptions thrown from stubs is necessarily a bad thing, I definitely understand how this suggests that the grouping is unsuccessful at "hinting" the developer on implementation, and also how the grouping may be too restrictive as a language-level feature. ArrayAccess really is an interesting comparison. I did very briefly consider the idea of implementing a *single* magic method: __doOperation(string $operator, mixed $lhs, $rhs = null) After thinking on it briefly, I came to many of the same conclusions: this would result almost invariably in further fracturing between a "Laravel" way of doing things and a "Symfony" way of doing things which would be wholly incompatible and inconsistent. It would also be... complex for IDE's to support in any meaningful way, especially for custom operators that are not part of the interpreter. (It also would be far more complex for me to implement as it would probably require some careful changes to the compiler.) So I'll simply disqualify the idea of custom operators right now. I do understand, like you, why some people might want them and use them, but I feel like it's too complex and risky of a change, and at its core, not a change that I want to make, so someone else would need to actually do the RFC if that was the case. > The 4 arithmetic operators, concat, and compare. I would argue that both modulo and pow (% and **) are arithmetic operators that should come with the basic four as well. Meanwhile, I think the concat operator is both more prone to error *and* less useful. Currently, if you try to concat an object, it will be cast to a string, and since __toString() already exists, this behavior can effectively be controlled already. The main reason that other operators couldn't easily be solved with supplementary __to*() methods is that for *many* usecases where you'd benefit from overloading operators, the scalar types don't adequately capture the state (which is presumably the reason that the program is representing them as objects). Further, as detailed in my earlier reply, I don't think we can get away with only allowing compare. Complex numbers are a trivial example of why, but there are many others where only some of the comparison operators make sense. We could, however, allow compare as a minimal implementation to support the others. If it is implemented, then the others can be derived, but if it is not then the other comparison operators should be able to be implemented individually. > None of these approaches resolves the commutability problem. There is no guarantee that $a + $b === $b + $a, if $a or $b are objects that implement Addable. I don't think this is a problem which can be resolved without some extremely strict limitations on the operator overloading. (Something like, objects can only be on both sides if they are the *same* class.) Even then, there is little we could do to prevent the user code from doing something like: function __add($rhs) { return (random_int(0, 1) == 1 ? true : 5); } As such, I think the idea of operator overloading is fundamentally incompatible with the concern of ensuring commutability. In fact, *many* of the usecases for this feature would *depend* on them not being commutable. For matrices, A * B != B * A except under specific values. This is in fact part of the definition of multiplication under matrices, so I feel that wanting to ensure commutative behavior actually represents misunderstanding the feature itself. Extending the native operators to work with matrices using an internal implementation would *also* result in non-commutative behavior, because that's the *correct* behavior for matrices. I do not see this as inherently a problem to be solved, but it is a thing to keep in mind when considering the implementation. > Should the methods in question be dynamic or static? In my mind, the only argument for static is that it makes it more likely that they'll be implemented in an immutable way. I also think that dynamic methods are entirely possible here. While immutability is an inherent property of using operators in nearly any context, it's not something that we can guarantee when we leave the implementation of operator handling up to userspace, and requiring statics won't do that either. Laravel as an example uses static properties and the __callStatic() method to provide mutable static calls everywhere in the entire framework with Facades (something there are very strong opinions about in userland). As such I think that requiring static methods is a way to make internals "feel better" about it without actually providing any real guarantees of consistency or immutability. > What if any type enforcement should the language force? Personally I do not think that any type enforcement should be required. I think it should be *possible* if the application wants it, but I don't think it should be required. Jordan --000000000000c97bc205c9010176--