develooper Front page | perl.perl5.porters | Postings from November 2019

Miscellaneous suggestions

Dave Mitchell
November 28, 2019 17:07
Miscellaneous suggestions
Message ID:
=head2 Synopsis:

    sub foo (
        Dog $spot,       # same as my Dog $spot
        $x ||= $default, # use default value if arg is missing or false
        $x //= $default, # use default value if arg is missing or undef
        $foo?,           # short  for $foo = undef
        \@bar?,          # short  for \@bar = []
        \%baz?,          # short  for \%baz = {}
    ) { ...}

    bar(=$x, =$y);       # short for bar(x => $x, y => $y)

Here are a few random suggestions that people have made at various times
(or that I thought up all by myself!).

=head2 Defined-or

in [perl #132444], Ovid suggested

    sub f($x //= expr) { ... }

which is like

    sub f($x = expr) { ... }

Except that it uses the default expression if the argument is undef as
well as if it is missing.

Presumably we should also have ||= .

=head2 Allow typed variables.

See the big proposal for a constraint system. Part of that proposal is that
the syntactic slot for types (similar to 'my Foo $foo') shouldn't be used
for a constraint (that becomes ($x is Foo) or ($x isa Foo) instead).

So I propose we allow

    sub f(Dog $spot, ...) { ..}

and make it mean exactly mean the same as the currently supported

    my Dog $spot;

which (among other things) allows compile-and runtime checking of
subscripts of hash references. If the semantics of 'my Dog $spot' ever
expand in the future, then the meaning of 'sub f (Dog $spot)' expands in

Placeholder parameters wouldn't be allowed types.

=head2 Allow a shortcut for a 'default' default value

allow $foo? as a shortcut for $foo=undef
  and $?    as a shortcut for $=

Similarly for reference aliases,
    \$s? becomes a shortcut for \$s = undef,
    \@a? becomes a shortcut for \@a = [],
    \%h? becomes a shortcut for \%h = {},

At the same time, ban the existing legal syntax '$=' which means an
optional placeholder, and allow only the new '$?'. This would make things
more consistent, as '$foo=' is currently illegal. Also, I find a bare
trailing equals sign ugly, and it could potentially clash with future
syntax which might be added to the end of a parameter.

Note that ?$foo is a query parameter "borrowing" the next argument, while
$foo? is an optional parameter which is assigned an undef value if no
argument is present.

=head2 Auto-declare $self

Perhaps allow simple syntax to auto-declare $self as the first argument?

In Perl 6, the invocant is implicit in method subs, and can be accessed
using the 'self' keyword:

    method foo ($x) {$x, 'foo') }

but can be explicitly named (note the lack of comma):

    method foo ($me: $x) {  $$x, 'foo') }

Cperl supports a similar auto-declaration with an added 'method' keyword:

    method foo ()           { $self->{foo} }
    method bar ($this:, $x) { $this->{$x}  }

Perl 5 of course doesn't have a 'method' keyword, and if we were to add
it, we would need to decide what semantics it brought to the table.

I don't have any strong urge to add such a feature.

=head2 Allow a code block

Using the general query parameter escape mechanism (which doesn't consume
an argument), perhaps a parameter starting with '?{' could be a code block
which would be executed at that point in the argument processing. E.g. 

    sub foo($x, ?{ print "x=$x\n" }, $y = $x+1) { ... }

(The docs will need to warn that it may affect (as in remove) optimisation
of subsequent parameter processing.)

I suppose the question is, whether this is useful, and whether it allows
you to do things that can't be done with default value expressions, with
the proposed $x //= 0 'undef parameter' handling, and with the proposed
constraint syntax (where/as etc)?

The '?' before the '{' isn't strictly necessary syntax-wise, but grouping
it in with the 'query parameter' syntax emphasises that this parameter
doesn't consume an argument.

=head2 Whitespace

We need to decide where whitespace is allowed or forbidden in things

My feeling (and as expressed in other individual proposals here) is that
everything apart from the sigil and parameter name is signature syntax and
can have optional whitespace around it, like perl stuff generally can.
E.g. both these are allowed:

    Dog\:$foo:shared=0 is Int where$_>0
    Dog \ : $foo : shared = 0 is Int where $_ > 0

Similarly, both of these are ok:

    ? ? $has_x

The remaining issue is whether whitespace is allowed between a sigil and a
parameter name. Perl 5 currently allows:

    my $ x;
    my $

