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

Re: Miscellaneous suggestions

Thread Previous | Thread Next
From:
Zefram via perl5-porters
Date:
December 2, 2019 17:35
Subject:
Re: Miscellaneous suggestions
Message ID:
20191202173504.hznk5y4wj7zonhgg@fysh.org
Dave Mitchell wrote:
>    sub f($x //= expr) { ... }

I'm dubious about that.  It's implying that, after $x has been initialised
from the argument, "$x //= expr" is performed.  The problem with that is
that it suggests that other kinds of assignment should work similarly:
not only "||=", but consider "sub f($x *= 2) {...}".  This could be
implemented just fine: initialise $x from the argument, and then perform
"$x *= 2" so that the body sees twice the argument value.  But then that
implies semantics for "sub f($x = expr) {...}" that are very different
from what we've already decided on.  I think if "//=" is going to be
allowed here then the defaulting "=" has to change to "!!=" or some such.

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

Meh.  I suppose if attributes are supported then this should be supported
too.

In the spirit of matching the "my" usage, the type should always be
adjacent to the specification of the lexical variable.  Thus "*Dog $spot",
not "Dog *$spot".

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

Meh.  I'm generally not a fan of these shortcuts.

>  and $?    as a shortcut for $=

If "$foo?" is allowed then "$?" certainly should be, but "$=" seems
short enough already.

>    \$s? becomes a shortcut for \$s = undef,

Presumably you mean "\$s = \undef"; "\$s = undef" would signal an error
in the default case.

>    \@a? becomes a shortcut for \@a = [],
>    \%h? becomes a shortcut for \%h = {},

Defaulting to empty aggregates, sure, but fresh mutable ones?  To parallel
the scalar default they should alias *im*mutable empty aggregates.
Probably always the same immutable array and the same immutable hash.

If there's serious doubt about what the "?" defaults should be, then the
"?" shorthand clearly isn't going to work.

>At the same time, ban the existing legal syntax '$='

I disagree.  This syntax is fine as it is, part of a coherent design.
"=" is consistently used in the syntax for optional parameters.

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

Imposing a specific variable name on the user?

It's a bit difficult to discuss this absent any "method" keyword or
anything else that implies a subroutine taking one or more stereotyped
positional parameters.

>    sub foo($x, ?{ print "x=$x\n" }, $y = $x+1) { ... }
...
>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,

Clearly it can do things that would be awkward otherwise.  For example,
it can munge the value of a parameter variable in arbitrary fashion,
making the munged value visible to expressions associated with setting up
later parameter variables.  Linking to the "//=" discussion above, "($x,
?{ $x //= 5 }, $y = $x+1)" lets one easily achieve the effect proposed
for "($x //= 5, $y = $x+1)", without needing to build in a "//=" operator.

So yes, it's useful, and it reduces the pressure for a bunch of other
features of dubious value.

>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.

It's a bit ugly, but the "query parameter" concept may make up for that.

>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.

Yes, these things should permit whitespace.

>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
>experimental.

No.  Perl 5 permits whitespace between sigil and identifier in all sorts
of non-experimental situations, including of course the non-experimental
"my" syntax for declaring lexical variables.  The signature syntax should
be consistent with the rest of Perl 5.  There is no justification for
importing a Perl 6 syntax rule just for this one case.

>Should we in some fashion allow additional user/pragma defined traits?
>E.g. 'does', 'has' etc?

"does" and "has" sound like additional forms of type constraint, and as
such should be handled as user-defined type constraints.  Preferably by
permitting arbitrary expressions on the rhs of "is", as I discussed in
that subthread.

As for other traits, we don't seem to have any generalised concept of
what traits are for.  Of all the traits you've proposed, one is for
coercion, and all the others are about constraints.  (Except for the bit
where you imagine "is Int" performing both constraint *and* coercion,
which I reckon is a bad idea.)  It would only be meaningful to have a
generalised trait system if there were a generalised way for plugged-in
trait code to do meaningful things.  We kinda already have such a system
with attributes, but it turns out there's very little that attribute code
can meaningfully do.  In Perl 6, trait handlers have a rich metaobject
ecosystem to mess about in; Perl 5 doesn't have anything like that,
so I think a generalised trait system would be at least as useless as
the generalised attribute system.

>I propose the following order:
...
>    Int               Optional type

This should go immediately before the sigilled name, as part of the
declaration of the lexical variable rather than anything to do with
arguments per se.

>    :foo(...)         Optional attribute(s)

This should go immediately after the sigilled name, for the same reason.

>    = ....            Default value
>    where/as/isa/is ... Constraint

This order is appropriate if constrants and coercion apply to default
values.  However, it means that trait keywords screw up expression syntax
in default value expressions, which should be avoided.  If default values
are exempted from constraint checking (as I've suggested), the order
should be swapped.  If traits come before default value then there's
no such syntactic problem: the defaulting "=" is a fine delimiter for
a trait expression, based purely on operator precedence.

>    sub f ($a,$a) { ... }
>
>    "my" variable $a masks earlier declaration in same scope
>
>I think it should croak instead. (p5hack agreed).

I think it should be consistent with other ways of declaring lexical
variables.  The rules should not be different just for signatures.
The programmer is free to make shadowing warnings fatal, and if we think
this is terrible style then we're free to implement a stricture (which
can be part of a Perl-version feature bundle) to make shadowing fatal.

>=head2 Signature introspection API.
...
>Should perl supply such an API?

Introspecting a signature should be exactly as easy (no easier and
no more difficult) than introspecting any other op in a sub's body.
It should absolutely not be promoted as subroutine metadata to be
examined independently from the rest of the body.  It's an internal
implementation detail that should not leak out independent of the rest
of the implementation.  If it is perceived as metadata, there's a danger
that it'll be treated as part of the sub's API, and become something
that isn't allowed to change between module versions.

>    foo(:$x, :$y);
...
>It would be nice if Perl 5 provided a similar syntax.

Yes, a bit.  If such a syntax is added, the named parameter syntax for
the common same-name case should imitate the syntax for this shorthand.

>It would be a compile-time error in void/scalar context.

That sounds like a bad idea.  List expressions are generally permitted in
void and scalar context.  I think this feature should be pure shorthand
for (foo=>$foo).

>Of course, the specific syntax ':$x' wont work in Perl 5, as it's seen as
>part of a ? : conditional.

Yes.  I think it might also clash with some of the other uses of colon.

>                                                            These appear
>to be free still (at least in the context of when a term is expected):
>
>    ^$x
>    =$x
>    >$x
>    .$x

"=" would be problematic because of clashes with POD syntax.  There's
already a bit of a clash, but it only arises where a new paragraph
(as judged for POD purposes) happens in the middle of an expression.
"=$x" would mean that expression syntax can *start* with "=", making it
much easier to mistake code for POD.

Of these options, I have some preference for ">$x", which at least looks
like an abbreviation of "x=>$x".  But all these options are ugly.

>A second possibility is some sort of punctuation char between the sigil
>and variable name, e.g. $*foo.

This is worse, for the reason you outlined.

>    =@foo
>    =%foo

This seems more confusing than it's worth, with the implicit
enreferencement.  On the receiving end of a named parameter, I'd want
the syntax to be "foo => \@foo", to make the aliasing clear, and the
call should be similar.

-zefram

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