Mailing List Archive

Having a :writer in 5.40 to pair with its :reader?
So the newly released Perl 5.39.8 implements :reader for the "class" feature.

Are we expecting to have some kind of :writer as well so that Perl 5.40 has them
as a pair?

While there was some discussion about whether or not the auto-generated :writer
sub should have a return value or not, I would assume that if this isn't finally
settled we could still have a version that does NOT return a value for 5.40, as
this would be backwards compatible with both use cases if we decided to change
it later.

Now FWIW this doesn't matter, as I personally tend to favor immutable objects
set only at construction time, and any exceptions I'd likely write setters for
explicitly. And I'd probably write getters explicitly too, especially if the
field in question is of some mutable type, so I can do protective cloning.

But I'm thinking for the benefit of others.

-- Darren Duncan
Re: Having a :writer in 5.40 to pair with its :reader? [ In reply to ]
Yes, please. Otherwise, it's not even.

I now use 'class' everywhere, I started to use the feature even before the
5.38.0 release.

It would be odd creating getters with :reader, and writing additional
wrapper methods for creating setters instead of using the :writer field
attribute.

And refactor those setter methods to fields with :writer attribute later in
the 5.42 release.

Thanks.

On Tue, Feb 27, 2024 at 9:44?PM Darren Duncan <darren@darrenduncan.net>
wrote:

> So the newly released Perl 5.39.8 implements :reader for the "class"
> feature.
>
> Are we expecting to have some kind of :writer as well so that Perl 5.40
> has them
> as a pair?
>
> While there was some discussion about whether or not the auto-generated
> :writer
> sub should have a return value or not, I would assume that if this isn't
> finally
> settled we could still have a version that does NOT return a value for
> 5.40, as
> this would be backwards compatible with both use cases if we decided to
> change
> it later.
>
> Now FWIW this doesn't matter, as I personally tend to favor immutable
> objects
> set only at construction time, and any exceptions I'd likely write setters
> for
> explicitly. And I'd probably write getters explicitly too, especially if
> the
> field in question is of some mutable type, so I can do protective cloning.
>
> But I'm thinking for the benefit of others.
>
> -- Darren Duncan
>
Re: Having a :writer in 5.40 to pair with its :reader? [ In reply to ]
Darren Duncan <darren@darrenduncan.net> wrote:
>
> Are we expecting to have some kind of :writer as well so that Perl 5.40 has them as a pair?

We do not:

https://www.nntp.perl.org/group/perl.perl5.porters/2024/02/msg267844.html


--
Arne Johannessen
<https://arne.johannessen.de/>
Re: Having a :writer in 5.40 to pair with its :reader? [ In reply to ]
On Tue, 27 Feb 2024 12:44:05 -0800
Darren Duncan <darren@darrenduncan.net> wrote:

> Are we expecting to have some kind of :writer as well so that Perl
> 5.40 has them as a pair?

Nope.

> While there was some discussion about whether or not the
> auto-generated :writer sub should have a return value or not

That was one among many reasons. There are others:

* What does :writer on a non-scalar field look like? What does it do?
Does it take a list of values and behave like list assignment? Or
does it take a single value being a reference to a container of new
values? Or do we just forbid it like we do on :param ?

* Once we have a :writer we need a :weaken, in case you wanted to
implement

method set_thing { builtin::weaken( $thing = shift ); }

How do :writer and :weaken interact, order-wise? Does it matter if
you did one first, vs. the other?

* How would a :writer interact with whatever value-constraint
assertion system we may end up adding? That's still a valid question
for :param as well, admittedly.

These are more tricky questions to deal with. I don't recall anyone
interacting with me on them, so in the time I've had I hadn't really
got around to a practical answer on any of them. Implementing :reader
took me a couple of hours so I managed to do that in time. There's no
time left before pre-5.40 feature freeze to get any :writer stuff in
now.

But if people actually want to help on anything then hopefully we can
get some of this in in time for 5.42.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Having a :writer in 5.40 to pair with its :reader? [ In reply to ]
On Wed, Feb 28, 2024 at 4:23?PM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:


> * What does :writer on a non-scalar field look like? What does it do?
> Does it take a list of values and behave like list assignment? Or
> does it take a single value being a reference to a container of new
> values? Or do we just forbid it like we do on :param ?
>

I feel like I haven't done enough to remind everyone of the design team's
thoughts on this and I'm sorry for that. We realized that non-scalar fields
were problematic, but there's so stuff to cover that it's easy to miss
this, so this is my fault for not following up.

The design team agreed that for the MVP, there were no attributes allowed
on non-scalar fields (except :common) due to these problems. Per the RFC,
section 6.2
<https://github.com/Perl-Apollo/Corinna/blob/master/rfc/attributes.md#62-field-creation>
:


*"For scalar fields declared with field (and only for scalar fields), you
can add attributes after the declaration and before the optional default,
if any."*

