2020-12-29 22:43 GMT, Rowan Tommins <rowan.coll...@gmail.com>:
> On 29/12/2020 18:38, Olle Härstedt wrote:
>> Instead of shoe-horning everything into the PHP object system, did
>> anyone consider adding support for records instead, which would always
>> be immutable, and could support the spread operator for cloning-with
>> similar as in JavaScript or OCaml? They could be based on PHP arrays
>> and thus be passed by value.
>
>
> While we could create a brand new "record" or "struct" type, I think
> there are a few reasons to think it would end up *looking* more like
> objects than arrays:
>
> - we have an established syntax for declaring types of object (class Foo
> {...}), and none for declaring types of array
> - the 'bar' in $foo['bar'] is an expression, implying dynamic options;
> the bar in $foo->bar is a bare identifier, implying statically defined
> options
> - similarly, we have a syntax for creating object instances, with
> statically analysable members: new Foo(bar: 42)
>
>
> The spread operator could be made to work with either style, if we
> preferred it to using "clone ... with ...":
>
> - ['bar'=>69, ...$existingFoo]
> - new Foo(bar: 69, ...$existingFoo)
>
>
> However, arrays arguably already have a clone-with syntax, more normally
> thought of as "copy-on-write". Rather than "mutable with special logic
> to pass and assign by value", I think you can model their behaviour as
> "immutable with special logic to clone with modifications":
>
> $foo = ['bar'=>42, 'baz'=>101];
> $newFoo = $foo; // lazy assignment by value is indistinguishable from
> assignment by pointer
> $newFoo['bar'] = 69; // $newFoo is a modified clone of $foo
> $newFoo['bar'] = 72; // mutating $newFoo in place is indistinguishable
> from creating and assigning another modified clone
>
>
> In theory, "records" could have this ability with object-like syntax:
>
> $foo = new Foo(bar: 42, baz: 101);
> $newFoo = $foo;
> $newFoo->bar = 69; // $newFoo is a modified clone
> $newFoo->bar = 72; // can be optimised as in-place modification, but
> conceptually cloning again
>
>
> In the simple case, that's equivalent to a clone-with:
>
> $foo = new Foo(bar: 42, baz: 101);
> $newFoo = clone $foo with { bar: 69 };
> $newFoo = clone $newFoo with { bar: 72 }; // can probably be optimised
> the same way as the above examples
>
>
> It would allow more complex modifications, though, such as deep
> modification:
>
> $foo = new Foo(bar: new Bar(name: 'Bob'));
> $newFoo = $foo;
> $newFoo->bar->name = 'Robert';
>
> That last line would do the same as this:
>
> $newFoo = clone $newFoo with { bar: clone $newFoo->bar with { name:
> 'Robert' }};
>
> How desirable that is, and how it fits with the use cases in Larry's
> post, I'm not sure.
>
>
> Regards,
>
> --
> Rowan Tommins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>

Good breakdown. One benefit of records is that they can be
structurally typed (instead of nominally, as classes are), but that's
probably never going to happen in PHP. :) Perhaps a `readonly`
attribute is best for now? Compare with the annotation supported by
Psalm: 
https://psalm.dev/docs/annotating_code/supported_annotations/#psalm-readonly-and-readonly

Olle

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

Reply via email to