Perl6: variable number of arguments to function/subroutine
I want to be able to run a function with a variable number of parameters in Perl6, but after reading through https://docs.perl6.org/language/functions#Arguments I don't see how it can be done. I see numerous links for other languages, and a warning that "Questions with similar titles have frequently been downvoted" but I don't see this anywhere in the documentation or StackOverflow.
I want to do something like this:
some-test($v1, $v2)
or
some-test($v3)
but not have a separate function using multi
for each
How can I construct a Perl6 subroutine which will accept a variable number of strings?
perl6
add a comment |
I want to be able to run a function with a variable number of parameters in Perl6, but after reading through https://docs.perl6.org/language/functions#Arguments I don't see how it can be done. I see numerous links for other languages, and a warning that "Questions with similar titles have frequently been downvoted" but I don't see this anywhere in the documentation or StackOverflow.
I want to do something like this:
some-test($v1, $v2)
or
some-test($v3)
but not have a separate function using multi
for each
How can I construct a Perl6 subroutine which will accept a variable number of strings?
perl6
So $v3 is a different value to $v1?
– Scimon
Feb 15 at 15:52
@Scimon all the variables given to the function/subroutine should be independent, so yes, $v3 should be different from $v1
– con
Feb 15 at 15:56
add a comment |
I want to be able to run a function with a variable number of parameters in Perl6, but after reading through https://docs.perl6.org/language/functions#Arguments I don't see how it can be done. I see numerous links for other languages, and a warning that "Questions with similar titles have frequently been downvoted" but I don't see this anywhere in the documentation or StackOverflow.
I want to do something like this:
some-test($v1, $v2)
or
some-test($v3)
but not have a separate function using multi
for each
How can I construct a Perl6 subroutine which will accept a variable number of strings?
perl6
I want to be able to run a function with a variable number of parameters in Perl6, but after reading through https://docs.perl6.org/language/functions#Arguments I don't see how it can be done. I see numerous links for other languages, and a warning that "Questions with similar titles have frequently been downvoted" but I don't see this anywhere in the documentation or StackOverflow.
I want to do something like this:
some-test($v1, $v2)
or
some-test($v3)
but not have a separate function using multi
for each
How can I construct a Perl6 subroutine which will accept a variable number of strings?
perl6
perl6
asked Feb 15 at 15:30
concon
1,0961820
1,0961820
So $v3 is a different value to $v1?
– Scimon
Feb 15 at 15:52
@Scimon all the variables given to the function/subroutine should be independent, so yes, $v3 should be different from $v1
– con
Feb 15 at 15:56
add a comment |
So $v3 is a different value to $v1?
– Scimon
Feb 15 at 15:52
@Scimon all the variables given to the function/subroutine should be independent, so yes, $v3 should be different from $v1
– con
Feb 15 at 15:56
So $v3 is a different value to $v1?
– Scimon
Feb 15 at 15:52
So $v3 is a different value to $v1?
– Scimon
Feb 15 at 15:52
@Scimon all the variables given to the function/subroutine should be independent, so yes, $v3 should be different from $v1
– con
Feb 15 at 15:56
@Scimon all the variables given to the function/subroutine should be independent, so yes, $v3 should be different from $v1
– con
Feb 15 at 15:56
add a comment |
3 Answers
3
active
oldest
votes
TL;DR You're asking about variadic functions.1 Simple use is simple. Some P6 features, most notably positional and named arguments, and variadic destructuring, add some wrinkles. Also, see the other answers which are very helpful too.
variable number of arguments
Simple use of a simple variadic function:
sub variadic (|args) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
A |foo
parameter slurps up all remaining arguments into a Capture
bound to sigilless identifier foo
:
sub variadic ($a, @b, %c, |others) { say others[0] }
variadic 1, [2,3], (:foo), 4, [5,6], (:bar); # 4
In the above example the others
parameter "slurps"1 up the last three listed arguments starting with the 4
.
Variadic variations
Things aren't always simple:
variadic(1, 2); # 2 -- works but args are Ints
variadic(:foo,:bar); # 0 -- where did :foo, :bar go?
variadic((:foo)); # 1 -- works; arg is Pair (:foo)
variadic((1, 2)); # 1 -- works; arg is List (1,2)
In the rest of this answer I explain:
Constraining arguments, eg ensuring they're all strings.
Positional vs named arguments;
**@foo
and*%foo
Variadic positionals destructuring;
+@foo
and*@foo
Constraining arguments
variable number of strings
You can impose any constraints you want on slurped arguments by using a where
clause. (Which you can in turn package into a subset
if you want.)
For example, to constrain all the arguments to be of type Str
:
sub variadic (|args where .all ~~ Str) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
variadic(1); # Constraint type check failed
Positional vs named arguments; **@foo
and *%foo
P6 supports both positional and named arguments.
Using |foo
in a signature always captures all remaining arguments, both positional and named:
sub slurps-into-WHAT (|args) { say WHAT args }
slurps-into-WHAT(); # (Capture)
A Capture
stores positional arguments in an internal list accessible via positional subscripting (i.e. args[...]
) and named arguments in a hash accessible via associative subscripting (i.e. args<...>
or args{...}
):
sub variadic (|args) { say " {args[1]} {args<named2>}" }
variadic('pos0', 'pos1', named1 => 42, named2 => 99); # pos1 99
Sometimes it's preferable to collect just named args, or just positional ones, or to collect both but in separate parameters.
To collect named args, use a parameter of the form *%foo
(one asterisk prefix and a hash arg):
sub variadic-for-nameds (*%nameds) { say %nameds }
variadic-for-nameds(:foo, :bar); # {bar => True, foo => True}
(Note that all methods collect named args in this way even if their signature doesn't explicitly say so.2)
To collect positional args, use a parameter of the form **@foo
(two asterisk prefix immediately followed by an array arg):
sub variadic-for-positionals (**@positionals) { say @positionals }
variadic-for-positionals(1, 2, 3); # [1 2 3]
Variadic positionals destructuring; +@foo
and *@foo
P6 provides a range of non-variadic argument destructuring features.
The first variadic positionals destructuring parameter form is +@foo
. This has exactly the same effect as **@foo
except in one case; if the variadic parameter gets just a single argument, and that argument is a list or array, then the parameter is bound to the content of that list or array, stripping away the list/array container:
sub variadic-plus (+@positionals) { say @positionals }
variadic-plus(1,2,3); # says same as for **@positionals
variadic-plus(1); # says same as for **@positionals
variadic-plus([1]); # [1] -- instead of [[1]]
variadic-plus((1,2,3)); # [1 2 3] -- instead of [(1 2 3)]
The +@foo
form was introduced to support the "single arg rule". It's used by core devs writing built ins. Users may wish to use it when they want the same behavior.
The other variadic positionals destructuring form is *@foo
. It does the same thing as +@foo
in that it extracts the content from list or array container args and throws the container away. But it's much more aggressive:
It does this for all arguments.
If an argument is a list rather than an array (
(...)
rather than[...]
) then it descends into that list and recursively repeats the exercise if an element of the list is itself another inner list or array.
Thus:
sub variadic-star (*@positionals) { say @positionals }
variadic-star((1,2),[3,4]); # [1 2 3 4]
variadic-star((1,2),(3,4,(5,6,(7,8)))); # [1 2 3 4 5 6 7 8]
variadic-star((1,2),(3,4,[5,6,(7,8)])); # [1 2 3 4 5 6 (7 8)]
(Note how it stripped the container from the [5,6,(7,8)]
array but did not descend into it.)
One final thing; are there variadic named destructuring parameters? You tell me.3
Bonus section: foo(...)
vs foo (...)
(I included this bonus section in the hope it heads off confusion. If this section is itself confusing, just ignore it.)
Routine calls can be written with or without parentheses around their list of arguments and they mean the same thing. The opening parenthesis must follow the routine name immediately, without intervening whitespace:
sub foo (|args) { say args[0] }
foo 'a', 'b'; # a
foo('a', 'b'); # a
(This rule only applies to the routine call, between the routine name and its arguments. It does not apply to the routine declaration, between the routine name and its parameters. For the latter, the declaration, you can leave no space or use space as I have above with sub foo (|args)
and it makes no difference.)
If you insert whitespace between the foo
and the opening parenthesis in a call you're writing something different:
foo ('a', 'b'); # (a b)
That calls foo
with one argument, the one list ('a', 'b')
in contrast to foo('a', 'b')
which calls foo
with two arguments, the two values inside the parentheses.
The following calls foo
with two arguments, both of which are lists:
foo ('a', 'b', 'c'), ('d', 'e', 'f'); # (a b c)
You may nest parentheses:
foo( ('a', 'b', 'c'), ('d', 'e', 'f') ) ; # (a b c)
foo (('a', 'b', 'c'), ('d', 'e', 'f')) ; # ((a b c) (d e f))
foo( (('a', 'b', 'c'), ('d', 'e', 'f')) ) ; # ((a b c) (d e f))
The latter two foo
calls get one argument, the one list ( ('a', 'b', 'c'), ('d', 'e', 'f') )
(that happens to contain two inner lists).
Footnotes
1 The standard industry term for this is a variadic function. At the time of writing this answer, the Rakudo P6 compiler uses the industry standard term ("variadic") in error messages but the official P6 doc tends to use the word "slurpy" instead of "variadic" and talks of "slurping up arguments".
2 Methods always have an implicit variadic named parameter called %_
if one is not explicitly specified:
say .signature given my method foo {} # (Mu: *%_)
3 The P6 language and/or the Rakudo P6 compiler currently allows parameters to be written in the form +%foo
and **%foo
. It doesn't really make sense to have variadic nameds destructuring. Perhaps that explains why both these forms do insane things:
**%foo
appears to be indistinguishable from%foo
.+%foo
appears to be indistinguishable from**@foo
except for using the identifier%foo
instead of@foo
. The object bound to%foo
is anArray
!
1
what is the purpose of the**
and+@
? These don't appear to exponentiate and add
– con
Feb 15 at 17:48
1
Answer rewritten. Please LMK if it makes sense and answers your questions.
– raiph
Feb 16 at 23:08
1
thanks for writing all of that, I'll get to reading it soon. I really appreciate all of the work that you put in to that answer!
– con
Feb 18 at 16:02
add a comment |
If you just want to be able to take 1 or 2 values then the easiest way is to mark the second value as optional :
sub some-test( $v1, $v2? ) { ... }
Or you can define a default value :
sub some-test( $v1, $v2="default" ) { ... }
Or if you want any number of values (1 or more) you can use a slurpy with a where clause :
sub some-test( *@v where *.elems > 0 ) { ... }
this fails withConstraint type check failed in binding to parameter '@v'; expected anonymous constraint to be met but got Array ($["a", "b"])
:-(
– con
Feb 15 at 16:11
Can you share the subroutine definition you used? $["a","b"] should match the where clause of *.elems > 0 (as it's got 2 elements).
– Scimon
Feb 15 at 16:15
sub some-test (*@v where *.elems < 0) { for @v -> $v { put $v } } my $x = 'a'; my $y = 'b'; some-test($x, $y);
– con
Feb 15 at 16:35
So you are testing elems < 0 which is true arrays with negative elements in. Instead of you test for elems > 0 then you won't accept an empty array but will accept others
– Scimon
Feb 15 at 16:41
Another option to get at least one value is to usesub some-test($v1, *@rest) { }
– moritz
Feb 16 at 13:04
add a comment |
You can use signature destructuring
sub some-test(*@all [$first, *@rest]) { ... } # must have 1 or more parameters
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54712440%2fperl6-variable-number-of-arguments-to-function-subroutine%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
TL;DR You're asking about variadic functions.1 Simple use is simple. Some P6 features, most notably positional and named arguments, and variadic destructuring, add some wrinkles. Also, see the other answers which are very helpful too.
variable number of arguments
Simple use of a simple variadic function:
sub variadic (|args) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
A |foo
parameter slurps up all remaining arguments into a Capture
bound to sigilless identifier foo
:
sub variadic ($a, @b, %c, |others) { say others[0] }
variadic 1, [2,3], (:foo), 4, [5,6], (:bar); # 4
In the above example the others
parameter "slurps"1 up the last three listed arguments starting with the 4
.
Variadic variations
Things aren't always simple:
variadic(1, 2); # 2 -- works but args are Ints
variadic(:foo,:bar); # 0 -- where did :foo, :bar go?
variadic((:foo)); # 1 -- works; arg is Pair (:foo)
variadic((1, 2)); # 1 -- works; arg is List (1,2)
In the rest of this answer I explain:
Constraining arguments, eg ensuring they're all strings.
Positional vs named arguments;
**@foo
and*%foo
Variadic positionals destructuring;
+@foo
and*@foo
Constraining arguments
variable number of strings
You can impose any constraints you want on slurped arguments by using a where
clause. (Which you can in turn package into a subset
if you want.)
For example, to constrain all the arguments to be of type Str
:
sub variadic (|args where .all ~~ Str) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
variadic(1); # Constraint type check failed
Positional vs named arguments; **@foo
and *%foo
P6 supports both positional and named arguments.
Using |foo
in a signature always captures all remaining arguments, both positional and named:
sub slurps-into-WHAT (|args) { say WHAT args }
slurps-into-WHAT(); # (Capture)
A Capture
stores positional arguments in an internal list accessible via positional subscripting (i.e. args[...]
) and named arguments in a hash accessible via associative subscripting (i.e. args<...>
or args{...}
):
sub variadic (|args) { say " {args[1]} {args<named2>}" }
variadic('pos0', 'pos1', named1 => 42, named2 => 99); # pos1 99
Sometimes it's preferable to collect just named args, or just positional ones, or to collect both but in separate parameters.
To collect named args, use a parameter of the form *%foo
(one asterisk prefix and a hash arg):
sub variadic-for-nameds (*%nameds) { say %nameds }
variadic-for-nameds(:foo, :bar); # {bar => True, foo => True}
(Note that all methods collect named args in this way even if their signature doesn't explicitly say so.2)
To collect positional args, use a parameter of the form **@foo
(two asterisk prefix immediately followed by an array arg):
sub variadic-for-positionals (**@positionals) { say @positionals }
variadic-for-positionals(1, 2, 3); # [1 2 3]
Variadic positionals destructuring; +@foo
and *@foo
P6 provides a range of non-variadic argument destructuring features.
The first variadic positionals destructuring parameter form is +@foo
. This has exactly the same effect as **@foo
except in one case; if the variadic parameter gets just a single argument, and that argument is a list or array, then the parameter is bound to the content of that list or array, stripping away the list/array container:
sub variadic-plus (+@positionals) { say @positionals }
variadic-plus(1,2,3); # says same as for **@positionals
variadic-plus(1); # says same as for **@positionals
variadic-plus([1]); # [1] -- instead of [[1]]
variadic-plus((1,2,3)); # [1 2 3] -- instead of [(1 2 3)]
The +@foo
form was introduced to support the "single arg rule". It's used by core devs writing built ins. Users may wish to use it when they want the same behavior.
The other variadic positionals destructuring form is *@foo
. It does the same thing as +@foo
in that it extracts the content from list or array container args and throws the container away. But it's much more aggressive:
It does this for all arguments.
If an argument is a list rather than an array (
(...)
rather than[...]
) then it descends into that list and recursively repeats the exercise if an element of the list is itself another inner list or array.
Thus:
sub variadic-star (*@positionals) { say @positionals }
variadic-star((1,2),[3,4]); # [1 2 3 4]
variadic-star((1,2),(3,4,(5,6,(7,8)))); # [1 2 3 4 5 6 7 8]
variadic-star((1,2),(3,4,[5,6,(7,8)])); # [1 2 3 4 5 6 (7 8)]
(Note how it stripped the container from the [5,6,(7,8)]
array but did not descend into it.)
One final thing; are there variadic named destructuring parameters? You tell me.3
Bonus section: foo(...)
vs foo (...)
(I included this bonus section in the hope it heads off confusion. If this section is itself confusing, just ignore it.)
Routine calls can be written with or without parentheses around their list of arguments and they mean the same thing. The opening parenthesis must follow the routine name immediately, without intervening whitespace:
sub foo (|args) { say args[0] }
foo 'a', 'b'; # a
foo('a', 'b'); # a
(This rule only applies to the routine call, between the routine name and its arguments. It does not apply to the routine declaration, between the routine name and its parameters. For the latter, the declaration, you can leave no space or use space as I have above with sub foo (|args)
and it makes no difference.)
If you insert whitespace between the foo
and the opening parenthesis in a call you're writing something different:
foo ('a', 'b'); # (a b)
That calls foo
with one argument, the one list ('a', 'b')
in contrast to foo('a', 'b')
which calls foo
with two arguments, the two values inside the parentheses.
The following calls foo
with two arguments, both of which are lists:
foo ('a', 'b', 'c'), ('d', 'e', 'f'); # (a b c)
You may nest parentheses:
foo( ('a', 'b', 'c'), ('d', 'e', 'f') ) ; # (a b c)
foo (('a', 'b', 'c'), ('d', 'e', 'f')) ; # ((a b c) (d e f))
foo( (('a', 'b', 'c'), ('d', 'e', 'f')) ) ; # ((a b c) (d e f))
The latter two foo
calls get one argument, the one list ( ('a', 'b', 'c'), ('d', 'e', 'f') )
(that happens to contain two inner lists).
Footnotes
1 The standard industry term for this is a variadic function. At the time of writing this answer, the Rakudo P6 compiler uses the industry standard term ("variadic") in error messages but the official P6 doc tends to use the word "slurpy" instead of "variadic" and talks of "slurping up arguments".
2 Methods always have an implicit variadic named parameter called %_
if one is not explicitly specified:
say .signature given my method foo {} # (Mu: *%_)
3 The P6 language and/or the Rakudo P6 compiler currently allows parameters to be written in the form +%foo
and **%foo
. It doesn't really make sense to have variadic nameds destructuring. Perhaps that explains why both these forms do insane things:
**%foo
appears to be indistinguishable from%foo
.+%foo
appears to be indistinguishable from**@foo
except for using the identifier%foo
instead of@foo
. The object bound to%foo
is anArray
!
1
what is the purpose of the**
and+@
? These don't appear to exponentiate and add
– con
Feb 15 at 17:48
1
Answer rewritten. Please LMK if it makes sense and answers your questions.
– raiph
Feb 16 at 23:08
1
thanks for writing all of that, I'll get to reading it soon. I really appreciate all of the work that you put in to that answer!
– con
Feb 18 at 16:02
add a comment |
TL;DR You're asking about variadic functions.1 Simple use is simple. Some P6 features, most notably positional and named arguments, and variadic destructuring, add some wrinkles. Also, see the other answers which are very helpful too.
variable number of arguments
Simple use of a simple variadic function:
sub variadic (|args) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
A |foo
parameter slurps up all remaining arguments into a Capture
bound to sigilless identifier foo
:
sub variadic ($a, @b, %c, |others) { say others[0] }
variadic 1, [2,3], (:foo), 4, [5,6], (:bar); # 4
In the above example the others
parameter "slurps"1 up the last three listed arguments starting with the 4
.
Variadic variations
Things aren't always simple:
variadic(1, 2); # 2 -- works but args are Ints
variadic(:foo,:bar); # 0 -- where did :foo, :bar go?
variadic((:foo)); # 1 -- works; arg is Pair (:foo)
variadic((1, 2)); # 1 -- works; arg is List (1,2)
In the rest of this answer I explain:
Constraining arguments, eg ensuring they're all strings.
Positional vs named arguments;
**@foo
and*%foo
Variadic positionals destructuring;
+@foo
and*@foo
Constraining arguments
variable number of strings
You can impose any constraints you want on slurped arguments by using a where
clause. (Which you can in turn package into a subset
if you want.)
For example, to constrain all the arguments to be of type Str
:
sub variadic (|args where .all ~~ Str) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
variadic(1); # Constraint type check failed
Positional vs named arguments; **@foo
and *%foo
P6 supports both positional and named arguments.
Using |foo
in a signature always captures all remaining arguments, both positional and named:
sub slurps-into-WHAT (|args) { say WHAT args }
slurps-into-WHAT(); # (Capture)
A Capture
stores positional arguments in an internal list accessible via positional subscripting (i.e. args[...]
) and named arguments in a hash accessible via associative subscripting (i.e. args<...>
or args{...}
):
sub variadic (|args) { say " {args[1]} {args<named2>}" }
variadic('pos0', 'pos1', named1 => 42, named2 => 99); # pos1 99
Sometimes it's preferable to collect just named args, or just positional ones, or to collect both but in separate parameters.
To collect named args, use a parameter of the form *%foo
(one asterisk prefix and a hash arg):
sub variadic-for-nameds (*%nameds) { say %nameds }
variadic-for-nameds(:foo, :bar); # {bar => True, foo => True}
(Note that all methods collect named args in this way even if their signature doesn't explicitly say so.2)
To collect positional args, use a parameter of the form **@foo
(two asterisk prefix immediately followed by an array arg):
sub variadic-for-positionals (**@positionals) { say @positionals }
variadic-for-positionals(1, 2, 3); # [1 2 3]
Variadic positionals destructuring; +@foo
and *@foo
P6 provides a range of non-variadic argument destructuring features.
The first variadic positionals destructuring parameter form is +@foo
. This has exactly the same effect as **@foo
except in one case; if the variadic parameter gets just a single argument, and that argument is a list or array, then the parameter is bound to the content of that list or array, stripping away the list/array container:
sub variadic-plus (+@positionals) { say @positionals }
variadic-plus(1,2,3); # says same as for **@positionals
variadic-plus(1); # says same as for **@positionals
variadic-plus([1]); # [1] -- instead of [[1]]
variadic-plus((1,2,3)); # [1 2 3] -- instead of [(1 2 3)]
The +@foo
form was introduced to support the "single arg rule". It's used by core devs writing built ins. Users may wish to use it when they want the same behavior.
The other variadic positionals destructuring form is *@foo
. It does the same thing as +@foo
in that it extracts the content from list or array container args and throws the container away. But it's much more aggressive:
It does this for all arguments.
If an argument is a list rather than an array (
(...)
rather than[...]
) then it descends into that list and recursively repeats the exercise if an element of the list is itself another inner list or array.
Thus:
sub variadic-star (*@positionals) { say @positionals }
variadic-star((1,2),[3,4]); # [1 2 3 4]
variadic-star((1,2),(3,4,(5,6,(7,8)))); # [1 2 3 4 5 6 7 8]
variadic-star((1,2),(3,4,[5,6,(7,8)])); # [1 2 3 4 5 6 (7 8)]
(Note how it stripped the container from the [5,6,(7,8)]
array but did not descend into it.)
One final thing; are there variadic named destructuring parameters? You tell me.3
Bonus section: foo(...)
vs foo (...)
(I included this bonus section in the hope it heads off confusion. If this section is itself confusing, just ignore it.)
Routine calls can be written with or without parentheses around their list of arguments and they mean the same thing. The opening parenthesis must follow the routine name immediately, without intervening whitespace:
sub foo (|args) { say args[0] }
foo 'a', 'b'; # a
foo('a', 'b'); # a
(This rule only applies to the routine call, between the routine name and its arguments. It does not apply to the routine declaration, between the routine name and its parameters. For the latter, the declaration, you can leave no space or use space as I have above with sub foo (|args)
and it makes no difference.)
If you insert whitespace between the foo
and the opening parenthesis in a call you're writing something different:
foo ('a', 'b'); # (a b)
That calls foo
with one argument, the one list ('a', 'b')
in contrast to foo('a', 'b')
which calls foo
with two arguments, the two values inside the parentheses.
The following calls foo
with two arguments, both of which are lists:
foo ('a', 'b', 'c'), ('d', 'e', 'f'); # (a b c)
You may nest parentheses:
foo( ('a', 'b', 'c'), ('d', 'e', 'f') ) ; # (a b c)
foo (('a', 'b', 'c'), ('d', 'e', 'f')) ; # ((a b c) (d e f))
foo( (('a', 'b', 'c'), ('d', 'e', 'f')) ) ; # ((a b c) (d e f))
The latter two foo
calls get one argument, the one list ( ('a', 'b', 'c'), ('d', 'e', 'f') )
(that happens to contain two inner lists).
Footnotes
1 The standard industry term for this is a variadic function. At the time of writing this answer, the Rakudo P6 compiler uses the industry standard term ("variadic") in error messages but the official P6 doc tends to use the word "slurpy" instead of "variadic" and talks of "slurping up arguments".
2 Methods always have an implicit variadic named parameter called %_
if one is not explicitly specified:
say .signature given my method foo {} # (Mu: *%_)
3 The P6 language and/or the Rakudo P6 compiler currently allows parameters to be written in the form +%foo
and **%foo
. It doesn't really make sense to have variadic nameds destructuring. Perhaps that explains why both these forms do insane things:
**%foo
appears to be indistinguishable from%foo
.+%foo
appears to be indistinguishable from**@foo
except for using the identifier%foo
instead of@foo
. The object bound to%foo
is anArray
!
1
what is the purpose of the**
and+@
? These don't appear to exponentiate and add
– con
Feb 15 at 17:48
1
Answer rewritten. Please LMK if it makes sense and answers your questions.
– raiph
Feb 16 at 23:08
1
thanks for writing all of that, I'll get to reading it soon. I really appreciate all of the work that you put in to that answer!
– con
Feb 18 at 16:02
add a comment |
TL;DR You're asking about variadic functions.1 Simple use is simple. Some P6 features, most notably positional and named arguments, and variadic destructuring, add some wrinkles. Also, see the other answers which are very helpful too.
variable number of arguments
Simple use of a simple variadic function:
sub variadic (|args) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
A |foo
parameter slurps up all remaining arguments into a Capture
bound to sigilless identifier foo
:
sub variadic ($a, @b, %c, |others) { say others[0] }
variadic 1, [2,3], (:foo), 4, [5,6], (:bar); # 4
In the above example the others
parameter "slurps"1 up the last three listed arguments starting with the 4
.
Variadic variations
Things aren't always simple:
variadic(1, 2); # 2 -- works but args are Ints
variadic(:foo,:bar); # 0 -- where did :foo, :bar go?
variadic((:foo)); # 1 -- works; arg is Pair (:foo)
variadic((1, 2)); # 1 -- works; arg is List (1,2)
In the rest of this answer I explain:
Constraining arguments, eg ensuring they're all strings.
Positional vs named arguments;
**@foo
and*%foo
Variadic positionals destructuring;
+@foo
and*@foo
Constraining arguments
variable number of strings
You can impose any constraints you want on slurped arguments by using a where
clause. (Which you can in turn package into a subset
if you want.)
For example, to constrain all the arguments to be of type Str
:
sub variadic (|args where .all ~~ Str) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
variadic(1); # Constraint type check failed
Positional vs named arguments; **@foo
and *%foo
P6 supports both positional and named arguments.
Using |foo
in a signature always captures all remaining arguments, both positional and named:
sub slurps-into-WHAT (|args) { say WHAT args }
slurps-into-WHAT(); # (Capture)
A Capture
stores positional arguments in an internal list accessible via positional subscripting (i.e. args[...]
) and named arguments in a hash accessible via associative subscripting (i.e. args<...>
or args{...}
):
sub variadic (|args) { say " {args[1]} {args<named2>}" }
variadic('pos0', 'pos1', named1 => 42, named2 => 99); # pos1 99
Sometimes it's preferable to collect just named args, or just positional ones, or to collect both but in separate parameters.
To collect named args, use a parameter of the form *%foo
(one asterisk prefix and a hash arg):
sub variadic-for-nameds (*%nameds) { say %nameds }
variadic-for-nameds(:foo, :bar); # {bar => True, foo => True}
(Note that all methods collect named args in this way even if their signature doesn't explicitly say so.2)
To collect positional args, use a parameter of the form **@foo
(two asterisk prefix immediately followed by an array arg):
sub variadic-for-positionals (**@positionals) { say @positionals }
variadic-for-positionals(1, 2, 3); # [1 2 3]
Variadic positionals destructuring; +@foo
and *@foo
P6 provides a range of non-variadic argument destructuring features.
The first variadic positionals destructuring parameter form is +@foo
. This has exactly the same effect as **@foo
except in one case; if the variadic parameter gets just a single argument, and that argument is a list or array, then the parameter is bound to the content of that list or array, stripping away the list/array container:
sub variadic-plus (+@positionals) { say @positionals }
variadic-plus(1,2,3); # says same as for **@positionals
variadic-plus(1); # says same as for **@positionals
variadic-plus([1]); # [1] -- instead of [[1]]
variadic-plus((1,2,3)); # [1 2 3] -- instead of [(1 2 3)]
The +@foo
form was introduced to support the "single arg rule". It's used by core devs writing built ins. Users may wish to use it when they want the same behavior.
The other variadic positionals destructuring form is *@foo
. It does the same thing as +@foo
in that it extracts the content from list or array container args and throws the container away. But it's much more aggressive:
It does this for all arguments.
If an argument is a list rather than an array (
(...)
rather than[...]
) then it descends into that list and recursively repeats the exercise if an element of the list is itself another inner list or array.
Thus:
sub variadic-star (*@positionals) { say @positionals }
variadic-star((1,2),[3,4]); # [1 2 3 4]
variadic-star((1,2),(3,4,(5,6,(7,8)))); # [1 2 3 4 5 6 7 8]
variadic-star((1,2),(3,4,[5,6,(7,8)])); # [1 2 3 4 5 6 (7 8)]
(Note how it stripped the container from the [5,6,(7,8)]
array but did not descend into it.)
One final thing; are there variadic named destructuring parameters? You tell me.3
Bonus section: foo(...)
vs foo (...)
(I included this bonus section in the hope it heads off confusion. If this section is itself confusing, just ignore it.)
Routine calls can be written with or without parentheses around their list of arguments and they mean the same thing. The opening parenthesis must follow the routine name immediately, without intervening whitespace:
sub foo (|args) { say args[0] }
foo 'a', 'b'; # a
foo('a', 'b'); # a
(This rule only applies to the routine call, between the routine name and its arguments. It does not apply to the routine declaration, between the routine name and its parameters. For the latter, the declaration, you can leave no space or use space as I have above with sub foo (|args)
and it makes no difference.)
If you insert whitespace between the foo
and the opening parenthesis in a call you're writing something different:
foo ('a', 'b'); # (a b)
That calls foo
with one argument, the one list ('a', 'b')
in contrast to foo('a', 'b')
which calls foo
with two arguments, the two values inside the parentheses.
The following calls foo
with two arguments, both of which are lists:
foo ('a', 'b', 'c'), ('d', 'e', 'f'); # (a b c)
You may nest parentheses:
foo( ('a', 'b', 'c'), ('d', 'e', 'f') ) ; # (a b c)
foo (('a', 'b', 'c'), ('d', 'e', 'f')) ; # ((a b c) (d e f))
foo( (('a', 'b', 'c'), ('d', 'e', 'f')) ) ; # ((a b c) (d e f))
The latter two foo
calls get one argument, the one list ( ('a', 'b', 'c'), ('d', 'e', 'f') )
(that happens to contain two inner lists).
Footnotes
1 The standard industry term for this is a variadic function. At the time of writing this answer, the Rakudo P6 compiler uses the industry standard term ("variadic") in error messages but the official P6 doc tends to use the word "slurpy" instead of "variadic" and talks of "slurping up arguments".
2 Methods always have an implicit variadic named parameter called %_
if one is not explicitly specified:
say .signature given my method foo {} # (Mu: *%_)
3 The P6 language and/or the Rakudo P6 compiler currently allows parameters to be written in the form +%foo
and **%foo
. It doesn't really make sense to have variadic nameds destructuring. Perhaps that explains why both these forms do insane things:
**%foo
appears to be indistinguishable from%foo
.+%foo
appears to be indistinguishable from**@foo
except for using the identifier%foo
instead of@foo
. The object bound to%foo
is anArray
!
TL;DR You're asking about variadic functions.1 Simple use is simple. Some P6 features, most notably positional and named arguments, and variadic destructuring, add some wrinkles. Also, see the other answers which are very helpful too.
variable number of arguments
Simple use of a simple variadic function:
sub variadic (|args) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
A |foo
parameter slurps up all remaining arguments into a Capture
bound to sigilless identifier foo
:
sub variadic ($a, @b, %c, |others) { say others[0] }
variadic 1, [2,3], (:foo), 4, [5,6], (:bar); # 4
In the above example the others
parameter "slurps"1 up the last three listed arguments starting with the 4
.
Variadic variations
Things aren't always simple:
variadic(1, 2); # 2 -- works but args are Ints
variadic(:foo,:bar); # 0 -- where did :foo, :bar go?
variadic((:foo)); # 1 -- works; arg is Pair (:foo)
variadic((1, 2)); # 1 -- works; arg is List (1,2)
In the rest of this answer I explain:
Constraining arguments, eg ensuring they're all strings.
Positional vs named arguments;
**@foo
and*%foo
Variadic positionals destructuring;
+@foo
and*@foo
Constraining arguments
variable number of strings
You can impose any constraints you want on slurped arguments by using a where
clause. (Which you can in turn package into a subset
if you want.)
For example, to constrain all the arguments to be of type Str
:
sub variadic (|args where .all ~~ Str) { say args .elems }
variadic(); # 0
variadic('1'); # 1
variadic('1', '2'); # 2
variadic(1); # Constraint type check failed
Positional vs named arguments; **@foo
and *%foo
P6 supports both positional and named arguments.
Using |foo
in a signature always captures all remaining arguments, both positional and named:
sub slurps-into-WHAT (|args) { say WHAT args }
slurps-into-WHAT(); # (Capture)
A Capture
stores positional arguments in an internal list accessible via positional subscripting (i.e. args[...]
) and named arguments in a hash accessible via associative subscripting (i.e. args<...>
or args{...}
):
sub variadic (|args) { say " {args[1]} {args<named2>}" }
variadic('pos0', 'pos1', named1 => 42, named2 => 99); # pos1 99
Sometimes it's preferable to collect just named args, or just positional ones, or to collect both but in separate parameters.
To collect named args, use a parameter of the form *%foo
(one asterisk prefix and a hash arg):
sub variadic-for-nameds (*%nameds) { say %nameds }
variadic-for-nameds(:foo, :bar); # {bar => True, foo => True}
(Note that all methods collect named args in this way even if their signature doesn't explicitly say so.2)
To collect positional args, use a parameter of the form **@foo
(two asterisk prefix immediately followed by an array arg):
sub variadic-for-positionals (**@positionals) { say @positionals }
variadic-for-positionals(1, 2, 3); # [1 2 3]
Variadic positionals destructuring; +@foo
and *@foo
P6 provides a range of non-variadic argument destructuring features.
The first variadic positionals destructuring parameter form is +@foo
. This has exactly the same effect as **@foo
except in one case; if the variadic parameter gets just a single argument, and that argument is a list or array, then the parameter is bound to the content of that list or array, stripping away the list/array container:
sub variadic-plus (+@positionals) { say @positionals }
variadic-plus(1,2,3); # says same as for **@positionals
variadic-plus(1); # says same as for **@positionals
variadic-plus([1]); # [1] -- instead of [[1]]
variadic-plus((1,2,3)); # [1 2 3] -- instead of [(1 2 3)]
The +@foo
form was introduced to support the "single arg rule". It's used by core devs writing built ins. Users may wish to use it when they want the same behavior.
The other variadic positionals destructuring form is *@foo
. It does the same thing as +@foo
in that it extracts the content from list or array container args and throws the container away. But it's much more aggressive:
It does this for all arguments.
If an argument is a list rather than an array (
(...)
rather than[...]
) then it descends into that list and recursively repeats the exercise if an element of the list is itself another inner list or array.
Thus:
sub variadic-star (*@positionals) { say @positionals }
variadic-star((1,2),[3,4]); # [1 2 3 4]
variadic-star((1,2),(3,4,(5,6,(7,8)))); # [1 2 3 4 5 6 7 8]
variadic-star((1,2),(3,4,[5,6,(7,8)])); # [1 2 3 4 5 6 (7 8)]
(Note how it stripped the container from the [5,6,(7,8)]
array but did not descend into it.)
One final thing; are there variadic named destructuring parameters? You tell me.3
Bonus section: foo(...)
vs foo (...)
(I included this bonus section in the hope it heads off confusion. If this section is itself confusing, just ignore it.)
Routine calls can be written with or without parentheses around their list of arguments and they mean the same thing. The opening parenthesis must follow the routine name immediately, without intervening whitespace:
sub foo (|args) { say args[0] }
foo 'a', 'b'; # a
foo('a', 'b'); # a
(This rule only applies to the routine call, between the routine name and its arguments. It does not apply to the routine declaration, between the routine name and its parameters. For the latter, the declaration, you can leave no space or use space as I have above with sub foo (|args)
and it makes no difference.)
If you insert whitespace between the foo
and the opening parenthesis in a call you're writing something different:
foo ('a', 'b'); # (a b)
That calls foo
with one argument, the one list ('a', 'b')
in contrast to foo('a', 'b')
which calls foo
with two arguments, the two values inside the parentheses.
The following calls foo
with two arguments, both of which are lists:
foo ('a', 'b', 'c'), ('d', 'e', 'f'); # (a b c)
You may nest parentheses:
foo( ('a', 'b', 'c'), ('d', 'e', 'f') ) ; # (a b c)
foo (('a', 'b', 'c'), ('d', 'e', 'f')) ; # ((a b c) (d e f))
foo( (('a', 'b', 'c'), ('d', 'e', 'f')) ) ; # ((a b c) (d e f))
The latter two foo
calls get one argument, the one list ( ('a', 'b', 'c'), ('d', 'e', 'f') )
(that happens to contain two inner lists).
Footnotes
1 The standard industry term for this is a variadic function. At the time of writing this answer, the Rakudo P6 compiler uses the industry standard term ("variadic") in error messages but the official P6 doc tends to use the word "slurpy" instead of "variadic" and talks of "slurping up arguments".
2 Methods always have an implicit variadic named parameter called %_
if one is not explicitly specified:
say .signature given my method foo {} # (Mu: *%_)
3 The P6 language and/or the Rakudo P6 compiler currently allows parameters to be written in the form +%foo
and **%foo
. It doesn't really make sense to have variadic nameds destructuring. Perhaps that explains why both these forms do insane things:
**%foo
appears to be indistinguishable from%foo
.+%foo
appears to be indistinguishable from**@foo
except for using the identifier%foo
instead of@foo
. The object bound to%foo
is anArray
!
edited Feb 16 at 23:06
answered Feb 15 at 17:00
raiphraiph
11.1k22138
11.1k22138
1
what is the purpose of the**
and+@
? These don't appear to exponentiate and add
– con
Feb 15 at 17:48
1
Answer rewritten. Please LMK if it makes sense and answers your questions.
– raiph
Feb 16 at 23:08
1
thanks for writing all of that, I'll get to reading it soon. I really appreciate all of the work that you put in to that answer!
– con
Feb 18 at 16:02
add a comment |
1
what is the purpose of the**
and+@
? These don't appear to exponentiate and add
– con
Feb 15 at 17:48
1
Answer rewritten. Please LMK if it makes sense and answers your questions.
– raiph
Feb 16 at 23:08
1
thanks for writing all of that, I'll get to reading it soon. I really appreciate all of the work that you put in to that answer!
– con
Feb 18 at 16:02
1
1
what is the purpose of the
**
and +@
? These don't appear to exponentiate and add– con
Feb 15 at 17:48
what is the purpose of the
**
and +@
? These don't appear to exponentiate and add– con
Feb 15 at 17:48
1
1
Answer rewritten. Please LMK if it makes sense and answers your questions.
– raiph
Feb 16 at 23:08
Answer rewritten. Please LMK if it makes sense and answers your questions.
– raiph
Feb 16 at 23:08
1
1
thanks for writing all of that, I'll get to reading it soon. I really appreciate all of the work that you put in to that answer!
– con
Feb 18 at 16:02
thanks for writing all of that, I'll get to reading it soon. I really appreciate all of the work that you put in to that answer!
– con
Feb 18 at 16:02
add a comment |
If you just want to be able to take 1 or 2 values then the easiest way is to mark the second value as optional :
sub some-test( $v1, $v2? ) { ... }
Or you can define a default value :
sub some-test( $v1, $v2="default" ) { ... }
Or if you want any number of values (1 or more) you can use a slurpy with a where clause :
sub some-test( *@v where *.elems > 0 ) { ... }
this fails withConstraint type check failed in binding to parameter '@v'; expected anonymous constraint to be met but got Array ($["a", "b"])
:-(
– con
Feb 15 at 16:11
Can you share the subroutine definition you used? $["a","b"] should match the where clause of *.elems > 0 (as it's got 2 elements).
– Scimon
Feb 15 at 16:15
sub some-test (*@v where *.elems < 0) { for @v -> $v { put $v } } my $x = 'a'; my $y = 'b'; some-test($x, $y);
– con
Feb 15 at 16:35
So you are testing elems < 0 which is true arrays with negative elements in. Instead of you test for elems > 0 then you won't accept an empty array but will accept others
– Scimon
Feb 15 at 16:41
Another option to get at least one value is to usesub some-test($v1, *@rest) { }
– moritz
Feb 16 at 13:04
add a comment |
If you just want to be able to take 1 or 2 values then the easiest way is to mark the second value as optional :
sub some-test( $v1, $v2? ) { ... }
Or you can define a default value :
sub some-test( $v1, $v2="default" ) { ... }
Or if you want any number of values (1 or more) you can use a slurpy with a where clause :
sub some-test( *@v where *.elems > 0 ) { ... }
this fails withConstraint type check failed in binding to parameter '@v'; expected anonymous constraint to be met but got Array ($["a", "b"])
:-(
– con
Feb 15 at 16:11
Can you share the subroutine definition you used? $["a","b"] should match the where clause of *.elems > 0 (as it's got 2 elements).
– Scimon
Feb 15 at 16:15
sub some-test (*@v where *.elems < 0) { for @v -> $v { put $v } } my $x = 'a'; my $y = 'b'; some-test($x, $y);
– con
Feb 15 at 16:35
So you are testing elems < 0 which is true arrays with negative elements in. Instead of you test for elems > 0 then you won't accept an empty array but will accept others
– Scimon
Feb 15 at 16:41
Another option to get at least one value is to usesub some-test($v1, *@rest) { }
– moritz
Feb 16 at 13:04
add a comment |
If you just want to be able to take 1 or 2 values then the easiest way is to mark the second value as optional :
sub some-test( $v1, $v2? ) { ... }
Or you can define a default value :
sub some-test( $v1, $v2="default" ) { ... }
Or if you want any number of values (1 or more) you can use a slurpy with a where clause :
sub some-test( *@v where *.elems > 0 ) { ... }
If you just want to be able to take 1 or 2 values then the easiest way is to mark the second value as optional :
sub some-test( $v1, $v2? ) { ... }
Or you can define a default value :
sub some-test( $v1, $v2="default" ) { ... }
Or if you want any number of values (1 or more) you can use a slurpy with a where clause :
sub some-test( *@v where *.elems > 0 ) { ... }
answered Feb 15 at 15:59
ScimonScimon
1,8771311
1,8771311
this fails withConstraint type check failed in binding to parameter '@v'; expected anonymous constraint to be met but got Array ($["a", "b"])
:-(
– con
Feb 15 at 16:11
Can you share the subroutine definition you used? $["a","b"] should match the where clause of *.elems > 0 (as it's got 2 elements).
– Scimon
Feb 15 at 16:15
sub some-test (*@v where *.elems < 0) { for @v -> $v { put $v } } my $x = 'a'; my $y = 'b'; some-test($x, $y);
– con
Feb 15 at 16:35
So you are testing elems < 0 which is true arrays with negative elements in. Instead of you test for elems > 0 then you won't accept an empty array but will accept others
– Scimon
Feb 15 at 16:41
Another option to get at least one value is to usesub some-test($v1, *@rest) { }
– moritz
Feb 16 at 13:04
add a comment |
this fails withConstraint type check failed in binding to parameter '@v'; expected anonymous constraint to be met but got Array ($["a", "b"])
:-(
– con
Feb 15 at 16:11
Can you share the subroutine definition you used? $["a","b"] should match the where clause of *.elems > 0 (as it's got 2 elements).
– Scimon
Feb 15 at 16:15
sub some-test (*@v where *.elems < 0) { for @v -> $v { put $v } } my $x = 'a'; my $y = 'b'; some-test($x, $y);
– con
Feb 15 at 16:35
So you are testing elems < 0 which is true arrays with negative elements in. Instead of you test for elems > 0 then you won't accept an empty array but will accept others
– Scimon
Feb 15 at 16:41
Another option to get at least one value is to usesub some-test($v1, *@rest) { }
– moritz
Feb 16 at 13:04
this fails with
Constraint type check failed in binding to parameter '@v'; expected anonymous constraint to be met but got Array ($["a", "b"])
:-(– con
Feb 15 at 16:11
this fails with
Constraint type check failed in binding to parameter '@v'; expected anonymous constraint to be met but got Array ($["a", "b"])
:-(– con
Feb 15 at 16:11
Can you share the subroutine definition you used? $["a","b"] should match the where clause of *.elems > 0 (as it's got 2 elements).
– Scimon
Feb 15 at 16:15
Can you share the subroutine definition you used? $["a","b"] should match the where clause of *.elems > 0 (as it's got 2 elements).
– Scimon
Feb 15 at 16:15
sub some-test (*@v where *.elems < 0) { for @v -> $v { put $v } } my $x = 'a'; my $y = 'b'; some-test($x, $y);
– con
Feb 15 at 16:35
sub some-test (*@v where *.elems < 0) { for @v -> $v { put $v } } my $x = 'a'; my $y = 'b'; some-test($x, $y);
– con
Feb 15 at 16:35
So you are testing elems < 0 which is true arrays with negative elements in. Instead of you test for elems > 0 then you won't accept an empty array but will accept others
– Scimon
Feb 15 at 16:41
So you are testing elems < 0 which is true arrays with negative elements in. Instead of you test for elems > 0 then you won't accept an empty array but will accept others
– Scimon
Feb 15 at 16:41
Another option to get at least one value is to use
sub some-test($v1, *@rest) { }
– moritz
Feb 16 at 13:04
Another option to get at least one value is to use
sub some-test($v1, *@rest) { }
– moritz
Feb 16 at 13:04
add a comment |
You can use signature destructuring
sub some-test(*@all [$first, *@rest]) { ... } # must have 1 or more parameters
add a comment |
You can use signature destructuring
sub some-test(*@all [$first, *@rest]) { ... } # must have 1 or more parameters
add a comment |
You can use signature destructuring
sub some-test(*@all [$first, *@rest]) { ... } # must have 1 or more parameters
You can use signature destructuring
sub some-test(*@all [$first, *@rest]) { ... } # must have 1 or more parameters
answered Feb 15 at 16:39
ugexeugexe
2,017923
2,017923
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54712440%2fperl6-variable-number-of-arguments-to-function-subroutine%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
So $v3 is a different value to $v1?
– Scimon
Feb 15 at 15:52
@Scimon all the variables given to the function/subroutine should be independent, so yes, $v3 should be different from $v1
– con
Feb 15 at 15:56