On 23/11/2024 16:05, Rob Landers wrote:
Your RFC doesn't discuss this - the changeName example shows behaviour
*inside* the method, but not behaviour when *calling* it
An interesting observation, can you explain more as to what you mean?
Looking closer, there's a hint at what you expect to happen in your
Rectangle example:
$bigRectangle = $rectangle->resize(10, 20);
assert($bigRectangle !== $rectangle); // true
It seems that modifications to $this aren't visible outside the method,
creating a purely local clone, which would be discarded if it wasn't
returned (or saved somewhere).
I can see the logic, but the result is a bit unintuitive:
data class Example {
public function __construct(public int $x) {}
public function inc(): void {
$this->x++;
}
}
$foo = new Example(0);
$foo->x++;
$foo->inc();
echo $foo->x; // 1, not 2
I think it would be clearer to prevent direct modification of $this:
data class Example {
public function __construct(public int $x) {}
public function inc(): void {
$this->x++; // ERROR: Can not mutate $this in data class
}
public function withInc(): static {
$new = $this; // explicitly make a local copy of $this
$new->x++; // copy-on-write separates $new from $this
return $new;
}
}
That would still be compatible with Ilija's suggestion, which was to add
special "mutating methods":
data class Example {
public function __construct(public int $x) {}
public mutating function inc(): void {
$this->x++;
}
}
$foo = new Example(0);
$foo->x++;
$foo->inc!(); // copy-on-write triggered *before* the method is called
echo $foo->x; // 2
--
Rowan Tommins
[IMSoP]