Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:81525 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 69476 invoked from network); 1 Feb 2015 09:38:42 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Feb 2015 09:38:42 -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.27 cause and error) X-PHP-List-Original-Sender: larry@garfieldtech.com X-Host-Fingerprint: 66.111.4.27 out3-smtp.messagingengine.com Received: from [66.111.4.27] ([66.111.4.27:44045] helo=out3-smtp.messagingengine.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 73/D3-01632-224FDC45 for ; Sun, 01 Feb 2015 04:38:42 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id E05E8205F1 for ; Sun, 1 Feb 2015 04:38:39 -0500 (EST) Received: from frontend1 ([10.202.2.160]) by compute1.internal (MEProxy); Sun, 01 Feb 2015 04:38:39 -0500 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=x-sasl-enc:message-id:date:from :mime-version:to:subject:references:in-reply-to:content-type :content-transfer-encoding; s=smtpout; bh=pp06KXFD2A3av+8LX95N9R 1i2ZA=; b=HNuLjtw60xlJFlPPWe87meEru8CAolHrVvgGczxXCatkRjZeH+VM1/ lx1kh0DxpkP3/SiuBudsIObmYM289Mo2bvgHZGbMCYfRDO9wtNO5oKxMsQloykEP AXJ6cysPq+pkBDwPpFh5Erb6g2lC6pAuLRhWoYnubqaPA7JtcLSB0= X-Sasl-enc: KrLWgVD4TaghodPJ29T7nYafOrLXnDAKC4926c8hGXJe 1422783519 Received: from [192.168.42.108] (unknown [98.226.241.18]) by mail.messagingengine.com (Postfix) with ESMTPA id A0109C00290 for ; Sun, 1 Feb 2015 04:38:39 -0500 (EST) Message-ID: <54CDF420.1030801@garfieldtech.com> Date: Sun, 01 Feb 2015 03:38:40 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: internals@lists.php.net References: <54CBC804.7050706@gmail.com> <54CD7668.30301@garfieldtech.com> <54CD7975.8040908@gmail.com> <54CDE9FF.40700@googlemail.com> In-Reply-To: <54CDE9FF.40700@googlemail.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] [RFC] Immutable variables and objects From: larry@garfieldtech.com (Larry Garfield) On 02/01/2015 02:55 AM, Crypto Compress wrote: > >>> The with*() methods in PSR-7 are documented to return a new instance, >>> not modify the existing instance. Yes, there's no way in PHP itself to >>> force that syntactically, which is why documentation exists. :-) >>> >>> Also, in the benchmarks we've run the performance cost of all those new >>> objects is measured in nanoseconds, ie, small enough that we're not >>> worried about it. (Hats off to the PHP Internals folks for making that >>> fast!) >> It is great that this is fast, but I wonder (maybe off-topic?) why do >> it? I.e. it is clear that in something like: >> >> $a = new Request->withHeaders(...)->withBody(...) >> ->withEncoding(...)->withETag(...) >> >> the intermediate objects are useless and nobody needs 5 new objects when >> you do it. Am I missing something here? > > Hi, > > my assumptions after some testing: > - This is only true in case of reassigning ($a = clone $a) the old > variable, as refcount for underlying values remains 1 for all values > in clones, so cow don't need to copy anything. > - If the old object is not thrown away, then memory consumption is > doubled and the "fast" argument is wrong. > (Performance, of cloning an object without copying values and of some > method calls, is negligible.) I'm not sure that anyone has benchmarked the memory impact of the immutable approach yet. I will pass that along and see what data comes out. > Omit mutator methods (with*/set*) is a simple and logical way to > achieve immutability in PHP. No need for const/final/... (Someone feel free to declare this thread off topic now, as we're basically just rehashing discussions had weeks ago on the FIG list.) The original calls for immutable HTTP message objects had no with*() methods. They objects were set from their constructor and that was the end of it. However, many people (myself included) pointed out that such objects, in actual practice, would be completely unusable. Middlewares need to be able to pass information from one layer to another; the most straightforward way to do that is (as Symfony does and PSR-7 recommends) an attributes collection on the request. But if you can't set that without going through a new constructor manually it becomes horribly difficult to do. Similarly, middlewares that want to set cache information for a whole application, encrypt/decrypt headers, or do anything else actually useful have to manually replicate the object themselves. An object with a complex constructor with lots of parameters offers, really, no value over a big-ass array. It's almost worse in my experience. (And yes, I've used such APIs and yes, I detest them.) Too, the constructor is obviously not part of the interface, which means every implementation would have its own constructor, thus eliminating the benefit of having a standard at all. The with*() methods solved that problem entirely, and enabled a nice fluent style for those who are into such things. --Larry Garfield