Newsgroups: php.internals
Path: news.php.net
Xref: news.php.net php.internals:122895
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 402A81A009C
	for <internals@lists.php.net>; Tue,  2 Apr 2024 20:10:43 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail;
	t=1712088671; bh=TZ1kWbMsvVfrblSmlBUwZifz/i79RHXc2/loubDM/PI=;
	h=Date:Subject:To:References:From:In-Reply-To:From;
	b=hpc2cCqW/C4Fl9AxcB68SDfr5SjzIMcAGnkuAtMGv6YXGmkF1mW6+4/hAbAc8Gwgo
	 Qrp6/3EmzFdEqVQG56LP0p0zaxr3Gt4T87O7cb/EC5wceERUAvV8hx1x90rwq4nnwR
	 jFlqNlnPvHbEM4FTQs9obFvS/Jn5bO+ESIFqkm9LDHsoR6kMDLdUr51bXkd5Y/bD/9
	 ehGA8VMJ3qk6yWqGKaFc73qJKcaZveAilGtdeK0KUoiUrBfYyNmGGE8VQCwNm5cr+C
	 2ydPOlDm2jD1bdvoOzrwgLRWKKHvXO9MocyD8kVFrONnQLJDDx45VFzRBpmg7TCKKt
	 RGcA+JGeUURNA==
Received: from php-smtp4.php.net (localhost [127.0.0.1])
	by php-smtp4.php.net (Postfix) with ESMTP id EEE55180004
	for <internals@lists.php.net>; Tue,  2 Apr 2024 20:11:09 +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,HTML_MESSAGE,
	RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE
	autolearn=no autolearn_force=no version=4.0.0
