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

Re: "no snails"; or having signatured subs complain about @_

Thread Previous | Thread Next
From:
Paul "LeoNerd" Evans
Date:
December 7, 2021 18:02
Subject:
Re: "no snails"; or having signatured subs complain about @_
Message ID:
20211207180223.1f085ca9@shy.leonerd.org.uk
On Tue, 7 Dec 2021 09:59:28 +0000
Dave Mitchell <davem@iabyn.com> wrote:

>     Query Parameters
>     http://nntp.perl.org/group/perl.perl5.porters/256680
...
> My proposal also included 'query parameters', which declare a
> parameter (i.e. a lexical var) but don't consume an argument -
> instead the var is set to some value indicating the current state of
> argument processing. Two query parameter types particularly relevant
> here are:
> 
>     (??$has_a, $a) # $has_a is set to true if there's an argument for
> $a (?*@args, ...) # the lexical var @args behaves just like the old
> @_ # i.e.  whose elements are aliases of the passed
>                    # arguments

I think a lot of that isn't even necessary though. A variant of my
no-snails branch which I haven't yet committed or pushed, very slightly
relaxes the rules and allows a use of @_ as an rvalue in scalar
context, purely to allow the code to determine the argument count.

Many uses of signatured subs in practice don't need to use @_ at all,
so are already no-snails safe. Of the remaining, the only case I have
ever seen in the wild is using @_ as a scalar to see if any (or maybe
how many) arguments were passed. The vast majority are things like the
combined reader-or-writer accessors of the form I personally dislike
but seem quite popular:

  sub red($self, $new = undef) {
     $self->{red} = $new if @_ > 1;
     return $self->{red};
  }

  $obj->red(123);                    # sets a new value
  say "Redness is now ", $obj->red;  # retrieves existing

It's almost entirely unheardof for @_ to ever appear in any situation
other than this. In these situations I think it could be quite easy to
permit a `builtin::argc` to allow it:

  use builtin 'argc';

  sub red($self, $new = undef) {
     $self->{red} = $new if argc > 1;
     return $self->{red};
  }

Potentially we could even still permit the use of @_ but only in
known-{scalar rvalue} contexts (such as the code above) allowing it to
continue to run unmodified from its current form. Already there is lots
of real code out in the wild (on CPAN and elsewhere) using @_ in
signatured subs in this way, and I think it would be nice not to break
them.


I will be entirely honest, and suggest that if we had some sort of argc
ability (either as a new builtin/keyword of that name, or just
scalar(@_) ) then I don't really see a use-case for any of the rest of
the query parameters extension. It seems a lot of extra syntax to have
to implement and explain to users.

It is perhaps cultural and perception-based, but given a choice between

  sub green($opt = undef) {
     say "Has optional argument $opt" if argc;
  }

  sub blue(??$has_opt, $opt = undef) {
     say "Has optional argument $opt" if $has_opt;
  }

I think I would prefer the former, both in terms of writing it for
myself, and explaining it to others.

-- 
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/

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