Mailing List Archive

//= and ||= in subroutine signatures
With perl v5.38.0 I wrote a code similar to:
perl -E 'sub foo ($x, $y //= 42, $z) {} foo(1, undef, 3)'
and got the error:
Mandatory parameter follows optional parameter at -e line 1, near "$z) "

So //= and ||= mark a parameter as optional, but optional parameters must follow mandatory ones. Outside of signatures these operators check a value of a variable. A mandatory parameter can have undef or false value. If it is feasible, maybe these operators could be applied to mandatory parameters as well.

--
Ivan Vorontsov <ivrntsv@yandex.ru>
Re: //= and ||= in subroutine signatures [ In reply to ]
On Sun, Sep 03, 2023 at 11:48:14AM +0300, Ivan Vorontsov wrote:
> With perl v5.38.0 I wrote a code similar to:
> perl -E 'sub foo ($x, $y //= 42, $z) {} foo(1, undef, 3)'
> and got the error:
> Mandatory parameter follows optional parameter at -e line 1, near "$z) "
>
> So //= and ||= mark a parameter as optional, but optional parameters
> must follow mandatory ones. Outside of signatures these operators check
> a value of a variable. A mandatory parameter can have undef or false
> value. If it is feasible, maybe these operators could be applied to
> mandatory parameters as well.

I don't see how that could work. It makes for an ambiguity.

You could create a parser rule which says that that if a mandatory
parameter follows a ||= parameter, then the ||= should be interpreted as
mandatory and vice versa:

sub f1($x, $y ||= 1, $z) {...} # $y is mandatory
sub f2($x, $y ||= 1, $z = 1) {...} # $y is optional

but then this becomes ambiguous:

sub f3($x, $y ||= 1) {...} # is $y optional or mandatory?

--
Please note that ash-trays are provided for the use of smokers,
whereas the floor is provided for the use of all patrons.
-- Bill Royston
Re: //= and ||= in subroutine signatures [ In reply to ]
On Sun, Sep 3, 2023 at 11:32?AM Dave Mitchell <davem@iabyn.com> wrote:

> On Sun, Sep 03, 2023 at 11:48:14AM +0300, Ivan Vorontsov wrote:
> > With perl v5.38.0 I wrote a code similar to:
> > perl -E 'sub foo ($x, $y //= 42, $z) {} foo(1, undef, 3)'
> > and got the error:
> > Mandatory parameter follows optional parameter at -e line 1, near
> "$z) "
> >
> > So //= and ||= mark a parameter as optional, but optional parameters
> > must follow mandatory ones. Outside of signatures these operators check
> > a value of a variable. A mandatory parameter can have undef or false
> > value. If it is feasible, maybe these operators could be applied to
> > mandatory parameters as well.
>
> I don't see how that could work. It makes for an ambiguity.


I generally find that if I need more than two parameters and some are
optional, switching to named parameters fixes the issue. It also makes it
easier to distinguish between the cases of "not passed" and "undef passed."

Best,
Ovid
--
Curtis "Ovid" Poe
--
CTO, All Around the World
World-class software development and consulting
https://allaroundtheworld.fr/
Re: //= and ||= in subroutine signatures [ In reply to ]
On Sun, 3 Sep 2023 10:32:00 +0100 Dave Mitchell <davem@iabyn.com> wrote:

> On Sun, Sep 03, 2023 at 11:48:14AM +0300, Ivan Vorontsov wrote:
> > With perl v5.38.0 I wrote a code similar to:
> > perl -E 'sub foo ($x, $y //= 42, $z) {} foo(1, undef, 3)'
> > and got the error:
> > Mandatory parameter follows optional parameter at -e line 1, near "$z) "
> >
> > So //= and ||= mark a parameter as optional, but optional parameters
> > must follow mandatory ones. Outside of signatures these operators check
> > a value of a variable. A mandatory parameter can have undef or false
> > value. If it is feasible, maybe these operators could be applied to
> > mandatory parameters as well.
>
> I don't see how that could work. It makes for an ambiguity.
>
> You could create a parser rule which says that that if a mandatory
> parameter follows a ||= parameter, then the ||= should be interpreted as
> mandatory and vice versa:
>
> sub f1($x, $y ||= 1, $z) {...} # $y is mandatory
> sub f2($x, $y ||= 1, $z = 1) {...} # $y is optional
>
> but then this becomes ambiguous:
>
> sub f3($x, $y ||= 1) {...} # is $y optional or mandatory?
>
> --
> Please note that ash-trays are provided for the use of smokers,
> whereas the floor is provided for the use of all patrons.
> -- Bill Royston