X-Spam-Virus: No
X-Envelope-From: <imsop.php@rwec.co.uk>
Received: from fout7-smtp.messagingengine.com (fout7-smtp.messagingengine.com [103.168.172.150])
	(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 <internals@lists.php.net>; Tue,  2 Apr 2024 20:11:09 +0000 (UTC)
Received: from compute7.internal (compute7.nyi.internal [10.202.2.48])
	by mailfout.nyi.internal (Postfix) with ESMTP id B0C1713801ED
	for <internals@lists.php.net>; Tue,  2 Apr 2024 16:10:40 -0400 (EDT)
Received: from mailfrontend1 ([10.202.2.162])
  by compute7.internal (MEProxy); Tue, 02 Apr 2024 16:10:40 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc
	: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=fm2; t=1712088640; x=1712175040; bh=KyowYWrvPA
	Yz95lOtchuoSBeBnipBCOVsXQI/f7AKMY=; b=Ue6u+HUxUNGntCTD8aZcW/R3ba
	JkqtbzKpaO6IRBNYoa7Z7n/0T0hrNOVDkkJR/A+rQA59Xj3GjLOay6JelPtKQP8q
	k0339r6snpPhbYBfMD8yhjN/QVJt/GQmCHmVUuIijN4MRr2HAwyKCOV54i6HHOAh
	eBHKWdAk77dUDnsWBHl0W/QwWlc5v49Yg0+aLARLQOyQN6oeMpVkEgOy/xcneevg
	pBygkgxUfx/fYw7UrClwPiC1U3PItv17rizHwNMcF6mHXeJbDsZfMgOyTjrgUjqa
	7w7+9fN5GjCzYobVEwegjdhRq19Shce1JA/efmP7wAyxWrLwnVwlctZzBCEA==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
	messagingengine.com; h=cc: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=
	fm2; t=1712088640; x=1712175040; bh=KyowYWrvPAYz95lOtchuoSBeBnip
	BCOVsXQI/f7AKMY=; b=DvynqSA/iDTz2UQIDpiLdcW1awiz7vFfA1VIRha6YXq6
	FC+d7t9RKBPmws4ZYB3noeGhg7Uf2QJJfWh/fCYK5mVzYvxUky5ce/fYVSkZwjgo
	i1YMBNdD+WlmUDJ3yzZIpGbw7WwpG845inCpq7GK6RCVfnPkoqpCgQmmB1+DQk00
	7IYE/GBu1zz0JfZqvDhBsma7PWDKj0weK4AACDIiJSvJcA15/LlAN6iGB0HZxD5O
	UmyLZuyV0rxYwRvFeu67xiuRlK+HvRVdWHKe+C8hg12t9IUfWVnJBsA1MTHbl6r6
	ZoUubdVGY3STifCA3a/fkpy4fHGpjvxUL3z3KGtNDQ==
X-ME-Sender: <xms:QGYMZqDTEH-715Eo8XSycehCxJXxkYNFAnPhHH9YKFzVmEJfkRecmg>
    <xme:QGYMZkj3wVdXRT8PjSVZr1TwBwfxi96Ckd5gxMJrDfUEpy1UQejye5Y1g4WC-sLs8
    Hn29awhqzP_GOhGFnQ>
X-ME-Received: <xmr:QGYMZtlRgf9PaduDm3Yv1XWQ27Bfzxyv4maiFVsufrBGnh22UJvwh5pKE2MKhOU4_OC98OwCWIebogk5YPopDyKJ279EFzfQhz2OgCHBiA5xKCko5q1Oxckj>
X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrudefvddgudegiecutefuodetggdotefrod
    ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh
    necuuegrihhlohhuthemuceftddtnecunecujfgurheptgfkffggfgfuvfhfhfgjsegrtd
    erredtvdejnecuhfhrohhmpedftfhofigrnhcuvfhomhhmihhnshculgfkoffuohfrngdf
    uceoihhmshhophdrphhhphesrhifvggtrdgtohdruhhkqeenucggtffrrghtthgvrhhnpe
    ehteelieeigfeuudeiueeiffdvveehudeufeekjeeugffffedtiedtgeettdelteenucev
    lhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehimhhsohhprd
    hphhhpsehrfigvtgdrtghordhukh
X-ME-Proxy: <xmx:QGYMZow7iOBX3VTgTWExECqz2zZKGGZ7mzff_cBI0XLrepMkH9yEKA>
    <xmx:QGYMZvTm1IjEUyx1X_N2e5vsN0Q_YMbDWhN-va040zposlkhQV5Hpg>
    <xmx:QGYMZjYq_IvmHaSd6_M7IOh2EiKC0H5YVuEoKZ66No5Nbmq5lJIUaA>
    <xmx:QGYMZoQOsFjyOYWOhKclHd8FoUVCW-ynuNSTyRnzfqTJ4jhzzTwTpQ>
    <xmx:QGYMZqde8ohg9SV5hXEHy0snc0PiLcUAXGO0hz-1PDdfxBScrw6xA0HF>
Feedback-ID: id5114917:Fastmail
Received: by mail.messagingengine.com (Postfix) with ESMTPA for
 <internals@lists.php.net>; Tue, 2 Apr 2024 16:10:39 -0400 (EDT)
Content-Type: multipart/alternative;
 boundary="------------CA6P0Eq3Ss680KHgjtM0011A"
Message-ID: <d02a2d11-cbe3-4fef-9181-2fbac8988f34@rwec.co.uk>
Date: Tue, 2 Apr 2024 21:10:38 +0100
Precedence: bulk
list-help: <mailto:internals+help@lists.php.net
list-unsubscribe: <mailto:internals+unsubscribe@lists.php.net>
list-post: <mailto:internals@lists.php.net>
List-Id: internals.lists.php.net
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
Subject: Re: [PHP-DEV] [RFC][Concept] Data classes (a.k.a. structs)
To: internals@lists.php.net
References: <CAPyj-LA7kJLdz3Pzbxr6x-7v2YV8n06pwxs6QoVe3CGgx-_GGA@mail.gmail.com>
Content-Language: en-GB
In-Reply-To: <CAPyj-LA7kJLdz3Pzbxr6x-7v2YV8n06pwxs6QoVe3CGgx-_GGA@mail.gmail.com>
From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]")

This is a multi-part message in MIME format.
--------------CA6P0Eq3Ss680KHgjtM0011A
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

