Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125578 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 411621A00BD for ; Tue, 17 Sep 2024 08:17:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1726561177; bh=536JbRCmjqdXdlouiOlTxoPCo4PW9zswyFvXaaS5rOY=; h=Date:Subject:To:References:From:In-Reply-To:From; b=K63qfvFWHHS20dHUohLnaFmRGdo7uMO+Wi6zP37G8dh9N0vp4FBcEtEHcvZlnL//2 jB+BEqwj2cuQgDzDFk1U1KZsssVDGPnGGWVMlC2YkI8O8qWnQ66uBWSaMjDwxJF9xO tYJDlGdKarGyqlfecexF7/x311fGVkOGAOHrdFH8HpxQ+4Tpsq5UuZkYV2jes3Afwm olo7K45yztd3ZGMYq4yw9VpMktaJVHi2g+BZfiT9A77CA9TztEzEndktGNAv9sx7tS NyFi891DZDafE7C/YM5qflf+bumL2RbK4MqRp4IEb0Pn+Jn2gncA6BAR8ickhGR2GZ /B5BkUumNoHBA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id DA82C180053 for ; Tue, 17 Sep 2024 08:19:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fout2-smtp.messagingengine.com (fout2-smtp.messagingengine.com [103.168.172.145]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 17 Sep 2024 08:19:36 +0000 (UTC) Received: from phl-compute-08.internal (phl-compute-08.phl.internal [10.202.2.48]) by mailfout.phl.internal (Postfix) with ESMTP id CEFCF138044C for ; Tue, 17 Sep 2024 04:17:30 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-08.internal (MEProxy); Tue, 17 Sep 2024 04:17:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc :content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm1; t=1726561050; x=1726647450; bh=jEhs8OhTQTwa7f5pfewxb31t9rDHEYDvL5eseRFJn10=; b= T94/SzhXsKUUT9rrRWPOXlJN6v5/Wg/llpc7ugEZlst+v5Pm9/1WbFHHGZtv/0Gv yZ+5puo0h7vkhFbgJmx2J1Rs3+VAkpkpDfEo1Unr6zSCEM92NBXnLKHZZt2+h5rs l9uowWMxqOGHjuawVrYHARjVwJPkNfbyJUFpVabhrKMRO1WKillsMUubwnH30Npx sPGuWxCfiwAgYTJAMc6QmK/QGmJ3R+6Rhn74f+jaZhgBeX6Bnzgr1zgMc/BAA+C9 R797DDle4FuF4dOVWCMN/LIujtNlsA1m2UlJAWRl+KhYlXuE9+axotGImXFYc1Ni 7c/NU+ChNlZCeSjjxS4JhA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1726561050; x= 1726647450; bh=jEhs8OhTQTwa7f5pfewxb31t9rDHEYDvL5eseRFJn10=; b=j RkQ46cgwvEZEP7pVunf+mRYQ9yg+lL8uUCzr5FyN7eaSkePh5EfBFbjsP7B5oY4d L6dQOYWV1ST62dHeCFvShpX+Db+WWsiPtlZGOuu4e8W66e23Zy7WRkGe1dMzpd6n gwMruk8qSAL3xb0Wdun5aZppNdDxtRck8KkzrDHjmArFy6LKIgMtocdHyBMd0xgj PGrer6/U6OaGot5wSQtDBdddMd/xjNi5H7YgPP9L7FErIb/PexCf+p4ZEVUsUlyd IjmHiLPsXoV6zsorLCTwVyt7RdkUpWyXm3WGmOQVO8oiwc93uKXpN4+AgG5rQeJZ UQtS71NMPyCKSwvz6G3Og== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrudekjedgtdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucenucfjughrpefkffggfg fuvfhfhfgjtgfgsehtjeertddtvdejnecuhfhrohhmpedftfhofigrnhcuvfhomhhmihhn shculgfkoffuohfrngdfuceoihhmshhophdrphhhphesrhifvggtrdgtohdruhhkqeenuc ggtffrrghtthgvrhhnpeejkefghfeugffgtdeuheeggfdugefhudekjefhteegieejleeh veelhfefvdfhudenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfh hrohhmpehimhhsohhprdhphhhpsehrfigvtgdrtghordhukhdpnhgspghrtghpthhtohep uddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepihhnthgvrhhnrghlsheslhhish htshdrphhhphdrnhgvth X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Tue, 17 Sep 2024 04:17:30 -0400 (EDT) Message-ID: <2551c06a-ec1f-4870-a590-aeb5752fc944@rwec.co.uk> Date: Tue, 17 Sep 2024 09:17:27 +0100 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again) To: internals@lists.php.net References: Content-Language: en-GB In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") On 14/09/2024 22:48, Jordan LeDoux wrote: > > 1. Should the next version of this RFC use the `operator` keyword, or > should that approach be abandoned for something more familiar? Why do > you feel that way? > > 2. Should the capability to overload comparison operators be provided > in the same RFC, or would it be better to separate that into its own > RFC? Why do you feel that way? > > 3. Do you feel there were any glaring design weaknesses in the > previous RFC that should be addressed before it is re-proposed? > I think there are two fundamental decisions which inform a lot of the rest of the design: 1. Are we over-riding *operators* or *operations*? That is, is the user saying "this is what happens when you put a + symbol between two Foo objects", or "this is what happens when you add two Foo objects together"? 2. How do we despatch a binary operator to one of its operands? That is, given $a + $b, where $a and $b are objects of different classes, how do we choose which implementation to run? One extreme is the "operators are just methods with funny names" approach: $a + $b is just sugar for $a->operator+($b); $a can do whatever it likes, but if it doesn't implement the operator, an error happens. There's no need to indicate reversed operands, no implementation on $b is never called. This is simple to implement, and great for users who want to build concise DSLs; but that degree of freedom is often unpopular. Towards the other end on question 1, you have defined *operations* with expected semantics, return types, relationships between operators, etc. The previous RFC actually went down this route for comparisons, defining a single "operator <=>" that actually overloaded all the comparison operators at once. I think if we're going down that route, a name like "__compare" or "interface Comparable { function compare(...) }" makes more sense - you're not actually saying "this is what happens if you type a spaceship", you're saying "here's how to compare two objects". On question 2, there are a few different possibilities. Despatch based on type: a) Binary operators are defined globally on specific type pairs, and the "best" overload chosen from all those currently loaded b) Slightly more restricted: they are defined as static methods, and the best overload chosen from the union of those defined on classes A and B (this is how C# works) c) Operator overloads are only possible between a class and a scalar/non-object, or a class and one of its ancestors; the implementation on the most specific class is used (e.g. if B extends A, B's implementation will be used) All of these can be written in a way that guarantees consistency ($a + $b will always call the same as $b + $a). Both (a) and (b) would be quite alien to PHP, which doesn't otherwise have multiple despatch, but (c) is quite tempting as a conservative approach. Despatch by trial and error: d) Each class can only define one overload for an operator, but can specify which types it accepts; if the definition on type A does not accept instances of B, the definition on type B is attempted e) Operator overloads all accept "mixed", but the definition on A can dynamically return a value which causes the definition on B to be attempted (this is how Python works) f) Instead of returning a special value, allow throwing a special exception; can be combined with option (d) by having the system catch any TypeError g) As in the previous proposal, the implementation on class B is only called if no implementation on class A exists Each of these can be combined with a special case to always prefer sub-classes; e.g if B extends A, then (new A) + (new B) should call the implementation on B first, even though it's on the RHS. (I spotted this in the Python docs, and it seems very sensible.) Finally, a very quick note on the OperandPosition enum: I think just a "bool $isReversed" would be fine - the "natural" expansion of "$a+$b" is "$a->operator+($b, false)"; the "fallback" is "$b->operator+($a, true)" Regards, -- Rowan Tommins [IMSoP]