Front page | perl.perl5.porters |
Postings from November 2019
Parameter Attributes
Thread Previous
|
Thread Next
From:
Dave Mitchell
Date:
November 28, 2019 17:01
Subject:
Parameter Attributes
Message ID:
20191128170100.GA3573@iabyn.com
=head2 Synopsis:
sub f ($x :foo, $y :bar(baz) bar2(baz2), ...) { ... }
analogous to:
my $x :foo;
my $y :bar(baz) bar2(baz2);
We should support parameter attributes. I think this is a relatively
uncontroversial proposal.
What exactly should the semantics be? Lets first review the current syntax
as applied to 'my' declarations:
my ($x, $y) :foo(foo_arg) :bar(bar_arg);
is roughly equivalent to
use attributes ();
my ($x,$y);
attributes->import(, __PACKAGE__, \$x, "foo(foo_arg)", "bar(bar_arg)");
attributes->import(, __PACKAGE__, \$y, "foo(foo_arg)", "bar(bar_arg)");
except that some attributes are built-in and are recognised and handled
directly by the lexer / parser, without attributes.pm ever getting
involved.
Note that attributes.pm says that attributes on variables are currently
experimental, although in practice we've supported things like
my $x : shared; for years.
As an aside, note that any argument to the attribute is scanned as a
single-quoted string - i.e. like q(...) - but is otherwise uninterpreted
by Perl itself. Thus hypothetically a constraint expressed as an
attribute, e.g.
sub foo ($x :where($x ne '(' ));
wouldn't get correctly parsed unless we handled it specially somehow,
which seems to be an argument for *not* using attributes for such things,
and instead use purpose-designed syntax, like, for example:
sub foo ($x where $x ne '(', ...)
Second and subsequent attributes may be preceded by a colon, but don't
have to be: these are equivalent:
my $x :foo :bar(1) :bar(2);
my $x :foo bar(1) :bar(2);
Thus for signatures, the obvious semantics would be that
sub f ($a :foo, ...) {...}
is equivalent to
sub f { my $a :foo; $a = $_[0]; .... }
The exact details of when attributes->import() is called is discussed in
the "Scope and Ordering" thread.
Once available, built-in attributes could in principle be used where Perl
6 uses traits, e.g.
sub f($x is ro) { ... } # Perl 6
sub f($x :ro) { ... } # Perl 5 ???
See the "Aliasing and Read-only variables" thread for more detailed
proposals.
Attributes can't be used on a placeholder parameter:
($x :foo) # ok
($ :foo) # error
Attributes can't be used with aliasing, except for slurpies (which alias
individual elements rather than the aggregate itself):
(\$x :foo) # error
(\@a :foo) # error
(\%h :foo) # error
(*$x :foo) # error
(*@a :foo) # ok - like: my @a: foo; \$a[0] = ...; \$a[1] = ...
(*%h :foo) # ok - like: my %h: foo; \$h{..} = ...; \$h{..} = ...
Note that in Perl 6 and some CPAN signature modules, the 'method' keyword
declares an implicit $self parameter, whose name can be overridden using
a postfix ':':
method foo($x, $y) { $self->{$x} = $y } # implicit $self
method foo($me: $x, $y) { $me->{$x} = $y } # explicit invocant
I have no plans to introduce such a 'method' keyword, but if we did,
we might need different syntax for the invocant, as the ':' would be
interpreted as the start of an attribute unless the toker was clever and
we are very careful that all signature syntax is capable of being
disambiguated.
Thread Previous
|
Thread Next