This is reinforced in the perlclasstut documentation I shared
<https://github.com/Perl-Apollo/Corinna/blob/master/pod/perlclasstut.pod#non-scalar-fields>
.






*"You can declare arrays and hashes as fields, with or without defaults:"
field @colors = qw/green yellow red/; field %seen;*




*"However, array and hash fields cannot have modifiers:" field %seen
:reader; # compile-time error field @array :param; # compile-time
error field %hash :writer; # compile-time error*

I recall it being agreed by the design team that we could revisit this
post-MVP. The flattening nature of Perl hashes and arrays makes this a
difficult problem.

But even having a :reader on non-scalars is problematic:

class Foo {
field @colors :reader = qw(red green blue);
}
my $colors = Foo->new->colors;

I've assigned to a scalar. Presumably the colors() method returns a list,
not an array ref. So $colors will now equal "blue"? I don't see how that's
useful. If we have field %hash :reader, assignment to a scalar will
effectively return a random value from the hash.

Worse, subtle bugs might occur if the value returned is undefined, making
it look, possibly incorrectly, as if the field variable wasn't initialized.

If we follow the RFC scrupulously, I think we can avoid these troublesome
cases and deal with them after we have the smaller MMVP released and people
have a better understanding of its behavior.

* Once we have a :writer we need a :weaken, in case you wanted to
> implement
>
> method set_thing { builtin::weaken( $thing = shift ); }
>
> How do :writer and :weaken interact, order-wise? Does it matter if
> you did one first, vs. the other?
>

I agree we need a :weaken, but for the MVP? I don't see that being used
*that* often in Moo/se, so we can document this as a limitation, though
perhaps I'm thinking unclearly on this.

The :weak attribute (written as :weaken) only shows up in the MMVP proposed
for the core <https://github.com/Perl-Apollo/Corinna/blob/master/rfc/mvp.md>.
It's not listed in the full MVP because, while discussed, it was never
specced. Confession time: I noticed some deviations on the MMVP features
from the MVP spec, but at that point, I was so burnt out on Corinna that I
just didn't say anything. Mea culpa.


> * How would a :writer interact with whatever value-constraint
> assertion system we may end up adding? That's still a valid question
> for :param as well, admittedly.
>

I don't believe this can be answered. We've no agreements on either the
syntax or semantics of said assertion system and, as you've pointed out, we
have no one to implement it. Barring some miracle, it's probably going to
be years before we can get there. I don't think anyone wants :writer
blocked for years waiting for something which may or may not happen.


> These are more tricky questions to deal with. I don't recall anyone
> interacting with me on them, so in the time I've had I hadn't really
> got around to a practical answer on any of them. Implementing :reader
> took me a couple of hours so I managed to do that in time. There's no
> time left before pre-5.40 feature freeze to get any :writer stuff in
> now.
>
> But if people actually want to help on anything then hopefully we can
> get some of this in in time for 5.42.
>

Again, if we stick to the spec, I think we're in a much better place
because the design team hammered this out over a multi-year period.

I will try to do a better job of following up on this. I'm sorry I have not.

Best,
Ovid
Re: Having a :writer in 5.40 to pair with its :reader? [ In reply to ]
For all my use cases, I consider the lack of explicit support for non-scalar
fields with attributes to be a non-issue, since I would always use scalar fields
for collections anyway, eg $myarrayref rather than @myarray and so on, and this
is how I prefer to code all of my Perl anyway. -- Darren Duncan

