develooper Front page | perl.perl5.porters | Postings from March 2021

Re: De-experimentalising "signatures"

Thread Previous | Thread Next
From:
B. Estrade
Date:
March 22, 2021 19:47
Subject:
Re: De-experimentalising "signatures"
Message ID:
d3db3a20-c7fe-73c0-34c4-08ed93d1073d@cpanel.net
On 3/22/21 11:55 AM, Paul "LeoNerd" Evans wrote:
> On Mon, 22 Mar 2021 17:12:19 +0100
> Leon Timmermans <fawaka@gmail.com> wrote:
> 
>> That does sound reasonable. I'm not sure why we haven't done so
>> already; that would have prevented this situation.
> 
> Without @_ you can't do arity-checking. E.g. while I personally dislike
> the style, a popular thing to do with object accessors is something
> like:
> 
>    sub name {
>      my $self = shift;
>      $self->{name} = shift if @_;
>      return $self->{name};
>    }
> 
> That could be written
> 
>    sub name ($self, $new = undef) {
>      $self->{name} = $new if @_ > 1;
>      return $self->{name};
>    }
> 
> (or something neater with Object::Pad + `method`), but lacking access
> to any form of scalar-snail, means we can't distinguish
> 
>    $obj->name()
> 
> from
> 
>    $obj->name(undef)
> 
> This is one among a number of reasons why @_ is currently still
> required in some situations, for which there are designs on adding more
> bits to signatures which will make simpler.
> 

I have never tried out signatures, but there's a lot of this style out 
there. '->' externally only seems to prepend the stringified name of 
__PACKAGE__ to @_.

There are actually 2 common patterns facilitated via the subroutine 
dereference idiom, effectively the same;

but one is for constructors:

sub new {
   my $pkg = shift;
   ...
   return $blessed_reference
}

and the other methods,

sub meth {
   my $self = shift;
   ... do stuff
}

Effectively, they are the same thing but are meaningful for humans when 
differentiating the constructor.

To keep the idiom intact in the context of both uses, and others that 
may be more creative, I don't see how access to @_ could be deprecated 
even in the face of "destructive" list operations like `shift`.

So is there use in electively making @_ immutable (or unavailable) in 
cases the developer want decorates their subroutine definition - or even 
denote via :lvalue that it is expecting "$self" because the it's 
intended to be called via __PACKAGE__->meth(...). The default case would 
behave as-is;

# case 1 - status quo

(as above)

# case 2 - __PACKAGE__ no restriction of caller; onus on developer to 
account for __PACKAGE__ in signature

sub new ($pkg, ..sig def) {
   # @_ is still available
   ...
   return $blessed_reference
}

and the other methods,

sub meth :self ($self, ..sig def) {
   # @_ is still available
   ... do stuff
}

# case 3 - __PACKAGE__ methods requires to be called 
__PACKAGE__->method(...) (no cheating allowed)

sub new :pkg (..sig def) {
   # $pkg is available, @_ is not
   ...
   return $blessed_reference
}

and the other methods,

sub meth :self (..sig def) {
   # $self is available, @_ is not
   ... do stuff
}

I must admit, it's not unlike some times I've "cheated" and called "oop" 
methods directly, using something like the following when I wanted to 
avoid full instantiation - mostly during unit test writing:

meth(q{Your::Package}, $arg1, ...);

Just a thought, I am sure this has been beaten into the ground at some 
point.

Cheers,
Brett

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About