Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parameter predicates in signatures #16245

Open
p5pRT opened this issue Nov 14, 2017 · 17 comments
Open

parameter predicates in signatures #16245

p5pRT opened this issue Nov 14, 2017 · 17 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 14, 2017

Migrated from rt.perl.org#132444 (status was 'open')

Searchable as RT132444$

@p5pRT
Copy link
Author

p5pRT commented Nov 14, 2017

From zefram@fysh.org

Created by zefram@fysh.org

Signatures as they currently exist are conspicuously missing the
feature of parameter predicates, that is, additional variables that get
a truth value to indicate whether an optional parameter was supplied.
Default values are sufficient for the majority of optional parameters,
but a substantial minority are not adequately characterised by any
default and need an explicit predicate value. Currently these cases
can be served by falling back to direct use of @​_, but a design goal
for signatures was that it should be possible for them to replace all
use of @​_. Parameter predicates are necessary to achieve that goal,
and are the last feature required for it.

The original purple_signatures branch had an implementation of parameter
predicates. That part was never merged to blead, however, because it
was not necessary in order to achieve the minimum deliverable product
for the initial 5.20 release, time was short, and we didn't have a clear
consensus on the syntax. The purple_signatures syntax remains an option
for this feature.

We should probably require that parameter predicates be implemented as a
prerequisite of declaring signatures stable. To that end, the signatures
experiment ticket [perl #121481] should depend on this ticket for the
time being. The dependence could be broken later, but that should only
be by an explicit decision to declare signatures complete enough without
this feature.

Perl Info

Flags:
    category=core
    severity=wishlist

Site configuration information for perl 5.27.5:

Configured by zefram at Fri Oct 20 23:24:00 BST 2017.

Summary of my perl5 (revision 5 version 27 subversion 5) configuration:
   
  Platform:
    osname=linux
    osvers=3.16.0-4-amd64
    archname=x86_64-linux-thread-multi
    uname='linux barba.rous.org 3.16.0-4-amd64 #1 smp debian 3.16.43-2+deb8u2 (2017-06-26) x86_64 gnulinux '
    config_args='-des -Dprefix=/home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52 -Duselargefiles -Dusethreads -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dusedevel -Uversiononly -Ui_db'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
    optimize='-O2'
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='4.9.2'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags =' -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
    libs=-lpthread -lnsl -ldb -ldl -lm -lcrypt -lutil -lc
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.19.so
    so=so
    useshrplib=true
    libperl=libperl.so
    gnulibc_version='2.19'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E -Wl,-rpath,/home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/5.27.5/x86_64-linux-thread-multi/CORE'
    cccdlflags='-fPIC'
    lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'



@INC for perl 5.27.5:
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/site_perl/5.27.5/x86_64-linux-thread-multi
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/site_perl/5.27.5
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/5.27.5/x86_64-linux-thread-multi
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/5.27.5


Environment for perl 5.27.5:
    HOME=/home/zefram
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/bin:/home/zefram/usr/perl/util:/home/zefram/pub/x86_64-unknown-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/bin:/usr/local/bin:/usr/games
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Nov 20, 2017

From @xsawyerx

On Tue, 14 Nov 2017 07​:21​:25 -0800, zefram@​fysh.org wrote​:

This is a bug report for perl from zefram@​fysh.org,
generated with the help of perlbug 1.40 running under perl 5.27.5.

-----------------------------------------------------------------
[Please describe your issue here]

Signatures as they currently exist are conspicuously missing the
feature of parameter predicates, that is, additional variables that
get
a truth value to indicate whether an optional parameter was supplied.
Default values are sufficient for the majority of optional parameters,
but a substantial minority are not adequately characterised by any
default and need an explicit predicate value. Currently these cases
can be served by falling back to direct use of @​_, but a design goal
for signatures was that it should be possible for them to replace all
use of @​_. Parameter predicates are necessary to achieve that goal,
and are the last feature required for it.

The original purple_signatures branch had an implementation of
parameter
predicates. That part was never merged to blead, however, because it
was not necessary in order to achieve the minimum deliverable product
for the initial 5.20 release, time was short, and we didn't have a
clear
consensus on the syntax. The purple_signatures syntax remains an
option
for this feature.

We should probably require that parameter predicates be implemented as
a
prerequisite of declaring signatures stable. To that end, the
signatures
experiment ticket [perl #121481] should depend on this ticket for the
time being. The dependence could be broken later, but that should
only
be by an explicit decision to declare signatures complete enough
without
this feature.

We discussed this at length at the core hackathon with no exact decision on how to implement this.

One suggestion was the following syntax​:

  sub abc ( $foo?, ?$is_foo) {
  $foo = do {...} unless $is_foo;
  }

Another (which was not happily received) was​:

  sub foo ($x, $y ? $is_y) {
  $y = $x unless $is_y;
  }

Yves suggested having another value (like PL_sv_undef) but that used for predicates, to differentiate a value not sent and a value sent as undef.

@p5pRT
Copy link
Author

p5pRT commented Nov 20, 2017

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Nov 20, 2017

From zefram@fysh.org

Sawyer X via RT wrote​:

One suggestion was the following syntax​:

sub abc ( $foo?, ?$is_foo) {

What is the "?" suffix on "$foo" about? We already have the "= undef"
syntax for optional parameters.

   $foo = do \{\.\.\.\} unless $is\_foo;

If that's all you're doing with a parameter predicate, it's better
written in the signature as "($foo = do {...})". Parameter predicates
are for the minority of cases that aren't adequately characterised as
a default value (even a dynamically computed one).

Another (which was not happily received) was​:

sub foo ($x, $y ? $is_y) {

You still need a default value expression. If the intent is that
"? $is_y" implies some default default value expression, then there
should still be a syntax for an optional default value expression.

I have a concern about incorporating the parameter predicate into the
same signature item as the primary parameter, which is that if we later
have a plugin mechanism for signature items then everyone implementing
some plugged-in kind of optional parameter will also have to implement
parameter predicates, duplicating core logic. If parameter predicates
are separate signature items, then they can naturally be applied
to any optional parameter. That's why I originally designed the
purple-signatures parameter predicates as separate signature items.

Apart from that non-fatal disadvantage, I'd be fine with something
like "($x, $y ? $is_y = $x)". Maybe also with "($y ? $is_y)" implying
"= undef", though I don't favour it.

Yves suggested having another value (like PL_sv_undef) but that used for
predicates, to differentiate a value not sent and a value sent as undef.

And how would we distinguish an argument being passed with that special
value from the argument not being passed? None of the possible answers
to that are remotely palatable.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From @demerphq

On 20 Nov 2017 13​:24, "Zefram" <zefram@​fysh.org> wrote​:

Sawyer X via RT wrote​:

One suggestion was the following syntax​:

sub abc ( $foo?, ?$is_foo) {

What is the "?" suffix on "$foo" about? We already have the "= undef"
syntax for optional parameters.

People want to distinguish no value passed from a default undef.

The idea was that the ? at the back of the first var allows the next var to
start with a ? and if so, be a flag which is set to true is the parameter
foo was passed.

   $foo = do \{\.\.\.\} unless $is\_foo;

If that's all you're doing with a parameter predicate, it's better
written in the signature as "($foo = do {...})". Parameter predicates
are for the minority of cases that aren't adequately characterised as
a default value (even a dynamically computed one).

Another (which was not happily received) was​:

sub foo ($x, $y ? $is_y) {

You still need a default value expression. If the intent is that
"? $is_y" implies some default default value expression, then there
should still be a syntax for an optional default value expression

This is a variant of the previous idea, $y ? $is_y means, the ? signals
that the argument $y is optional, has no default, but if it has been
provided is_y should be set to true.

Again, this is to distinguish no-value passed from a default undef.

I have a concern about incorporating the parameter predicate into the
same signature item as the primary parameter, which is that if we later
have a plugin mechanism for signature items then everyone implementing
some plugged-in kind of optional parameter will also have to implement
parameter predicates, duplicating core logic. If parameter predicates
are separate signature items, then they can naturally be applied
to any optional parameter. That's why I originally designed the
purple-signatures parameter predicates as separate signature items.

Apart from that non-fatal disadvantage, I'd be fine with something
like "($x, $y ? $is_y = $x)". Maybe also with "($y ? $is_y)" implying
"= undef", though I don't favour it.

Yves suggested having another value (like PL_sv_undef) but that used for
predicates, to differentiate a value not sent and a value sent as undef.

And how would we distinguish an argument being passed with that special
value from the argument not being passed? None of the possible answers
to that are remotely palatable

Well, I dunno. This is a variant of the semipredicate problem​: We want to
distinguish no-argument from the set of valid defaults or provided
arguments.

Lets assume we do not use any of these flag-based solutions, how would we
do this?

Answer​: the same way you solve any semipredicate problem​: use a unique
value that can only end up in an argument if it was the default.

{
  my $no_value;
  sub foo($x=\$no_value) {
  if ($x and ref $x and $x==\$no_value) {
  say "no value provided"
  } else {
  say "got a value​:$x"
  }
  }
}

So now there is no way a caller provided value can be mistaken for the
no-value parameter (provided the ref to $no_value cannot "escape" the
closure).

All I was thinking of was a standardized way to implement this pattern.
Some kind of "undef" that has a special property that we can tell it from a
true undef. Maybe magic that works such that once ANY operation is
performed on the var the "nothingness" goes away, but that a special
function could "see through" (while at the same time resetting the magic).

So you could so something like this​:

  sub foo($x?) {
  if (is_nothing($x)) { # at this point is_nothing($x) would no longer
be true
  say "no value provided"
  } else {
  say "got a value​:$x"
  }
  }

maybe the magic would know what sub it came from, and when is_nothing($x)
was called would validate that the current sub matched. Etc.... Anyway, I
can see this is a rabit-hole.

Frankly, I /personally/ don't see a need to support this in the signature
syntax explicitly as this pattern for solving the semipredicate problem is
well known to me. On the other hand, if our community is desperate for a
different way to solve this problem then all I can say is I would prefer
almost any other solution than having these flag variables. No other
language needs this, why should Perl?

cheers,
Yves

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From zefram@fysh.org

demerphq wrote​:

People want to distinguish no value passed from a default undef.

The parameter variable will still get some value, if the argument wasn't
passed. That is, it has a default value (whether undef or anything else).
We could in theory avoid assigning a (visible) default value by making all
access to $foo croak, but that would require an extra conditional in all
padsv ops, so I'm assuming we wouldn't do that. Distinguishing between
no value passed and the parameter variable's default value is the very
purpose of parameter predicate variables.

The idea was that the ? at the back of the first var allows the next var to
start with a ? and if so, be a flag which is set to true is the parameter
foo was passed.

So the effect of the "?" on the primary parameter variable is merely
to mark it as an optional parameter, without explicitly stating its
default value. So assuming the actual default value is undef, the
"?" is precisely equivalent to "= undef". You're not clear about whether
a predicate item would be permitted after an optional parameter with
explicit default, but I don't see why we'd forbid that. What's left?
A stylistic distinction between "?" and "= undef"? The presence of the
predicate item seems enough distinction to me.

This is a variant of the previous idea, $y ? $is_y means, the ? signals
that the argument $y is optional, has no default,

Again, $y would actually have some default value.

And how would we distinguish an argument being passed with that special
value from the argument not being passed?

Well, I dunno.

Right, we can drop that idea then.

       Maybe magic that works such that once ANY operation is

performed on the var the "nothingness" goes away, but that a special
function could "see through" (while at the same time resetting the magic).

That sort of idea was raised in the old "acceptable signatures" thread,
where it was spelled "exists($x)" or "defaulted($x)" or "$(x?)".
It overloads the concept of the lexical variable, giving it state that
isn't adequately referenced by the ordinary "$x".

                                                     I would prefer

almost any other solution than having these flag variables. No other
language needs this, why should Perl?

That canard again. We're not designing signatures for other languages,
we're designing them for Perl. Perl is not your other language of choice,
and there is no a priori reason why Perl's features should look the same
as the features of that other language.

Quick comparisons​:

* C doesn't need parameter predicates because it puts the burden of
  identifying the end of the argument list entirely on the programmer of
  the callee​: run off the end of the argument list (or get an argument
  type wrong) and you invoke undefined behaviour. In fact those aren't
  really named parameters, as seen by the callee, so it's dubious to
  say that C supports optional parameters at all.

* Most versions of Lisp (pretty much any that support named optional
  parameters as a lambda list feature) *do* support explicit parameter
  predicates. They recognise the need for such a feature, and satisfy
  that need.

* Bourne shell doesn't support naming of parameters to shell functions,
  so we couldn't really expect it to support naming parameter predicates.
  But it does provide the ability to detect the presence of a parameter
  in a manner coherent with the way parameters are referenced,
  "${2+supplied}" for the "$2" parameter. Essentially, there's an
  `unset' state for shell variables which is distinguishable from all
  values that can be passed to shell functions. If that is viewed as a
  value that a variable can hold, then it sucks that that value can't
  be passed to functions. It only makes sense with the understanding
  that shell functions are imitating external commands, and so only
  take a Unix-style argv[]. Perl's functions are not so restricted,
  because Perl was always intended as an actual programming language.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From @Smylers

Zefram writes​:

Quick comparisons​:

* C ... it's dubious to say that C supports optional parameters at
all.

* Most versions of Lisp (pretty much any that support named optional
parameters as a lambda list feature) *do* support explicit parameter
predicates. They recognise the need for such a feature, and satisfy
that need.

* Bourne shell doesn't support naming of parameters to shell functions,
so we couldn't really expect it to support naming parameter predicates.
But it does provide the ability to detect the presence of a parameter
in a manner coherent with the way parameters are referenced,

• PHP has the func_num_args() function, which returns the equivalent
  of scalar @​_​: you get to know how many arguments were actually
  supplied, so can work out whether that was enough to include any
  specific optional argument.

  That has the advantages of not requiring any special syntax in
  signatures, nor always initializing a special variable which is rarely
  needed.
 
  It has the disadvantages of placing the cognitive load on the
  programmer of keeping track of which optional argument has which
  position number, and that it can't be adapted to named arguments;
  should signatures ever be extended that way, a different mechanism
  would be required for indicating their absence.

Smylers

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From @demerphq

On 21 November 2017 at 13​:52, Zefram <zefram@​fysh.org> wrote​:

demerphq wrote​:

People want to distinguish no value passed from a default undef.

The parameter variable will still get some value, if the argument wasn't
passed. That is, it has a default value (whether undef or anything else).
We could in theory avoid assigning a (visible) default value by making all
access to $foo croak, but that would require an extra conditional in all
padsv ops, so I'm assuming we wouldn't do that. Distinguishing between
no value passed and the parameter variable's default value is the very
purpose of parameter predicate variables.

The idea was that the ? at the back of the first var allows the next var to
start with a ? and if so, be a flag which is set to true is the parameter
foo was passed.

So the effect of the "?" on the primary parameter variable is merely
to mark it as an optional parameter, without explicitly stating its
default value. So assuming the actual default value is undef, the
"?" is precisely equivalent to "= undef". You're not clear about whether
a predicate item would be permitted after an optional parameter with
explicit default, but I don't see why we'd forbid that. What's left?
A stylistic distinction between "?" and "= undef"? The presence of the
predicate item seems enough distinction to me.

I am getting a bit tired of explaining things that other people want,
but my understanding of the conversation was that it was felt that we
dont want to pay the cost of tracking what args are passed unless
someone actually needs that functionality.

So the idea was that the ? style syntaxes would tell Perl that it is needed.

This is a variant of the previous idea, $y ? $is_y means, the ? signals
that the argument $y is optional, has no default,

Again, $y would actually have some default value.

Again, this isnt my argument. I am explaining what other people said.

And how would we distinguish an argument being passed with that special
value from the argument not being passed?

Well, I dunno.

Right, we can drop that idea then.

This sarcasm is unnecessary and unwelcome.

       Maybe magic that works such that once ANY operation is

performed on the var the "nothingness" goes away, but that a special
function could "see through" (while at the same time resetting the magic).

That sort of idea was raised in the old "acceptable signatures" thread,
where it was spelled "exists($x)" or "defaulted($x)" or "$(x?)".
It overloads the concept of the lexical variable, giving it state that
isn't adequately referenced by the ordinary "$x".

Sure.

                                                     I would prefer

almost any other solution than having these flag variables. No other
language needs this, why should Perl?

That canard again.

I dont find that very respectful Zefram, especially considering I am
just trying to help, and really don't care what we do here.

A canard is defined as "an unfounded rumour or story".

My opinion on whether Perl should not egregiously deviate from
programming norms is neither a rumour nor a story, nor is it
unfounded.

We're not designing signatures for other languages,
we're designing them for Perl. Perl is not your other language of choice,
and there is no a priori reason why Perl's features should look the same
as the features of that other language.

I understand your view, and I even respect it. But it would be nice to
see some sign that respect is reciprocated.

Quick comparisons​:

* C doesn't need parameter predicates because it puts the burden of
identifying the end of the argument list entirely on the programmer of
the callee​: run off the end of the argument list (or get an argument
type wrong) and you invoke undefined behaviour. In fact those aren't
really named parameters, as seen by the callee, so it's dubious to
say that C supports optional parameters at all.

* Most versions of Lisp (pretty much any that support named optional
parameters as a lambda list feature) *do* support explicit parameter
predicates. They recognise the need for such a feature, and satisfy
that need.

This is a good argument. But not that compelling to me. I dont think
that many programmers know Lisp these days.

* Bourne shell doesn't support naming of parameters to shell functions,
so we couldn't really expect it to support naming parameter predicates.
But it does provide the ability to detect the presence of a parameter
in a manner coherent with the way parameters are referenced,
"${2+supplied}" for the "$2" parameter. Essentially, there's an
`unset' state for shell variables which is distinguishable from all
values that can be passed to shell functions. If that is viewed as a
value that a variable can hold, then it sucks that that value can't
be passed to functions. It only makes sense with the understanding
that shell functions are imitating external commands, and so only
take a Unix-style argv[]. Perl's functions are not so restricted,
because Perl was always intended as an actual programming language.

Like I said, I don't care what we do beyond a general aesthetic
distaste for these flags. I can do what I want with or without them.

So do what you want, I am out of this discussion now.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From zefram@fysh.org

demerphq wrote​:

I am getting a bit tired of explaining things that other people want,

I, too, would rather have the idea from someone who actually wants it,
so that we can properly debate it. You certainly shouldn't feel any
obligation to defend anyone else's idea.

but my understanding of the conversation was that it was felt that we
dont want to pay the cost of tracking what args are passed unless
someone actually needs that functionality.

So the idea was that the ? style syntaxes would tell Perl that it is needed.

The parameter predicate item itself serves to signal that the information
is needed. Not that there's really an avoidable cost​: internally perl
tracks how many arguments were passed in any case.

This sounds rather as though we're debating something that got mangled en
route to this thread, rather than something that was actually proposed.
Again, it would be good for someone who actually favours whatever this
is based on to make the case for it here.

Right, we can drop that idea then.

This sarcasm is unnecessary and unwelcome.

That's not sarcasm. If there's no actual proposal there then there is
nothing to debate. (I was, however, under the impression that you were
the person proposing this class of mechanism. Given that you're not,
we still don't have anything to debate, but that now doesn't imply any
fault on your part.)

My opinion on whether Perl should not egregiously deviate from
programming norms

That's a more nuanced position that was implied by the blanket statement
about all other languages. I'm happy to examine the designs of other
languages to see what lessons can be gleaned from them, and I'm OK with
a principle that Perl should imitate when there's no stronger reason to
design in a particular way. But we get problems when people deny that
Perl has any reason to differ from other languages.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From @xsawyerx

Let me pause things right here, if I may.

I am afraid Yves is here because of me. While we were discussing
signatures, Todd Rinaldo expressed the need for making a distinction
between "parameter sent as undef" and "parameter was not sent." This is
something that Moose provides, for example, and it is something he
considered useful for his code.

Yves was at the discussion and offered his suggestion on how one might
accomplish this. I have relayed the suggestions with Yves' name dropped
without clarifying it was a suggestion on his behalf to solve someone
else's problem.

Given time, I'm sure Todd would fill in the blanks on his need so they
may be discussed as valid needs in order to move towards how they might
be accomplished. To be fair, none of us were happy with all the
different solutions we came up with, so no one will argue that any of
these are "pretty". :)

On 11/21/2017 03​:56 PM, Zefram wrote​:

demerphq wrote​:

I am getting a bit tired of explaining things that other people want,
I, too, would rather have the idea from someone who actually wants it,
so that we can properly debate it. You certainly shouldn't feel any
obligation to defend anyone else's idea.

but my understanding of the conversation was that it was felt that we
dont want to pay the cost of tracking what args are passed unless
someone actually needs that functionality.

So the idea was that the ? style syntaxes would tell Perl that it is needed.
The parameter predicate item itself serves to signal that the information
is needed. Not that there's really an avoidable cost​: internally perl
tracks how many arguments were passed in any case.

This sounds rather as though we're debating something that got mangled en
route to this thread, rather than something that was actually proposed.
Again, it would be good for someone who actually favours whatever this
is based on to make the case for it here.

Right, we can drop that idea then.
This sarcasm is unnecessary and unwelcome.
That's not sarcasm. If there's no actual proposal there then there is
nothing to debate. (I was, however, under the impression that you were
the person proposing this class of mechanism. Given that you're not,
we still don't have anything to debate, but that now doesn't imply any
fault on your part.)

My opinion on whether Perl should not egregiously deviate from
programming norms
That's a more nuanced position that was implied by the blanket statement
about all other languages. I'm happy to examine the designs of other
languages to see what lessons can be gleaned from them, and I'm OK with
a principle that Perl should imitate when there's no stronger reason to
design in a particular way. But we get problems when people deny that
Perl has any reason to differ from other languages.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From curtis_ovid_poe@yahoo.com

If I may jump in​:
If an undef parameter is sent, I'd love to be able to handle that with​:
    sub foo ($bar //= 1) { ... }
Also, please provide the subname in the error message. There are many ways I can get an error message and be unclear about what sub we're talking about. (Template Toolkit is a great example. Line directives and eval are others). Having the subname in the error message means I can quickly find the offender.
Cheers,Ovid-- IT consulting, training, specializing in Perl, databases, and agile developmenthttp​://www.allaroundtheworld.fr/. 
Buy my book! - http​://bit.ly/beginning_perl

  On Tuesday, 21 November 2017, 16​:08​:30 CET, Sawyer X <xsawyerx@​gmail.com> wrote​:

Let me pause things right here, if I may.

I am afraid Yves is here because of me. While we were discussing
signatures, Todd Rinaldo expressed the need for making a distinction
between "parameter sent as undef" and "parameter was not sent." This is
something that Moose provides, for example, and it is something he
considered useful for his code.

Yves was at the discussion and offered his suggestion on how one might
accomplish this. I have relayed the suggestions with Yves' name dropped
without clarifying it was a suggestion on his behalf to solve someone
else's problem.

Given time, I'm sure Todd would fill in the blanks on his need so they
may be discussed as valid needs in order to move towards how they might
be accomplished. To be fair, none of us were happy with all the
different solutions we came up with, so no one will argue that any of
these are "pretty". :)

On 11/21/2017 03​:56 PM, Zefram wrote​:

demerphq wrote​:

I am getting a bit tired of explaining things that other people want,
I, too, would rather have the idea from someone who actually wants it,
so that we can properly debate it.  You certainly shouldn't feel any
obligation to defend anyone else's idea.

but my understanding of the conversation was that it was felt that we
dont want to pay the cost of tracking what args are passed unless
someone actually needs that  functionality.

So the idea was that the ? style syntaxes would tell Perl that it is needed.
The parameter predicate item itself serves to signal that the information
is needed.  Not that there's really an avoidable cost​: internally perl
tracks how many arguments were passed in any case.

This sounds rather as though we're debating something that got mangled en
route to this thread, rather than something that was actually proposed.
Again, it would be good for someone who actually favours whatever this
is based on to make the case for it here.

Right, we can drop that idea then.
This sarcasm is unnecessary and unwelcome.
That's not sarcasm.  If there's no actual proposal there then there is
nothing to debate.  (I was, however, under the impression that you were
the person proposing this class of mechanism.  Given that you're not,
we still don't have anything to debate, but that now doesn't imply any
fault on your part.)

My opinion on whether Perl should not egregiously deviate from
programming norms
That's a more nuanced position that was implied by the blanket statement
about all other languages.  I'm happy to examine the designs of other
languages to see what lessons can be gleaned from them, and I'm OK with
a principle that Perl should imitate when there's no stronger reason to
design in a particular way.  But we get problems when people deny that
Perl has any reason to differ from other languages.

-zefram
 

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From zefram@fysh.org

Ovid via perl5-porters wrote​:

If I may jump in​:
If an undef parameter is sent, I'd love to be able to handle that with​:
sub foo ($bar //= 1) { ... }

That is a very different situation from that with which this ticket
is concerned. By all means open a separate ticket with your suggestion.

Also, please provide the subname in the error message.

This too should go in its own ticket.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Nov 21, 2017

From @xsawyerx

On 11/21/2017 06​:38 PM, Zefram wrote​:

Ovid via perl5-porters wrote​:

If I may jump in​:
If an undef parameter is sent, I'd love to be able to handle that with​:
sub foo ($bar //= 1) { ... }
That is a very different situation from that with which this ticket
is concerned. By all means open a separate ticket with your suggestion.

Ovid, I don't think this approaches the situation here. I think we're
trying to address whether it is important to identify the following
different calls​:

foo();
foo( 'bar' => undef );

In the first, $bar will have a default or undef (depending on signature)
but in the latter you will not know whether someone sent 'bar', unless
we provided a non-undef default.

Also, please provide the subname in the error message.
This too should go in its own ticket.

Ovid, could you please open an issue for this? I think it's important
and would like us to prioritize it.

@p5pRT
Copy link
Author

p5pRT commented Nov 29, 2017

From @rjbs

* Sawyer X via RT <perlbug-followup@​perl.org> [2017-11-20T06​:44​:50]

Signatures as they currently exist are conspicuously missing the feature of
parameter predicates, that is, additional variables that get a truth value
to indicate whether an optional parameter was supplied.

My suggestion at the time was, and remains now, to provide argc in caller.
(It'd be great to use this as an excuse for making caller return an object more
often, but we can live without that.)

The "was $x provided" is rarely needed, and checking argc is simple, out of the
way, but not obscure or weird. It also requires no new syntax.

The down side is needing to update the positions numbers used in checking argc.
I think it's fine. We're making the unlikely case possible, we don't need to
make it slick.

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2017

From zefram@fysh.org

Ricardo Signes wrote​:

My suggestion at the time was, and remains now, to provide argc in caller.

This would suck, for several reasons. The more important reasons
are about using argc as a way to check for parameters being supplied.
A secondary issue is that caller() is a poor place to provide it.

Firstly, checking argc is an annoying way of doing this job. This isn't
the 1970s. We've got signatures in the first place partly because it's
annoying to refer to parameters by index, which of course we're free to
do in @​_. Naming parameters is a superior way of referring to them, and
that applies to parameter predicates just as much as to parameter values.
This is particularly relevant when parameters change index through edits.

Also, all of the proposed means of accessing argc decouple the argc
value from the named parameters. What I mean by that is that they
access the argc for some call identified by the dynamic environment in
which argc is being accessed, rather than the call that established
the lexical variables in which parameter values are found. This is
an issue if part of the subroutine's code is inside a closure, which
inherits the lexical parameter variables but has its own dynamic call
state, or if the subroutine calls another subroutine to which it wants
to explicitly pass parameter variables. This could be addressed by
providing a lexical argc variable, set up by the signature in response
to some new signature syntax requesting it, but that doesn't seem any
gain over actual parameter predicates.

But even if we're happy with a decoupled argc as a means of determining
which parameters were passed, doing it this way would mean that the
signature system remains materially incomplete, as a means of accessing
parameters. It's a cop-out​: "if you're doing anything tricky you
have to use this other mechanism instead". Although it's not strictly
necessary for signatures to handle these cases, because Perl does have
other mechanisms (starting with the existing @​_), that's the same sense
in which we don't need signatures at all.

The intention with signatures always appeared to be that they should
ultimately (albeit not in the first experimental version) be a complete
interface to parameters. It should in particular be possible to use
them in all the places that currently use @​_​: the programmer should
have a free choice between these two styles of access to parameters.
This intention is attested by the multiple debates we had about the
enablement of signatures potentially suppressing the setup of @​_.
We decided against making that link, but not by reason of rejecting the
notion that signatures could serve as a complete substitute for @​_.
The reasoning was about not forcing programmers to make the complete
switch in one go. (Getting argc from caller() rather than from @​_
doesn't invalidate the intent that signatures be a complete feature.)

This concept of feature completeness does not lead to adding an unlimited
number of features to signatures. Parameter predicates are necessary *and
sufficient* to achieve completeness with respect to rvalue parameters.
Look, for example, at how lambda lists have evolved in the Lisp world,
where early on several features were added in quick succession,
but they then settled down on a feature set pretty close to what
we'd have if we just added parameter predicates to what we have now.
(See <http​://www.lispworks.com/documentation/lw60/CLHS/Body/03_da.htm>
for the Common Lisp definition; Common Lisp is a large Lisp with a lot
of historical artifacts.) The fact that Perl can have lvalue parameters
means that we require one more feature beyond rvalue parameters, namely
aliasing, but again that's just the one feature (and it's only half of
[perl #132472]).

As for caller() as the place to get argc, it's a sensible place to acquire
sub call parameters for stack tracing, but it's a bit too decoupled from
the actual call to use for semantic purposes. The ability to override
it with a CORE​::GLOBAL​::caller() does not play nicely with this kind
of usage. If we really want dynamic access to argc, the place to get it
is either from @​_, which has the same pros and cons as other uses of @​_,
or from a new op with a new keyword. There's independent motivation for
such new ops for parameter access, which we've discussed in the context
of suppressing @​_.

The "was $x provided" is rarely needed,

It's not that rare. I found that 20% of my optional parameters needed
such a predicate. By "need" here I mean that they cannot be satisfied
by the use of a default value expression. It is not at all unusual in
Perl to define subroutines such that they do slightly different jobs
depending on which parameters were supplied, not just the same job with
a default parameter value.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 1, 2017

From @demerphq

On 30 November 2017 at 18​:58, Zefram <zefram@​fysh.org> wrote​:

The "was $x provided" is rarely needed,

It's not that rare. I found that 20% of my optional parameters needed
such a predicate. By "need" here I mean that they cannot be satisfied
by the use of a default value expression. It is not at all unusual in
Perl to define subroutines such that they do slightly different jobs
depending on which parameters were supplied, not just the same job with
a default parameter value.

I've never encountered this problem in a way it couldn't be solved
using the standard techniques for solving the empty predicate problem.

Just my $0.02 cents.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Oct 15, 2019

From @leonerd

Another potentially simple workaround​:

$ perl -E \
  'use feature "signatures";
  sub f($x = (my $x_was_default = 1, "default"))
  { say "$x but $x_was_default" }

  f();
  f("other");'

  The signatures feature is experimental at -e line 1.
  default but 1
  other but

--
Paul "LeoNerd" Evans

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants