Re: Immutable modifier

From: Date: Mon, 16 Nov 2015 11:30:31 +0000
Subject: Re: Immutable modifier
References: 1 2 3 4  Groups: php.internals 
Request: Send a blank email to internals+get-89232@lists.php.net to get a copy of this message
Mathieu Rochette wrote on 16/11/2015 10:00:
Would it be allowed to assign non immutable types to properties of an immutable class ?
I think this is the trickiest part of trying to enforce immutability: nesting. Consider the following: // Basic properties $my_immutable_object->foo = 42; $my_immutable_object->foo++; // Nested object - implicitly immutable? required to be explicitly immutable? $my_immutable_object->bar->something = 42; $my_immutable_object->bar->setSomething(42); // Array access - no idea how this should work $my_immutable_object->quux[0] = 42; $my_immutable_object->quux[] = 'Hello'; $my_immutable_object->quux['World'][0]['X'] = 'A'; The other problem is that to be useful, certain functions usually need to be able to mutate the state of objects which are officially immutable. For instance, implementations of PSR-7 need a set of copy constructors for the withX methods. You could do this using the suggested rule that immutability applies only to non-null properties, and manually populate every property of an empty instance, but it's much more efficient to "clone $this" and then change the one property that needs to be different. For this particular example, you could write quite a nice implementation by "freezing" the instance once it's initialised: // example plucked from https://github.com/guzzle/psr7/blob/master/src/Request.php#L101
    public function withMethod($method)
    {
        // The method starts by making a mutable clone of the immutable $this
        $new = clone $this;
        $new->method = strtoupper($method);
        # SUGGESTED ADDITION: new keyword to set an object to be immutable
        freeze $new;
        // After this point, nothing should be able to mutate the new object, only clone it
        return $new;
    }
The freeze operation could perhaps be recursive, or perhaps it could work like "clone", with an "__freeze" method responsible for freezing nested objects as necessary. The ability to freeze an array would also be useful in that case... I realise this is a lot more complex than the original suggestion, but I think something of this level of detail is needed to make it useful. Regards, -- Rowan Collins [IMSoP]

« previous php.internals (#89232) next »