Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:122913 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 71BEF1A009C for ; Wed, 3 Apr 2024 18:09:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1712167793; bh=NarDEt0cSGoqEqM96rinRKS+7N1HbYsUjRQt0UiyswQ=; h=References:In-Reply-To:From:Date:Subject:To:From; b=bmSieBYpgLI6RX8D/od2a0/Aqzblll4VqEgOtDfBtoeybtFQQ0MThurcjKlAZjVwn Ao/EiVX1+y7RUJ4bpvg6I/LsKlsNJij4PqcV6UO9UBuor2958iQdFb/DMlbrhpLveA IWfTP9+PCLlEmErTg0znT1OsqDuqRWoXlHTsNkeYoa8w/LqYV7mtnuO7YfUp2WA7p+ F2YmvQkICLaLAfKklxB70KeeQc/Uf+qUZZHel9Fqh9GWXZrzhlScsI/mwh/hrYssiJ R+DRYl0P5MGKGP7zoeLaZxBC21wFYw/W6RFpxxnyupx8dJ+ZNH1YmGM5cXN0d6h1jG 2qmvAjM84MDRA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id D7F1F180508 for ; Wed, 3 Apr 2024 18:09:51 +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.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,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: Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) (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 ; Wed, 3 Apr 2024 18:09:49 +0000 (UTC) Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-69929db09c9so488546d6.0 for ; Wed, 03 Apr 2024 11:09:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712167760; x=1712772560; darn=lists.php.net; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=ef+1l0VRQ+Bo7Hr7H+5uKJ1Jy+099fR7jyneNH8miw0=; b=UDyQZoqFojNhh02oZ0I4p5u5wBLAn6MUrX1BxqPnO/v0ll9vfncT3MwDQwnp19C0eZ cuzUG5jVAi2OngaawRHez738KL2U1/Hu+J4W/WyqOn9wCQ+1MVMF+Lvq+mrRQQXOy1/F ftCPim98P31SvbVLpLSxssZFv1qwYt1AROfB7ZECtVo7liI0JEdaYrOXW+4H+asbfF55 GeudPcS7V8aod9GNCx8J8Q+2ptL4jbVe6u5AUJnzWE7nlEoi0IWn2TcAtkAwMx6J+KwG aBDlPk4e/r91+eqpyHMqqLi8M+X2xZcIg630kmAyqTX4MsFWXF7ZNbGGMEwPRnqp4+P8 5sRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712167760; x=1712772560; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ef+1l0VRQ+Bo7Hr7H+5uKJ1Jy+099fR7jyneNH8miw0=; b=rAAOVJCs/LPiovnq3gA7cof5yUEVJofEbBGSxDViHfKD7TlSjGVYbd7z3cz4BRCk/O +6Hv2xF3vBNU5Z3i5YcNO3wibVnwNdvqy/QPy2gioAAiY8LgAOqZyQYzZQG8DyzM6nSQ sJei2ZLcBN16+5w0eAjvJ5HL7wxPfBoZPwFQTgjDoMEsKBoh9wGWTePcPdaVudaMy0tp Da3Ad9rO7bdhlgCmNPfnywMKJIKDqUcktyrhMuTkhbtoRJLD0rC1A2GCzhafaTEqG50M MqzLqM+JHnsQnlekBxQMtl9YIPMp/1aP7YCozRwJIyGdYTNcLiz5V3o682hH7LxpHgCe UFMw== X-Gm-Message-State: AOJu0YxMIKNCrzvq56hy+Ez9tnpqDxlbQqeHAoBa/HqlVePpmGTr4GEZ i30DKYIbyOQv5S20oAigqbd/crlK2ujEPS2XKNBXTx4XI6A7Yt2FArZl9m1RsvenElRX+Nwz64f Wk91JWZhxo+ypTC2dCKuCZxHovRxPkv+/o/z2iSSh X-Google-Smtp-Source: AGHT+IEEYScIxQhLl7tEsntDq91laQ5nrGPjodtYB2GqKSTMIWX4y7KA0qcidKwCe3Nfh0qhcOnhAR8gxBAbE4Bw0Oc= X-Received: by 2002:a05:6214:21c3:b0:699:2cad:151c with SMTP id d3-20020a05621421c300b006992cad151cmr113329qvh.48.1712167759949; Wed, 03 Apr 2024 11:09:19 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net MIME-Version: 1.0 References: <1a4a44c5-d4f5-40ca-b3dc-13d64c2b4425@app.fastmail.com> In-Reply-To: Date: Wed, 3 Apr 2024 20:09:08 +0200 Message-ID: Subject: Re: [PHP-DEV] [RFC][Concept] Data classes (a.k.a. structs) To: php internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: tovilo.ilija@gmail.com (Ilija Tovilo) Hi Larry On Wed, Apr 3, 2024 at 12:03=E2=80=AFAM Larry Garfield wrote: > > On Tue, Apr 2, 2024, at 6:04 PM, Ilija Tovilo wrote: > > > I think you misunderstood. The intention is to mark both call-site and > > declaration. Call-site is marked with ->method!(), while declaration > > is marked with "public mutating function". Call-site is required to > > avoid the engine complexity, as previously mentioned. But > > declaration-site is required so that the user (and IDEs) even know > > that you need to use the special syntax at the call-site. > > Ah, OK. That's... unfortunate, but I defer to you on the implementation = complexity. As I've argued, I believe the different syntax is a positive. This way, data classes are known to stay unmodified unless: 1. You're explicitly modifying it yourself. 2. You're calling a mutating method, with its associated syntax. 3. You're creating a reference from the value, either explicitly or by passing it to a by-reference parameter. By-reference argument passing is the only way that mutations of data classes can be hidden (given that they look exactly like normal by-value arguments), and its arguably a flaw of by-reference passing itself. In all other cases, you can expect your value _not_ to unexpectedly change. For this reason, I consider it as an alternative approach to readonly classes. > > Disallowing ordinary by-ref objects is not trivial without additional > > performance penalties, and I don't see a good reason for it. Can you > > provide an example on when that would be problematic? > > There's two aspects to it, that I see. > > data class A { > public function __construct(public string $name) {} > } > > data class B { > public function __construct( > public A $a, > public PDO $conn, > ) {} > } > > $b =3D new B(new A(), $pdoConnection); > > function stuff(B $b2) { > $b2->a->name =3D 'Larry'; > // This triggers a CoW on $b2, separating it from $b, and also creating= a new instance of A. What about $conn? > // Does it get cloned? That would be bad. Does it not get cloned? Th= at seems weird that it's still the same on > // a data object. > > $b2->conn->beginTransaction(); > // This I would say is technically a modification, since the state of t= he connection is changing. But then > // should this trigger $b2 cloning from $b1? Neither answer is obvious= to me. > } IMO, the answer is relatively straight-forward: PDO is a reference type. For all intents and purposes, when you're passing B to stuff(), B is copied. Since B::$conn is a "reference" (read pointer), copying B doesn't copy the connection, only the reference to it. B::$a, however, is a value type, so copying B also copies A. The fact that this isn't _exactly_ what happens under the hood due to CoW is an implementation detail, it doesn't need to change how you think about it. From the users standpoint, $b and $b2 can already separate values once stuff() is called. This is really no different from arrays: ```php $b =3D ['a' =3D> ['name' =3D> 'Larry'], 'conn' =3D> $pdoConnection]; $b2 =3D $b; // $b is detached from $b2, $b['conn'] remains a shared object. ``` > The other aspect is, eg, serialization. People will come to expect (reas= onably) that a data class will have certain properties (in the abstract sen= se, not lexical sense). For instance, most classes are serializable, but a= few are not. (Eg, if they have a reference to PDO or a file handle or som= ething unserializable.) Data classes seem like they should be safe to seri= alize always, as they're "just data". If data classes are limited to primi= tives and data classes internally, that means we can effectively guarantee = that they will be serializable, always. If one of the properties could be = a non-serializable object, that assumption breaks. I'm not sure that's a convincing argument to fully disallow reference types, especially since it would prevent you from storing DateTimeImmutables and other immutable values in data classes and thus break many valid use-cases. That would arguably be very limiting. > There's probably other similar examples besides serialization where "thin= k of this as data" and "think of this as logic" is how you'd want to think,= which leads to different assumptions, which we shouldn't stealthily break. I think your assumption here is that non-data classes cannot contain data. This doesn't hold, and especially will not until data classes become more common. Readonly classes can be considered strict versions of data classes in terms of mutability, minus some of the other semantic changes (e.g. identity). Ilija