Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128026 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 lists.php.net (Postfix) with ESMTPS id 289211A00BC for ; Mon, 14 Jul 2025 09:16:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1752484510; bh=EFFz296A9g0DySJUQrd+uSOidiTG8mB0nDtrsdvVf2A=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=KmKBkV/xr0kzUuLEq0CwH1qKZYBuhufA8+uSI4gFS9/kJLNv2cONZibqUCDgKMGvy qhO8UFf8rWKJWxwY20eXNe2eegAR78+IRqCvB+I6XHi9WNrEBADc8iYI4r+gVhBztI 85gMg6Ay3wAn7E30d2nKGw+KxzVgZImhl3CJpthKd2WA7yGamJezjUre6jY4426JA9 l73tazU+4crv/F3Hq8FR/E2MdqFNoo3AIBR0nNnU0xqUf+aHqy47vjTdgCc3/gKo7F iAF9+Gg2V7+TErmVIaDf9+FeOE4d1ykwpZR+uKGdFaL+BWf2XCtEIb8UHPMdivrGMT 9VUtrkMkiNRig== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id E9096180074 for ; Mon, 14 Jul 2025 09:15:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.2 required=5.0 tests=BAYES_40,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from mail-lf1-f54.google.com (mail-lf1-f54.google.com [209.85.167.54]) (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 ; Mon, 14 Jul 2025 09:15:09 +0000 (UTC) Received: by mail-lf1-f54.google.com with SMTP id 2adb3069b0e04-5550dca1241so3702842e87.0 for ; Mon, 14 Jul 2025 02:16:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752484616; x=1753089416; darn=lists.php.net; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=H0+ac0CQiBGeKumIptHPVEn4T1FKR+fihdoLIStkTi0=; b=U4ctdaWiy/7wxGhAX3CuFZXRaUd2DgKu6HmH5UhKWtK9wqYXEUlvb10lxEHbtsqkxm MGCQfTF4FSyJQ2GyIFXC5J3YmAx+xM8h+LrYQwqMTSVOo3By0IFkK/+pw45CWMlM9AnF W6FxPU1LcQnJY0KCnwSh0UB6FEA7GEURIfgQccqSv9aW6nUz++1ijmfm2rDzS973EDEj resazic5kMDDX9p8+Pro7Dq3IIC7Pb98R9RQrTmjOVVQdxKWytsO3lzdSZcUt/2ZHkO4 5mOLoKlZLQToTDefVolxlIAubYPE/Utgz19VIYZ0f7rNqCSjvpjbzho9T+bIDXapghPr SBzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752484616; x=1753089416; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=H0+ac0CQiBGeKumIptHPVEn4T1FKR+fihdoLIStkTi0=; b=nh6RnzSOa3i9jfHJsbCAIjtzcdoisvCe7rN1fr0b7QYCN10/jw1gmpT4oBF+xi28nT ganpS1m2AJWjKuxmcuBuAMw5BZ+qkO8PnIiRA2p47Q+Bb2DuUc9XH7KlI7+uhb/TCJ/I m/v8iGnRd7sg5juuGQ1PhCOrQxWcoKZz6diUtMazu7jhrwG/RptbOc3/8BH5KEYSJ8CG XIx+Em+UgsfRL5y9CCzNLT42fY7jhNB6/YzXm9i1jJhCgP1r7nYafFoTSLJ43LPj4usf MlHLVsDKBE2+5sY59lKZQk/VxZ2MlMAZWzzQiso3xJjeonrKL9FiGzD8YcPZnR2PlwTm u7FQ== X-Gm-Message-State: AOJu0YwJtfBQCkuotBpjfkTRB1udGsBpztBVrut2gPTrs26OWsl8vnJB L/gU0GTa3bfLy9IMGEU0bffATKt9dKvZUcoZUXdTAHeeGcrTJWRgUzXk X-Gm-Gg: ASbGncs1gUAk522mQTPGPMooPxLuzvj++eNMJcxWOG61SN4KF1hh57+dJhS5qcnqyMZ GtVEwPSdkLFZqdF6r1QAYBjLIIyhOu+Nmmt1RG/BBipk8tTlRXClbkt+b0WAs2MAaOzw9yPnGS+ 9T8MuPEmwqV4xcfuk6RkSvuSISASKhZLCwtgqk2vpK99iecjYIh7yMHYl7cy1XciQw2mJNoYxOZ /LhcYUAKgYC6XcioV9cAo2/36EI9Ms8+erIWCwn6oIPVSlu7JfGnRehsokjTZCLZk8EqeCOM2Pj hjmVO5fRCO6a1RFC+eo/12m7lpHCbjNHEghwBqgYpAtygwUzGGniBpHVsqC1nHLUQq2cJzGA/rc EjiDfnXsnlZ7L7EzvmYXzv6HOQrbwyihKWD4TUg== X-Google-Smtp-Source: AGHT+IE0LZMXrcp7+46stLNaHwPRo1hrP2dmxgtRO1uUddmrIW6sd7psSzblZwdqZcebPbsbN/oOCA== X-Received: by 2002:a05:6512:2393:b0:553:3916:4e1c with SMTP id 2adb3069b0e04-55a044c9576mr3329792e87.2.1752484615804; Mon, 14 Jul 2025 02:16:55 -0700 (PDT) Received: from smtpclient.apple ([46.73.17.85]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5593c9d0914sm1893060e87.112.2025.07.14.02.16.54 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Jul 2025 02:16:55 -0700 (PDT) X-Google-Original-From: Dmitry Derepko Message-ID: <0D6532F3-6E95-48B9-B394-E9CC1EC00B56@gmail.com> Content-Type: multipart/alternative; boundary="Apple-Mail=_01F2A5F2-E317-44BA-825D-E0445CB333F9" Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.600.51.1.1\)) Subject: Re: [PHP-DEV] RFC: Records Date: Mon, 14 Jul 2025 12:16:44 +0300 In-Reply-To: Cc: internals@lists.php.net To: Rob Landers References: X-Mailer: Apple Mail (2.3826.600.51.1.1) From: xepozzd@gmail.com (Dmitry Derepko) --Apple-Mail=_01F2A5F2-E317-44BA-825D-E0445CB333F9 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hi, Rob! I'm just wondering, why the implementation differs from a regular class?=20= Record makes a "class" immutable and unique, using field value = comparison instead of object refs. It has a custom `with` method which = is similar to the new `clone` operator accepted recently. I'd suggest = not introducing a new keyword "record" and new syntax to create records, = but use regular `class` and `new Class`. Class should have a modifier = "data" like readonly, so it should be: data class Record { public function __construct(public $a){} // $a is mutable, because = why not? } Data class will compare with others using field value comparison. = Moreover, if you want to make it readonly, use the existing keyword to = achieve this: readonly data class Record { public function __construct(public $a){} // $a is immutable, because = of "readonly" class modifier } 1. So record Record {} becomes readonly data class Record {} 2. We introduce data classes, which are similar to records and are = mutable by default 3. No new constructions to create the new type of classes, no = adjustments for autoloading and other things internally 4. Eliminate with method, replace `with` method with the new `clone` 5. Inline constructor isn=E2=80=99t necessary and could be proposed = separately. I=E2=80=99ve thought recently about this feature WDYT? (sorry for the duplicate in private mailbox) ---------- Best regards, Dmitrii Derepko. @xepozz > On Nov 17, 2024, at 2:14=E2=80=AFAM, Rob Landers = wrote: >=20 > Hello internals, >=20 > I'm ready as I'm going to be to introduce to you: "Records" = https://wiki.php.net/rfc/records! >=20 > Records allow for a lightweight syntax for defining value objects. = These are superior to read-only classes due to having value semantics = and far less boilerplate, for most things developers use read-only = classes for. They are almost as simple to use as arrays (and provide = much of the same semantics), but typed. >=20 > As an example, if you wanted to define a simple User record: >=20 > record User(string $emailAddress, int $databaseId); >=20 > Then using it is as simple as calling it like a function, with the & = symbol: >=20 > $rob =3D &User("rob@bottled.codes ", 1); >=20 > Since it has value semantics, we can get another instance, and it is = strongly equal to another of the same parameters: >=20 > $otherRob =3D &User("rob@bottled.codes ", = 1); > assert($otherRob =3D=3D=3D $rob); // true >=20 > Records may also have methods (even hooks), use traits, and implement = interfaces: >=20 > record Vector3(float $x, float $y, $z) implements Vector { > use Vector; > public float magnitude { > get =3D> return sqrt($this->x ** 2 + $this->y ** 2 + $this->z ** = 2) > } > } >=20 > Further, an automatic (but overridable) "with" method is generated for = every record. This allows you to get a new record similar to a given = one, very easily: >=20 > record Planet(string $name); >=20 > $earth =3D &Planet("earth"); > $mars =3D $earth->with(name: "mars"); >=20 > The depth of records was an immense exploration of the PHP engine, = language design, and is hopefully quite powerful for the needs of = everyday PHP and niche libraries. I took care in every aspect and tried = to cover every possible case in the RFC, but I still probably missed = some things. I plan on having a full implementation done by the end of = the year and open to a vote by the end of January, but I'd like to open = the discussion up here first. Love it or hate it, I'd like to hear your = thoughts. >=20 > =E2=80=94 Rob --Apple-Mail=_01F2A5F2-E317-44BA-825D-E0445CB333F9 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
Hi, = Rob!

I'm just wondering, why the implementation = differs from a regular class? 

Record = makes a "class" immutable and unique, using field value comparison = instead of object refs. It has a custom `with` method which is similar = to the new `clone` operator accepted recently. I'd suggest not = introducing a new keyword "record" and new syntax to create records, but = use regular `class` and `new Class`. Class should have a modifier "data" = like readonly, so it should be:

data class = Record {
    public function __construct(public = $a){} // $a is mutable, because why = not?
}

Data class will compare with = others using field value comparison. Moreover, if you want to make it = readonly, use the existing keyword to achieve = this:

readonly data class Record = {
    public function __construct(public $a){} // $a = is immutable, because of "readonly" class = modifier
}

1. So record Record {} = becomes readonly data class Record {}
2. We introduce data = classes, which are similar to records and are mutable by = default
3. No new constructions to create the new type of = classes, no adjustments for autoloading and other things = internally
4. Eliminate with method, replace `with` method = with the new `clone`
5. Inline constructor isn=E2=80=99t = necessary and could be proposed separately. I=E2=80=99ve thought = recently about this = feature

WDYT?

(sorry for = the duplicate in private mailbox)

----------

Best regards,
Dmitrii = Derepko.
@xepozz

On Nov 17, 2024, at 2:14=E2=80=AFA= M, Rob Landers <rob@bottled.codes> wrote:

Hello = internals,

I'm ready as I'm going to be to introduce to = you: "Records" https://wiki.php.net/rfc/records= !

Records allow for a lightweight syntax for defining value = objects. These are superior to read-only classes due to having value = semantics and far less boilerplate, for most things developers use = read-only classes for. They are almost as simple to use as arrays (and = provide much of the same semantics), but typed.

As an example, = if you wanted to define a simple User record:

record = User(string $emailAddress, int $databaseId);

Then using it is = as simple as calling it like a function, with the & = symbol:

$rob =3D &User("rob@bottled.codes", = 1);

Since it has value semantics, we can get another instance, and it = is strongly equal to another of the same parameters:

$otherRob =3D = &User("rob@bottled.codes", = 1);
assert($otherRob =3D=3D=3D $rob); // true

Records may also = have methods (even hooks), use traits, and implement = interfaces:

record Vector3(float $x, float $y, $z) = implements Vector {
  use Vector;
  public float magnitude {
    = get =3D> return sqrt($this->x ** 2 + $this->y ** 2 + = $this->z ** 2)
  }
}

Further, an automatic (but overridable) "with" = method is generated for every record. This allows you to get a new = record similar to a given one, very easily:

record = Planet(string $name);

$earth =3D &Planet("earth");
$mars =3D = $earth->with(name: "mars");

The depth of records was an immense exploration = of the PHP engine, language design, and is hopefully quite powerful for = the needs of everyday PHP and niche libraries. I took care in every = aspect and tried to cover every possible case in the RFC, but I still = probably missed some things. I plan on having a full implementation done = by the end of the year and open to a vote by the end of January, but I'd = like to open the discussion up here first. Love it or hate it, I'd like = to hear your thoughts.

=E2=80=94 = Rob

= --Apple-Mail=_01F2A5F2-E317-44BA-825D-E0445CB333F9--