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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to