Reputation: 1549
I have two subroutines that output a prompt. One is a facade subroutine and another is the main subroutine as shown below:
sub facade(@)
{
my ($prompt) = @_;
return main("FLAG", $prompt);
}
sub main($@)
{
my ($flags) = shift;
my ($prompt) = @_;
...<functionality to print a menu prompt>...
}
What I want to happen is to output something like the menu below:
Choose an option
X) Exit
1) Green
2) Blue
3) Red
4) Purple (only if "FLAG" is passed in)
What actually happens is the following:
Choose an option
X) Exit
1) Green
2) Blue
3) Red
4) FLAG
This means that the first argument is for some reason absorbed into the "@" itself and not into the logic of my function which says "if this flag exists, output a 4th option". This leads to my question:
How do I prevent the first "$" argument in a subroutine from being absorbed into "@_"?
Upvotes: 0
Views: 169
Reputation: 386461
Your question isn't very clear. I think you have a sub that has a required parameter ($prompt
) and one optional parameter ($flag
), and that you're basically asking how to implement that.
It's easiest if optional parameter come after required ones.
sub main($;$) {
my ($prompt, $flag) = @_;
...
if ($flag) { ... }
...
}
main($prompt); # $flag = undef, which is false.
main($prompt, 0); # $flag = 0, which is false.
main($prompt, 1); # $flag = 1, which is true.
The above will assign undef
to $flag
if only one argument was provided. You could evaluate @_
in scalar context to get the number of arguments provided to check if $flags
was provided, but it's not necessary here because undef
is a good default.
If a sub accepts multiple options, it's probably best to provide them by name as follows:
sub main($%) {
my ($prompt, %opts) = @_;
...
if ($opts{purple}) { ... }
...
}
main($prompt);
main($prompt, purple => 1);
Note there are problems to using prototypes (including the fact that they can be silently ignored), so you should probably avoid using them even though I left them in.
Upvotes: 4