Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:116690 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 4549 invoked from network); 20 Dec 2021 23:40:00 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 20 Dec 2021 23:40:00 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 149E3180541 for ; Mon, 20 Dec 2021 16:43:34 -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=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE 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-ua1-f49.google.com (mail-ua1-f49.google.com [209.85.222.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 ; Mon, 20 Dec 2021 16:43:33 -0800 (PST) Received: by mail-ua1-f49.google.com with SMTP id o63so8525324uao.5 for ; Mon, 20 Dec 2021 16:43:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dqxtech-net.20210112.gappssmtp.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=10Hub6NvUZrvRT1Tp1n2FHcUbYx8vcXwoCFfaQNHpD8=; b=AYPGeeyjIVxWzSB0gCaoInL1dwsFSwE2G336PfOhKmIWOVLsxIVcma9sFT077zJ3WM KzrfLzBxLCSRlX8ROvUUPXTUK8OTUCKLi8hWgpNdVybkcqqTC0IHSNh/GMjXKemg26Wj tzKSuICe3rzn7fMn6ME3z1/G7unZaTGIoCPSbmXkfxO/IDOMPQibkN7qgciJvk5lw0jC j19D5t5ray6e8lzoJJVFnGuV0t0VWLKIkxlLOOa3aRQB4flJWWYhPZHUa9GuOBCOCARA zsQwNrlo3UhilENMCL9n3OZTBHTeSfxCw/SQ41KX0VFDrxkLjRERuS2PG+3pP/ebTbid rbbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=10Hub6NvUZrvRT1Tp1n2FHcUbYx8vcXwoCFfaQNHpD8=; b=u2r1FP9w+n1Pru8eY2RWUFZKmxe27BbvwvaleaFG8A0a43Y68uMcSLzt73oML5at+E x2o3mro18OOS8pwXKJ9+N4P9eq8RQvUjFBtFpv7WJWZ+6ipHv8r16Ojh1BB0LOTh8q/E Bf4zXFyTm7EF1DvNFPobv0ktfxnujA0MEYLf4Gb1sPTpFDw0reEOHsMArSWUml+586vj PfEi3eK3SPYBTBmmu6wsUvY0N5gGUMtDiPP6eu3qJGRNPi8qCHYxxgjOPIXAj4EtBiEb rRyuMYFK+iFKuU6VSMHvnp9khRVMvj0oFNhmIrRRmiylx4hnCO8bmWErwQBd9BdRIPoC T3hA== X-Gm-Message-State: AOAM533jAE8ds3ZFmQ9tiTv1oQkoXZUXNDIqlHd97+jHPVSbV5e10iqA iUQc/HmPcQDvEAxyS6WE3KOnD4QWGcm2ktrfYB5pQg== X-Google-Smtp-Source: ABdhPJyMLpyOu4MacPDlEC3UQPwmiRoNpCvt7QYwkzM0w+7d8Q4B30SfeCCp7KhZYvLeUIvUDfuIZ+NVax68UN61yUI= X-Received: by 2002:ab0:6848:: with SMTP id a8mr322846uas.137.1640047412755; Mon, 20 Dec 2021 16:43:32 -0800 (PST) MIME-Version: 1.0 References: <44b3fb4b-4693-1639-c8c0-5e17296c196e@gmail.com> <4b58c011-ed87-ba87-201d-0cf8e4116c6f@processus.org> <67431363-cd1e-9575-7d51-0f4d265d05b9@gmail.com> In-Reply-To: Date: Tue, 21 Dec 2021 01:43:21 +0100 Message-ID: To: Dan Ackroyd Cc: Stanislav Malyshev , PHP internals Content-Type: text/plain; charset="UTF-8" Subject: Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6) From: andreas@dqxtech.net (Andreas Hennings) On Tue, 21 Dec 2021 at 00:03, Dan Ackroyd wrote: > > On Fri, 17 Dec 2021 at 18:36, Stanislav Malyshev wrote: > > > > When reading > > this code: $foo * $bar - how do I know which of the ways you took and > > where should I look for the code that is responsible for it? When I see > > $foo->times($bar) it's clear who's in charge and where I find the code. > > Terse code is nice but not at the expense of making it write-only. > > Well, there's only two places to look with operator overloads, but > yes you're right, using operator overloads for single operation is not > a good example of how they make code easier to read. The more > complicated example from the introduction to the RFC > https://wiki.php.net/rfc/user_defined_operator_overloads#introduction > shows how they make complex maths easier to read. I think the example in the RFC is interesting, but not ideal to advertise the RFC. The example is with native scalar types and build-in operator implementations. (I don't know how GMP works internally, but for an average user of PHP it does not make sense to call this "overloaded") In fact, if we add overloaded operators as in the RFC, the example becomes less easy to read, because now we can no longer be sure by just looking at the snippet: - Are those variables scalar values, or objects? - Are the operators using the built-in implementation or some custom overloaded implementation? (depends on the operand types) - Are the return values or intermediate values scalars or objects? We need really good variable names, and/or other contextual information, to answer those questions. This said, I am sure we _can_ find good examples. In this thread, people already mentioned Matrix/Vector, Money/Currency and Time/Duration. Others would be various numbers with physical measuring units. > > The exact position of where that trade-off is 'worth it' is going to > be different for different people. But one of the areas where PHP is > 'losing ground' to Python is how Python is better at processing data > with maths, and part of that is how even trivial things, such as > complex numbers, are quite difficult to implement and/or use in > userland PHP. Could be interesting to look for examples in Python. I was not lucky so far, but there must be something.. > > Stanislav Malyshev wrote: > > And again, what's the intuitive > > difference between operators +=+@-+ and ++--=!* ? > > That's not part of the RFC. > > There's enough trade-offs to discuss already; people don't need to > imagine more that aren't part of what is being proposed. > > > I have encountered > > toolkits where the authors think it's cute to define "+" to mean > > something that has nothing to do with mathematical addition > > Rather than leaving everyone to make the same mistakes again, this RFC > might be improved by having a list of stuff that it really shouldn't > be used for. At least then anyone who violates those guidelines does > so at their own risk. Having guidelines would also help junior devs > point out to more senior devs that "you're trying to be clever and the > whole team is going to regret this". > > I started a 'Guidelines for operator overloads' here > (https://github.com/Danack/GuidelinesForOperatorOverloads/blob/main/guidelines.md) > - if anyone has horrorible examples they'd like to add, PR's are > welcome. I think it is a good start. I would avoid appealing to "common sense" or "logical sense" though, this can mean different things to different people, and is also somewhat tautological, like "do good things, avoid bad things". More meaningful terms can be "familiar", "expectations", "predictable", "non-ambiguous". (I see this language is coming from the C++ document, but either way I don't like it) Possible alternative language snippets: For designing operators: - Replicate familiar notations from the subject domain, e.g. maths, physics, commerce. (this has some overlap with the first point) - Return the type and value that people expect based on their expectations and mental models. - Use identifiers (class names, method names, variable names) from the same subject domain language that inspires the operators. - Avoid ambiguity: If different people will have different expectations for return type and value, introduce well-named methods instead of overloaded operators. - Completeness trade-off: Understand the full range of operators, and type combinations for the same operator, that is common in the subject domain. Then decide which of those should be supported with operator overloads, and which should be supported with methods instead. - Take inspiration from code examples outside of PHP. For using operators: Use descriptive variable names, method names, other identifiers, and other hints (@var comments etc), so that the type and role of each variable and value can be easily understood. E.g. "$duration = $tStart - $tEnd;". "If you provide constructive operators, they should not change their operands." I think we should use the term "immutable": Operators should be immutable to the operands. If operands are objects, the operator should return a new instance instead of modifying the existing instance. For +=, we should still recommend immutable behavior. It is just so much better :) $price = new PriceInDollar(5); assert($price->amount() === 5); $old_price = $price; assert($price === $old_price); // same object. $price *= 2; // Shortcut for "$price = $price * 2;", creating a new instance. assert($price->amount() === 10); assert($old_price->amount() === 5); assert($price !== $old_price); // different object. ---------- Btw it would be really interesting to find such a list of recommendations for Python. The reference you added, https://isocpp.org/wiki/faq/operator-overloading#op-ov-rules, is for C++, which is less comparable to PHP than Python is. -- Andreas > > cheers > Dan > Ack > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php >