Maybe genuine optional parameters must be only the ones marked by =
sign. Others are mandatory. To mandatory parameters with //= or ||=
operators, that are last in the list or precede optional ones with =,
undef values are assigned, if there are less arguments than mandatory
parameters, and then operator works with that value.

--
Ivan Vorontsov <ivrntsv@yandex.ru>
Re: //= and ||= in subroutine signatures [ In reply to ]
On Sun, Sep 03, 2023 at 01:28:08PM +0300, Ivan Vorontsov wrote:
> Maybe genuine optional parameters must be only the ones marked by =
> sign. Others are mandatory. To mandatory parameters with //= or ||=
> operators, that are last in the list or precede optional ones with =,
> undef values are assigned, if there are less arguments than mandatory
> parameters, and then operator works with that value.

I think that that's complex and confusing. You're basically saying

f($x, $y = 1, $z = 2) # $y is optional parameter
f($x, $y //= 1, $z = 2) # $y is optional parameter
f($x, $y //= 1, $z ) # $y is mandatory parameter
f($x, $y //= 1 ) # $y is optional parameter

I think //= and ||= should be consistently either mandatory or optional,
and not vary based on context.

And since there already been a release (5.38) where they're optional, I
think we should keep it that way.

--
Decaffeinated coffee is like dehydrated water
Re: //= and ||= in subroutine signatures [ In reply to ]
> f($x, $y //= 1, $z = 2) # $y is optional parameter

This is an intermediate case. To a caller $y is optional, but $y
must have undef value either explicitly or implicitly to trigger the
assignment, $z must not accept argument at all to get assigned. I would
call $y semi-optional :)

> I think //= and ||= should be consistently either mandatory or optional,
> and not vary based on context.

I think that it doesn't matter whether a parameter is mandatory or
optional. //= and ||= operators work by checking a value. It's a
conditional assignment to a variable that must already have a value to
be examined. It is a nice feature to have, a convenient shortcut, which
now works only in case of optional parameters.

If it can't be done, it's okay. I can write the check explicitly (as
usual :)):
sub foo ($x, $y, $z) { $y //= 42 }

--
Ivan Vorontsov <ivrntsv@yandex.ru>
Re: //= and ||= in subroutine signatures [ In reply to ]
On Mon, Sep 04, 2023 at 06:25:57PM +0300, Ivan Vorontsov wrote:
> > f($x, $y //= 1, $z = 2) # $y is optional parameter
>
> This is an intermediate case. To a caller $y is optional, but $y
> must have undef value either explicitly or implicitly to trigger the
> assignment, $z must not accept argument at all to get assigned. I would
> call $y semi-optional :)

I don't understand what you are trying to say there. The difference
between a mandatory and optional argument is that perl will croak()
if not enough mandatory arguments are passed to the function.

Given

f($x, $y //= 1, $z = 2) # $y is optional parameter

what do you expect the result to be for each of these (i.e. croak, or $y
assigned the value 2, or whatever)?

f(1);
f(1,2);
f(1, undef);
f(1, 2, undef);


--
Monto Blanco... scorchio!
Re: //= and ||= in subroutine signatures [ In reply to ]
On Sun, 3 Sept 2023 at 10:48, Ivan Vorontsov <ivrntsv@yandex.ru> wrote:

> With perl v5.38.0 I wrote a code similar to:
> perl -E 'sub foo ($x, $y //= 42, $z) {} foo(1, undef, 3)'
> and got the error:
> Mandatory parameter follows optional parameter at -e line 1, near "$z)
> "
>
> So //= and ||= mark a parameter as optional, but optional parameters must
> follow mandatory ones. Outside of signatures these operators check a value
> of a variable. A mandatory parameter can have undef or false value. If it
> is feasible, maybe these operators could be applied to mandatory parameters
> as well.
>
>
you are mixing two domains not clearly formulated yet (in Perl)

one is signatures, where operators acts like "if not exists"
second is data contract, where you want "use 42 if undef"

first one struggles with missing concept of "not-exists" value
for second, you can use Type::Params for now, maybe current WIP (Oshun)
will solve it in future



> --
> Ivan Vorontsov <ivrntsv@yandex.ru>
>
Re: //= and ||= in subroutine signatures [ In reply to ]
Dave Mitchell writes:
> On Sun, Sep 03, 2023 at 01:28:08PM +0300, Ivan Vorontsov wrote:
>> Maybe genuine optional parameters must be only the ones marked by =
>> sign. Others are mandatory. To mandatory parameters with //= or ||=
>> operators, that are last in the list or precede optional ones with =,
>> undef values are assigned, if there are less arguments than mandatory
>> parameters, and then operator works with that value.
>
> I think that that's complex and confusing. You're basically saying
>
> f($x, $y = 1, $z = 2) # $y is optional parameter
> f($x, $y //= 1, $z = 2) # $y is optional parameter

IMHO the only sensible interpretation of that syntax (given what it does
elsewhere) would have been "$y is a mandatory parameter that gets a
value of 1 (or whatever expression in that place) when passed an undef"
(and the same for "||=" when passed something that evaluates to
"false"). Optionality should have been strictly assigned by plain "=".
Of course think something like

$y //= "undef" = "default"

would have been subject to lengthy discussion, both on whether it should
even be there and what exactly it does.


Regards,
Achim.
--
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

Factory and User Sound Singles for Waldorf rackAttack:
http://Synth.Stromeko.net/Downloads.html#WaldorfSounds
Re: //= and ||= in subroutine signatures [ In reply to ]
On Mon, 4 Sep 2023 16:44:13 +0100 Dave Mitchell <davem@iabyn.com> wrote:

> On Mon, Sep 04, 2023 at 06:25:57PM +0300, Ivan Vorontsov wrote:
> > > f($x, $y //= 1, $z = 2) # $y is optional parameter
> >
> > This is an intermediate case. To a caller $y is optional, but $y
> > must have undef value either explicitly or implicitly to trigger the
> > assignment, $z must not accept argument at all to get assigned. I would
> > call $y semi-optional :)
>
> I don't understand what you are trying to say there. The difference
> between a mandatory and optional argument is that perl will croak()
> if not enough mandatory arguments are passed to the function.

Sorry for confusion. $y is optional. I called $y semi-optional
jokingly. It's hard to joke in a foreign language. Won't try to do it
again.

But I tried to underline that //= operator demands a value to be
checked. With optional parameters to trigger checked assignment to $y,
it must get value undef either explicitly f('foo', undef) or implicitly
f('foo'). With mandatory parameters (as in hypothetical
sub foo ($x, $y //= 42, $z) {}) $y must always get explicit value through
an argument which might happen to be undef, then checked assignment
triggers.

Consider this example:
# $v, $w, $x are mandatory; $y, $z are optional
sub bar ($v, $w, $x, $y //= 1, $z = 2) {
$w //= 42;
}
Wouldn't it be convenient to write as:
# $v, $w, $x are mandatory; $y, $z are optional
sub bar ($v, $w //= 42, $x, $y //= 1, $z = 2) {
}
But I suppose it can't be done. It's fine.

> Given
>
> f($x, $y //= 1, $z = 2) # $y is optional parameter
>
> what do you expect the result to be for each of these (i.e. croak, or $y
> assigned the value 2, or whatever)?
>
> f(1);
> f(1,2);
> f(1, undef);
> f(1, 2, undef);

They must work as documentation says.

f(1); # $x = 1, $y = 1, $z = 2
f(1,2); # $x = 1, $y = 2, $z = 2
f(1, undef); # $x = 1, $y = 1, $z = 2
f(1, 2, undef); # $x = 1, $y = 2, $z = undef

--
Ivan Vorontsov <ivrntsv@yandex.ru>
Re: //= and ||= in subroutine signatures [ In reply to ]
On Tue, 5 Sep 2023 22:55:46 +0300
Ivan Vorontsov <ivrntsv@yandex.ru> wrote:

> Wouldn't it be convenient to write as:
> # $v, $w, $x are mandatory; $y, $z are optional
> sub bar ($v, $w //= 42, $x, $y //= 1, $z = 2) {
> }

If you want $w to be mandatory, you can't put a defaulting expression
on it.

If you still want its value to be 42 if the caller *explicitly decided
to pass undef*, that's that regular code inside the function is for.

sub bar ($v, $w, $x, $y //= 1, $z = 2) {
$w //= 42;
...
}

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: //= and ||= in subroutine signatures [ In reply to ]
On Tue, 5 Sep 2023 22:12:38 +0100 "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:

> On Tue, 5 Sep 2023 22:55:46 +0300
> Ivan Vorontsov <ivrntsv@yandex.ru> wrote:
>
> > Wouldn't it be convenient to write as:
> > # $v, $w, $x are mandatory; $y, $z are optional
> > sub bar ($v, $w //= 42, $x, $y //= 1, $z = 2) {
> > }
>
> If you want $w to be mandatory, you can't put a defaulting expression
> on it.
>
> If you still want its value to be 42 if the caller *explicitly decided
> to pass undef*, that's that regular code inside the function is for.
>
> sub bar ($v, $w, $x, $y //= 1, $z = 2) {
> $w //= 42;
> ...
> }

Accepted.

--
Ivan Vorontsov <ivrntsv@yandex.ru>
Re: //= and ||= in subroutine signatures [ In reply to ]
Let me try to answer this message one more time. Consider this answer
independent from the other one that took a different route.

On Mon, 4 Sep 2023 14:10:56 +0100 Dave Mitchell <davem@iabyn.com> wrote:

> On Sun, Sep 03, 2023 at 01:28:08PM +0300, Ivan Vorontsov wrote:
> > Maybe genuine optional parameters must be only the ones marked by =
> > sign. Others are mandatory. To mandatory parameters with //= or ||=
> > operators, that are last in the list or precede optional ones with =,
> > undef values are assigned, if there are less arguments than mandatory
> > parameters, and then operator works with that value.
>
> I think that that's complex and confusing. You're basically saying
>
> f($x, $y = 1, $z = 2) # $y is optional parameter
> f($x, $y //= 1, $z = 2) # $y is optional parameter
> f($x, $y //= 1, $z ) # $y is mandatory parameter
> f($x, $y //= 1 ) # $y is optional parameter

With my suggestion it should be:

f($x, $y = 1, $z = 2) # $y is optional parameter
f($x, $y //= 1, $z = 2) # $y is mandatory parameter
f($x, $y //= 1, $z ) # $y is mandatory parameter
f($x, $y //= 1 ) # $y is mandatory parameter

Consider this example:

f($v, $w //= 42, $x, $y //= 1, $z = 2)

Here $v, $w, $x, $y are mandatory, $z is optional. But function can be
called with less arguments than number of mandatory parameters because
of $y. In that case $y assigned undef, then checked assignment is
applied. When number of arguments is equal to number of mandatory
parameters only checked assignment is applied to $y. Checked assignment
is applied to $w always.

But with my suggestion = parameters must be very last in the parameter
list without //= and ||= parameters in between them. That's a drawback.
Right now they can be interspersed.

> I think //= and ||= should be consistently either mandatory or optional,
> and not vary based on context.

Mandatory by the suggestion.

> And since there already been a release (5.38) where they're optional, I
> think we should keep it that way.

As I understand unconditionally. So any change is a break. And a user
visible break as far as I see is the prohibition of interspersing =
parameters with //= and ||= parameters. Allowing interspersing
mandatory parameters with //= and ||= parameters is an addition, not a
break. It brings questions. Is the suggestion worthwhile the break? Is
it implementable?

This is my last attempt on this idea. I hope I am not too irritating.

--
Ivan Vorontsov <ivrntsv@yandex.ru>
Re: //= and ||= in subroutine signatures [ In reply to ]
On 2023-09-05 23:37, Ivan Vorontsov wrote:
> [...]
> f($x, $y = 1, $z = 2) # $y is optional parameter
> f($x, $y //= 1, $z = 2) # $y is mandatory parameter
> f($x, $y //= 1, $z ) # $y is mandatory parameter
> f($x, $y //= 1 ) # $y is mandatory parameter
>
> Consider this example:
>
> f($v, $w //= 42, $x, $y //= 1, $z = 2)
>
> Here $v, $w, $x, $y are mandatory, $z is optional. But function can be
> called with less arguments than number of mandatory parameters because
> of $y.

Mandatory is a strict condition,
so if-or-when it gets called with less arguments than defined as the
minimum,
then that is an error, which is best caught at compile-time ("if") already.

A run-time ("when") check is still needed, as f(@v) could turn out to be
a violation.

-- Ruud
Re: //= and ||= in subroutine signatures [ In reply to ]
On Wed, 6 Sep 2023 00:37:13 +0300 Ivan Vorontsov <ivrntsv@yandex.ru> wrote:

> On Mon, 4 Sep 2023 14:10:56 +0100 Dave Mitchell <davem@iabyn.com> wrote:
>
> > On Sun, Sep 03, 2023 at 01:28:08PM +0300, Ivan Vorontsov wrote:
> > > Maybe genuine optional parameters must be only the ones marked by =
> > > sign. Others are mandatory. To mandatory parameters with //= or ||=
> > > operators, that are last in the list or precede optional ones with =,
> > > undef values are assigned, if there are less arguments than mandatory
> > > parameters, and then operator works with that value.
> >
> > I think that that's complex and confusing. You're basically saying
> >
> > f($x, $y = 1, $z = 2) # $y is optional parameter
> > f($x, $y //= 1, $z = 2) # $y is optional parameter
> > f($x, $y //= 1, $z ) # $y is mandatory parameter
> > f($x, $y //= 1 ) # $y is optional parameter
>
> With my suggestion it should be:
>
> f($x, $y = 1, $z = 2) # $y is optional parameter
> f($x, $y //= 1, $z = 2) # $y is mandatory parameter
> f($x, $y //= 1, $z ) # $y is mandatory parameter
> f($x, $y //= 1 ) # $y is mandatory parameter
>
> Consider this example:
>
> f($v, $w //= 42, $x, $y //= 1, $z = 2)
>
> Here $v, $w, $x, $y are mandatory, $z is optional. But function can be
> called with less arguments than number of mandatory parameters because
> of $y. In that case $y assigned undef, then checked assignment is
> applied. When number of arguments is equal to number of mandatory
> parameters only checked assignment is applied to $y. Checked assignment
> is applied to $w always.
>
> But with my suggestion = parameters must be very last in the parameter
> list without //= and ||= parameters in between them. That's a drawback.
> Right now they can be interspersed.
>
> > I think //= and ||= should be consistently either mandatory or optional,
> > and not vary based on context.
>
> Mandatory by the suggestion.
>
> > And since there already been a release (5.38) where they're optional, I
> > think we should keep it that way.
>
> As I understand unconditionally. So any change is a break. And a user
> visible break as far as I see is the prohibition of interspersing =
> parameters with //= and ||= parameters. Allowing interspersing
> mandatory parameters with //= and ||= parameters is an addition, not a
> break. It brings questions. Is the suggestion worthwhile the break? Is
> it implementable?

After some time I think that's not a good idea. Too much fuss for
too little. The current behavior is good enough for me. Thank you all
for attention.

--
Ivan Vorontsov <ivrntsv@yandex.ru>