and similarly allows:

    sub f ($ x, $
    { ... }

On the other hand, Perl 6 doesn't allow whitespace. Should we similarly
ban it from Perl 5 signatures? My gut feeling is yes: fix this while still

=head2 Other traits

(This section is just a vague bit of hand-waving.)

The current Constraints proposal defines 4 traits which can follow a
parameter declaration (an attribute and a default value have been included
jn theses examples to demonstrate where traits fit in with them):

    $x :shared = 0 where ...
    $x :shared = 0 as    ...
    $x :shared = 0 isa   ...
    $x :shared = 0 is    ...

Should we in some fashion allow additional user/pragma defined traits?
E.g. 'does', 'has' etc? I have absolutely no idea of how they could be
hooked in (or even whether they could), or how useful they would be, or
what they (in general terms) would do.

Also, is the existing attribute mechanism sufficient instead? The main
differences are that:
  1. Attributes take simple q()-quoted strings as their argument, and
     are called immediately after the parameter lexical variable has been
     created but before the argument has been processed and bound to the
  2. The currently proposed constraint traits are processed after argument
     and/or default value binding, and what follows them is general perl
     syntax, at a precedence such that only a ',', ')' or another trait
     can terminate them. In addition, the complete collection of trait
     code is enclosed in a logical scope where $_ has been initially
     aliased to the parameter variable. Presumably custom traits would
     follow a similar pattern.

=head2 Order of features within a parameter declaration

I propose the following order:

    ?                 Optional start of query parameter
    ?                 Optional start of boolean query parameter (??$x)
    Int               Optional type
    '\' or '*'        Aliasing
    :                 Named parameter
    [$@%]foo          Sigil with optional parameter name
    !                 Optional "croak if undef"
    :foo(...)         Optional attribute(s)
    ?                 'default' default value (instead of default value below)
    = ....            Default value
    where/as/isa/is ... Constraint

=head2 Duplicate parameter names should be an error

At the moment, this just gives a warning:

    sub f ($a,$a) { ... }

    "my" variable $a masks earlier declaration in same scope

I think it should croak instead. (p5hack agreed).

=head2 Signature introspection API.

It has been suggested that  there should be a Signature Introspection API
(possibly via a CPAN XS module) which say, given a code ref, allows perl
code to return information about the sub's signature declaration.

Should perl supply such an API? Failing that, should perl make it easy
(e.g. by guaranteeing a stable optree layout) for a 3rd party to provide
such an API? Or should we declare that this is A Bad Thing - that the
signature is private implementation detail of a sub which it's free to
change, and that external code inspecting is wrong. In which case we would
offer no support or guarantees to anything attempting to implement such an

IIRC Aaron Crane has been championing this, and that in a moment of
weakness I may have encouraged him (or at least not discouraged him).
Now from a more sober standpoint, I'm reverting to my usual gut feeling
that we shouldn't provide guarantees about opcodes etc.

=head2 Caller parameter name auto-generation

(This isn't strictly speaking a proposal about signatures.)

When passing named parameters, you often end up passing both a name and
a variable with that same name:

    sub foo(:$x, :$y) { print $x + $y }

    my ($x, $y) = ....;
    foo(x => $x, y => $y); # 'x' and 'y' appear twice in the source

Perl 6 has a bit of syntactic sugar which allows you to avoid repeating

    foo(:$x, :$y);

is short for

    foo(x => $x, y => $y)

It would be nice if Perl 5 provided a similar syntax. In fact this
wouldn't just apply to sub calls, it could be used anywhere in list
context, e.g.

    %hash = (:$x, :$y);

It would be a compile-time error in void/scalar context. Unknown context
would be treated as list context, so e.g. these

    return :$y;
    return :$x, :$y;

would be compiled respectively as

    return y => $y;
    return x => $x,  y => $y;

and if that sub was called in scalar context, the sub would return just
the last element, ie. $y.

Of course, the specific syntax ':$x' wont work in Perl 5, as it's seen as
part of a ? : conditional. In fact most punctuation characters appearing
before a sigil already have some sort of meaning in Perl 5. These appear
to be free still (at least in the context of when a term is expected):


A second possibility is some sort of punctuation char between the sigil
and variable name, e.g. $*foo. Most of the time this currently gets parsed
as a special punctuation variable followed immediately by a barewword.
Possibly the lexer's behaviour could be changed so that a specific
punctuation var followed immediately by a bareword would be treated
specially. This then gives lots of possibilities, e.g.


etc. However, personally I prefer the special char being before the sigil,
and of the four listed above I think I prefer '='. So that's

    foo(=$x, =$y);
    %points = (=$x, =$y);


Whitespace should be allowed:

    @points = (= $x, = $y);

Note that it would be a parse error for '=' to precede anything other than
a plain scalar lexical or package variable name. So these are legal:

    = $foo
    = $1
    = ${^FOO} # same as "^FOO" => ${^FOO} # or should this be illegal?
    = $Foo::Bar                           # or should this be illegal?

while these are illegal:

    = @foo
    = $foo[1]

Although arguably


could be shorthand for

    foo => \@foo
    foo => \%foo

(I'm not entirely convinced, though). Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About