On 02/04/2024 01:17, Ilija Tovilo wrote:
> I'd like to introduce an idea I've played around with for a couple of
> weeks: Data classes, sometimes called structs in other languages (e.g.
> Swift and C#).


Hi Ilija,

I'm really interested to see how this develops. A couple of thoughts 
that immediately occurred to me...


I'm not sure if you've considered it already, but mutating methods 
should probably be constrained to be void (or maybe "mutating" could 
occupy the return type slot). Otherwise, someone is bound to write this:

$start = new Location('Here');
$end = $start->move!('There');

Expecting it to mean this:

$start = new Location('Here');
$end = $start;
$end->move!('There');

When it would actually mean this:

$start = new Location('Here');
$start->move!('There');
$end = $start;


I seem to remember when this was discussed before, the argument being 
made that separating value objects completely means you have to spend 
time deciding how they interact with every feature of the language.

Does the copy-on-write optimisation actually require the entire class to 
be special, or could it be triggered by a mutating method on any object? 
To allow direct modification of properties as well, we could move the 
call-site marker slightly to a ->! operator:

$foo->!mutate();
$foo->!bar = 42;

The first would be the same as your current version: it would perform a 
CoW reference separation / clone, then call the method, which would 
require a "mutating" marker. The second would essentially be an 
optimised version of $foo = clone $foo with [ 'bar' => 42 ]

During the method call or write operation, readonly properties would 
allow an additional write, as is the case in __clone and the "clone 
with" proposal. So a "pure" data object would simply be declared with 
the existing "readonly class" syntax.

The main drawback I can see (outside of the implementation, which I 
can't comment on) is that we couldn't overload the === operator to use 
value semantics. In exchange, a lot of decisions would simply be made 
for us: they would just be objects, with all the same behaviour around 
inheritance, serialization, and so on.


Regards,

-- 
Rowan Tommins
[IMSoP]

--------------CA6P0Eq3Ss680KHgjtM0011A
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">On 02/04/2024 01:17, Ilija Tovilo
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAPyj-LA7kJLdz3Pzbxr6x-7v2YV8n06pwxs6QoVe3CGgx-_GGA@mail.gmail.com">
      <pre>I'd like to introduce an idea I've played around with for a couple of
weeks: Data classes, sometimes called structs in other languages (e.g.
Swift and C#).</pre>
    </blockquote>
    <p><br>
    </p>
    <p>Hi Ilija,</p>
    <p>I'm really interested to see how this develops. A couple of
      thoughts that immediately occurred to me...<br>
    </p>
    <p><br>
    </p>
    <p>I'm not sure if you've considered it already, but mutating
      methods should probably be constrained to be void (or maybe
      "mutating" could occupy the return type slot). Otherwise, someone
      is bound to write this:</p>
    <p>$start = new Location('Here');<br>
      $end = $start-&gt;move!('There');</p>
    <p>Expecting it to mean this:<br>
    </p>
    <p>$start = new Location('Here');<br>
      $end = $start;<br>
      $end-&gt;move!('There');</p>
    <p>When it would actually mean this:</p>
    <p>$start = new Location('Here');<br>
      $start-&gt;move!('There');<br>
      $end = $start;</p>
    <p><br>
    </p>
    <p>I seem to remember when this was discussed before, the argument
      being made that separating value objects completely means you have
      to spend time deciding how they interact with every feature of the
      language.<br>
    </p>
    <p>Does the copy-on-write optimisation actually require the entire
      class to be special, or could it be triggered by a mutating method
      on any object? To allow direct modification of properties as well,
      we could move the call-site marker slightly to a -&gt;! operator:<br>
    </p>
    <p>$foo-&gt;!mutate();<br>
      $foo-&gt;!bar = 42;</p>
    <p>The first would be the same as your current version: it would
      perform a CoW reference separation / clone, then call the method,
      which would require a "mutating" marker. The second would
      essentially be an optimised version of $foo = clone $foo with [
      'bar' =&gt; 42 ]<br>
    </p>
    <p>During the method call or write operation, readonly properties
      would allow an additional write, as is the case in __clone and the
      "clone with" proposal. So a "pure" data object would simply be
      declared with the existing "readonly class" syntax.<br>
    </p>
    <p>The main drawback I can see (outside of the implementation, which
      I can't comment on) is that we couldn't overload the === operator
      to use value semantics. In exchange, a lot of decisions would
      simply be made for us: they would just be objects, with all the
      same behaviour around inheritance, serialization, and so on.<br>
    </p>
    <p><br>
    </p>
    <p>Regards,<br>
    </p>
    <pre class="moz-signature" cols="72">-- 
Rowan Tommins
[IMSoP]</pre>
  </body>
</html>

--------------CA6P0Eq3Ss680KHgjtM0011A--