Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:89247 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 27346 invoked from network); 16 Nov 2015 22:11:12 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 16 Nov 2015 22:11:12 -0000 Authentication-Results: pb1.pair.com smtp.mail=larry@garfieldtech.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=larry@garfieldtech.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain garfieldtech.com from 66.111.4.29 cause and error) X-PHP-List-Original-Sender: larry@garfieldtech.com X-Host-Fingerprint: 66.111.4.29 out5-smtp.messagingengine.com Received: from [66.111.4.29] ([66.111.4.29:59618] helo=out5-smtp.messagingengine.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 46/83-34372-F745A465 for ; Mon, 16 Nov 2015 17:11:12 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 7F43420854 for ; Mon, 16 Nov 2015 17:11:09 -0500 (EST) Received: from frontend2 ([10.202.2.161]) by compute1.internal (MEProxy); Mon, 16 Nov 2015 17:11:09 -0500 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-sasl-enc:x-sasl-enc; s=smtpout; bh=4vYiSnYQ65fHNoE lgxZ//z72+pQ=; b=AzJDJKjDv3psEU79t4uHDptg5LDhDNukY+deoNsF99AXThv fMJsDJOwdjUQSFio3Vtu/+4I2A5um3P2SHCFWXjy5Vw/C8C03DxHk33VYED2jxn4 K0UCdNgiyETB4nAfGWOB82nmmdC8OyN3mYxAYg84fnd5t0/+hWgF7C6kOYxU= X-Sasl-enc: c45+5U4IsBBAhqrIgMLKMTRXuU8ZRwG6ZVOQajU1SJjR 1447711869 Received: from Crells-MacBook-Pro.local (unknown [63.250.249.138]) by mail.messagingengine.com (Postfix) with ESMTPA id 4047068017B for ; Mon, 16 Nov 2015 17:11:09 -0500 (EST) To: internals@lists.php.net References: Message-ID: <564A547C.9060504@garfieldtech.com> Date: Mon, 16 Nov 2015 16:11:08 -0600 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Thunderbird/38.0.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Immutable modifier From: larry@garfieldtech.com (Larry Garfield) On 11/16/15 3:15 AM, Chris Riley wrote: > Hi, > > There has been a lot of interest recently (eg psr-7) in immutable data. I'm > considering putting an RFC together to add language support for immutables: > > immutable class Foo { > public $bar; > public function __construct($bar) { > $this->bar = $bar; > } > } > > Immutable on a class declaration makes all (maybe only public?) properties > of the class immutable after construct; assigning to a property would > result in a Fatal error. > > class Foo { > public $bar; > immutable public $baz; > } > > Immutable on a property makes the property immutable once it takes on a > none null value. Attempts to modify the property after this results in a > fatal error. > > Any thoughts? > ~C As a firm believer in the value of immutable data structures, I don't believe such a simple approach would be useful and would likely be counter-productive. The trick is there are 2 cases for immutability: An immutable service object, and an immutable data object. A service object should be immutable once it's setup. However, that setup *may*, in some cases, involve setter injection. That's inferior or constructor injection but that is not always feasible. In practice, I'm not sure we need new syntax here at all. For data objects, this is where it gets interesting. Data objects *do* need to be modifiable for a given context... for that context. Immutable data objects are, largely, useless and in my experience harmful unless they have a ->giveNewVersionWithThisOneChange() method. In PSR-7, that's the with*() methods. DateTimeImmutable has the same methods as DateTime, but they return new instances rather than modifying the invoked object (despite their confusing names, which are like that for historical reasons). My ideal would be to revive the property RFC and leverage per-property access control separately for read and write to create externally-immutable objects. That would allow for with*() methods to be implemented as appropriate for a given object. The problem with a simple keyword approach is that "modifier" methods often should not, and in the case of PSR-7 cannot, correspond to simple get/set mapping to an object property. (See withAddedHeader(), withoutHeader(), etc.) Some level of flexibility needs to be given to the implementer to create an effectively-immutable object that is more than just a bare struct that's hard to work with. If there were some way to flag for the compiler that "This object is supposed to be effectively-immutable, please check and make sure I didn't screw that up", that would be lovely but sounds hard. :-) -- --Larry Garfield