Re: [RFC][DISCUSSION] - Immutable classes and properties
| From: | Davey Shafik | Date: | Mon, 12 Dec 2016 05:58:52 +0000 |
| Subject: | Re: [RFC][DISCUSSION] - Immutable classes and properties | ||
| References: | 1 2 3 4 5 6 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-97363@lists.php.net to get a copy of this message | ||
On Sun, Dec 11, 2016 at 7:40 PM, Mathieu Rochette <mathieu@texthtml.net>
wrote:
>
>
> On 12/12/2016 01:16 AM, Silvio Marijić wrote:
> > This have occurred to me also, I wanted to separate that into two RFC's,
> > but then how we deal with RFC's that depend on each other?
> well that's just my opinion but I don't think they depend on each other,
> this rfc seems useful on its own. The "clone" one might depends on this
> one but it does not *need* to either (otoh it certainly would be much
> more useful with immutable classes than mutable classes)
>
> plus, this part might already trigger enough discussion and adding
> everything at once might get confusion. I can think of : clone, late
> initialization, DateTimeImmutable and probably other subjects that could
> make the discussion noisy
>
> I'm not as familiar as you are with this mailing list so I might very
> well be wrong too ^^
> >
> > 2016-12-12 1:03 GMT+01:00 Larry Garfield <larry@garfieldtech.com>:
> >
> >> Assuming this was intended for the list...
> it was, thank you
> >>
> >> On 12/11/2016 05:55 PM, Mathieu Rochette wrote:
> >>
> >>> Currently the only "unlocked context" for an object is its
> >>> constructor. As discussed previously, that is insufficient. For any
> >>> non-trivial object (more than 1-3 internal properties) creating a new
> >>> one via the constructor only when incrementally building is
> >>> prohibitively difficult. The pattern of with*() methods that spawn
> >>> new objects via clone(), a la PSR-7, needs to be supported. That is:
> >>>
> >>> immutable class Money {
> >>> // ...
> >>>
> >>> public function add(Money $other) : Money {
> >>> $new = clone($this);
> >>> $new->amount += $other->amount;
> >>> return $new;
> >>> }
> >>> }
> >>>
> >>> I'm not sure how easily we can denote that sort of case. It's outside
> >>> the __clone() function itself, which is what makes it difficult.
> >>> Without that, though, such immutable objects are of only limited use.
> >>>
> >>
> >>
> >>> As you said, it has been already been discussed that a method to build
> >>> new altered object from an existing one could be improved. Different
> >>> options were proposed but maybe it's better to start small to get this
> >>> first part right and add this in another rfc ? having everything at the
> >>> same time might makes the rfc more difficult to be accepted
> >>>
> >> On the contrary, an RFC that doesn't fully solve the issue at hand and
> >> leaves major gaps in place is a poor RFC, and I would expect to be
> >> justifiably voted down.
>
I wonder if we can essentially make all public methods act like they are
static (no access to $this) and then use something like:
immutable class Foo {
protected $bar;
public function getBar() with (Foo $instance): string // $instance is
a clone of $this
{
// context == $instance, so access to private/protected
return $instance->bar;
}
public function withBar($bar) with (Foo $instance): Foo
{
$instance->bar = $bar; // Allowed as we're in scope
return $instance;
}
}
Only operations in the scope of the class itself (and it's descendants,
adhering to standard visibility rules) can make changes on the cloned
variant. The
with ($instance) is optional, $instance is just a variable
name. In reality you'll want to use it most of the time I imagine.
I suppose you can re-use the use keyword here too.
Also, this shouldn't allow for immutable properties.
Another option is to look at the way that HHVM does immutable types, though
that is _file_ based.
- Davey