On 2024-02-28 11:35 p.m., Ovid wrote:
> On Wed, Feb 28, 2024 at 4:23?PM Paul "LeoNerd" Evans wrote:
>
>  * What does :writer on a non-scalar field look like? What does it do?
>    Does it take a list of values and behave like list assignment? Or
>    does it take a single value being a reference to a container of new
>    values? Or do we just forbid it like we do on :param ?
>
>
> I feel like I haven't done enough to remind everyone of the design team's
> thoughts on this and I'm sorry for that. We realized that non-scalar fields were
> problematic, but there's so stuff to cover that it's easy to miss this, so this
> is my fault for not following up.
>
> The design team agreed that for the MVP, there were no attributes allowed on
> non-scalar fields (except :common) due to these problems. Per the RFC, section
> 6.2
> <https://github.com/Perl-Apollo/Corinna/blob/master/rfc/attributes.md#62-field-creation>:
>
> /"For scalar fields declared with field (and only for scalar fields), you can
> add attributes after the declaration and before the optional default, if any."
> /
>
> This is reinforced in the perlclasstut documentation I shared
> <https://github.com/Perl-Apollo/Corinna/blob/master/pod/perlclasstut.pod#non-scalar-fields>.
>
> /"You can declare arrays and hashes as fields, with or without defaults:"
>
>     field @colors = qw/green yellow red/;
>     field %seen;
>
> /
> /"However, array and hash fields cannot have modifiers:"
>
>     field %seen :reader;  # compile-time error
>     field @array :param;  # compile-time error
>     field %hash :writer;  # compile-time error/
> I recall it being agreed by the design team that we could revisit this post-MVP.
> The flattening nature of Perl hashes and arrays makes this a difficult problem.
>
> But even having a :reader on non-scalars is problematic:
>
>     class Foo {
>         field @colors :reader = qw(red green blue);
>     }
>     my $colors = Foo->new->colors;
>
> I've assigned to a scalar. Presumably the colors() method returns a list, not an
> array ref. So $colors will now equal "blue"? I don't see how that's useful. If
> we have field %hash :reader, assignment to a scalar will effectively return a
> random value from the hash.
>
> Worse, subtle bugs might occur if the value returned is undefined, making it
> look, possibly incorrectly, as if the field variable wasn't initialized.
>
> If we follow the RFC scrupulously, I think we can avoid these troublesome cases
> and deal with them after we have the smaller MMVP released and people have a
> better understanding of its behavior.
>
>  * Once we have a :writer we need a :weaken, in case you wanted to
>    implement
>
>      method set_thing { builtin::weaken( $thing = shift ); }
>
>    How do :writer and :weaken interact, order-wise? Does it matter if
>    you did one first, vs. the other?
>
>
> I agree we need a :weaken, but for the MVP? I don't see that being used
> /that/ often in Moo/se, so we can document this as a limitation, though perhaps
> I'm thinking unclearly on this.
>
> The :weak attribute (written as :weaken) only shows up in the MMVP proposed for
> the core <https://github.com/Perl-Apollo/Corinna/blob/master/rfc/mvp.md>. It's
> not listed in the full MVP because, while discussed, it was never specced.
> Confession time: I noticed some deviations on the MMVP features from the MVP
> spec, but at that point, I was so burnt out on Corinna that I just didn't say
> anything. Mea culpa.
>
>  * How would a :writer interact with whatever value-constraint
>    assertion system we may end up adding? That's still a valid question
>    for :param as well, admittedly.
>
>
> I don't believe this can be answered. We've no agreements on either the syntax
> or semantics of said assertion system and, as you've pointed out, we have no one
> to implement it. Barring some miracle, it's probably going to be years before we
> can get there. I don't think anyone wants :writer blocked for years waiting for
> something which may or may not happen.
>
> These are more tricky questions to deal with. I don't recall anyone
> interacting with me on them, so in the time I've had I hadn't really
> got around to a practical answer on any of them. Implementing :reader
> took me a couple of hours so I managed to do that in time. There's no
> time left before pre-5.40 feature freeze to get any :writer stuff in
> now.
>
> But if people actually want to help on anything then hopefully we can
> get some of this in in time for 5.42.
>
>
> Again, if we stick to the spec, I think we're in a much better place because the
> design team hammered this out over a multi-year period.
>
> I will try to do a better job of following up on this. I'm sorry I have not.
>
> Best,
> Ovid
Re: Having a :writer in 5.40 to pair with its :reader? [ In reply to ]
On Thu, 29 Feb 2024 at 15:35, Ovid <curtis.poe@gmail.com> wrote:

> But even having a :reader on non-scalars is problematic:
>
> class Foo {
> field @colors :reader = qw(red green blue);
> }
> my $colors = Foo->new->colors;
>
> I've assigned to a scalar. Presumably the colors() method returns a list,
> not an array ref. So $colors will now equal "blue"? I don't see how
> that's useful. If we have field %hash :reader, assignment to a scalar
> will effectively return a random value from the hash.
>

That doesn't sound right - it sounds like you expect `sub { qw(red green
blue) }` behaviour, which I think would be very surprising?

The @colors field is an array. The accessor returns that array, not a
static list. `return @x` in scalar context has well-defined behaviour:

$ perl -le'use 5.038; package Foo { sub new ($class) { bless { colors => [
qw(red green blue) ] }, $class } sub colors ($self) { $self->{colors}->@* }
} my $colors = Foo->new->colors; print $colors'
3

It's useful in the same way that any function returning an array/hash in
scalar context would be useful: example use-cases could be "does this have
items", "how many items do we have".
Re: Having a :writer in 5.40 to pair with its :reader? [ In reply to ]
On Thu, Feb 29, 2024 at 9:06?AM Tom Molesworth <tom@deriv.com> wrote:


> I've assigned to a scalar. Presumably the colors() method returns a list,
>> not an array ref. So $colors will now equal "blue"? I don't see how
>> that's useful. If we have field %hash :reader, assignment to a scalar
>> will effectively return a random value from the hash.
>>
>
> That doesn't sound right - it sounds like you expect `sub { qw(red green
> blue) }` behaviour, which I think would be very surprising?
>
> The @colors field is an array. The accessor returns that array, not a
> static list. `return @x` in scalar context has well-defined behaviour:
>

Ah yes, you're right! So that point is probably a non-issue. Thank you :)

I still think the other points are valid, vis-a-vis sticking to the spec we
have.

Best,
Ovid