Alternatively, you can use shift:sub hello { ($name) = @_; # argument assigned to a one member list print("Hello $name\n"); } hello("Reinier");# output: Hello Reinier
In case of multiple arguments, process @_ e.g. in a for loop:sub hello { $name = shift; print("Hello $name\n"); } hello("Reinier"); # output: Hello Reinier
Returning a calculated value:sub hello_all { print("Hello $_\n") for @_; } hello_all( qw(Reinier Sebastian Daniel Florence) ); # output: Hello Reinier Hello Sebastian etc. on separate lines
sub add {
($x, $y) = @_;# argument assigned to a list
return ($x + $y);# the subroutine returns the sum of $x and $y, which is equal to $_[0] + $_[1]
}
$sum = add(2,3);
print($sum . "\n");# output: 5
Notice that it can be really inefficient to pass an array as argument. Later we'll discuss a better method.sub add {
$sum = 0;
foreach $arg (@_) {
$sum += $arg;
}
return ($sum);
}
@list = (1, 2, 3, 4, 5);
$sum = add(@list);# notice $sum is another variable than the local one within the subroutine 'add'
print($sum . "\n");# output: 15
sub add {
$sum = 0;
$sum += $_ foreach (@_);
return ($sum);
}
sub find_arg {
print("value first argument: " . $_[0] . "\n");
print("value first argument: " . shift . "\n");
print("value last argument: " . $_[$#_] . "\n");
print("value last argument: " . pop . "\n");
}
sub multiply {
($x, $y) = @_;
return ($x * $y);
}
print(multiply(2,3) . "\n");
sub power {
($x, $y) = @_;
return ($x ** $y);
}
for ($i = 0;$i < 10; $i++) {
print($i . " " . power(2,$i) . "\n");
}
sub calculate {
($x, $y) = @_;
return ($x + $y, $x * $y);
}
($sum, $mult) = calculate(2, 3);
print("Sum: " . $sum . "\n");
print("Multiplication: " . $mult . "\n");
Another example:sub favorite_color { return $_[0] || "red"; } print(favorite_color("green") . "\n"); # prints: green print(favorite_color() . "\n");# prints: red
sub sum_of_powers { my ($end, $power, $start) = @_; $power || ($power = 2); # or: $power ||= 2; $start ||= 1; my $sum = 0; for my $i ($start .. $end) { $sum += $i ** $power; } return($sum); } print(sum_of_powers(10), "\n";# 385 print(sum_of_powers(10, 3), "\n";# 3025 print(sum_of_powers(10, 3, 5), "\n";# 2925
There is another thing:sub modify {
$_[0] = 3;
$_[1] = 4;
return ($_[0], $_[1]);
}
$var1 = 1;
$var2 = 2;
modify($var1, $var2);
print($var1 . " " . $var2 . "\n");# prints: 3 4
will work. However, the following gives an error, because($a, $b, @c) = @_
(@c, $a, $b) = @_
1. How to use shift or shift()?
a. To remove the first element of an array:
b. To get and remove the first argument of @_ in a function:@arr = (1,2,3); print(shift(@arr)); # output: 1 print("@arr");# output: 2 3
c. To get and remove the first argument of @ARGV in file scope:sub greeting { print("Hello " . shift); # or shift(@_) } greeting("Reinier", "Daniel");# output: Hello Reinier
2. How to handle many arguments in a subroutine?# contents of test.pl: print(shift);# invoke this test.pl with e.g. two arguments test.pl arg1 arg2# output: arg1
The best solution is "named arguments" using a hash reference. Study this code:image_link ("https://www.reiniermaliepaard.nl", 0, "at home", "img/at_home.jpeg", 600, 452);
3. How to check/validate arguments (function/command line)?sub image_link { ($args) = @_; return $img_link = '<a href = '$args->{href}'><img ' . 'border = '$args->{img_border}' alt = '$args->{img_alt} ' . 'src = '$args->{img_src}' width= '$args->{img_width} ' . 'height = '$args->{img_height}'></a>'; } $img_link_def = image_link ({ href => 'https://www.reiniermaliepaard.nl', img_border => 0, img_alt => 'at home', img_src => 'img/at_home.jpeg', img_width => 600, img_height => 452, }); print($img_link_def); # <a href = "https://www.reiniermaliepaard.nl"><img border = "0" alt = "at home" src = "img/at_home.jpeg" width= "600" height = "452"></a>
b. Check the numbers arguments: evaluate the special variables in scalar context and compare.if (! @ARGV) { print "No command-line arguments provided.\n"; } if (! @_) { print "No function arguments provided.\n"; }
c. Check if the arguments (command line) meet certain criteria: same type.if (@ARGV != 2){ die "Expected two arguments: @ARGV"; } if (@_ != 3){ die "Expected three arguments: @_; }
d. Check if the arguments (command line) meet certain criteria: different type.if (@ARGV) { for(@ARGV){ die "Error: expected only positive integers: $_" unless /^\d+$/; } } # the next code saved as add_no.pl #!/usr/bin/perl sub add_2_numbers { if (@_ == 2) { for(@_){ die "Error: expected only positive integers: @_" unless /^\d+$/; } } else { die "Error: expected two positive integers: @_"; } } add_2_numbers (1, -2);# Error: expected two positive integers: -2 at add_no.pl line 7. add_2_numbers (1, -2, 3);# Error: expected two positive integers: 1 -2 3 at add_no.pl line 12.
e. Params::ValidationCompiler.#!/usr/bin/perl # Check if the correct number of arguments is provided if (@ARGV != 2) { die("Usage: $0\n"); } # Capture command-line arguments ($arg1, $arg2) = @ARGV;# Validate argument 1 (e.g., it should be a positive integer) if ($arg1 !~ /^\d+$/ || $arg1 <= 0) { die("Argument 1 must be a positive integer.\n"); }# Validate argument 2 (e.g., it should be a string) if ($arg2 !~ /^[A-Za-z]+$/) { die("Argument 2 must contain only letters.\n"); }# If all validations pass, proceed with your script logic print "Argument 1: $arg1\n"; print "Argument 2: $arg2\n";# Your application logic goes here
sub str2int { $arg = shift; print($arg," : ", ($arg + 0), "\n"); } $str = "00012345"; # 12345 str2int($str); $str = "+0678";# 678 str2int($str); $str = "0000090.123";# 90.123 str2int($str); $str = "+00456.789";# 456.789 str2int($str); $str = "0.123";# 0.123 str2int($str); $str = "000.123";# 0.123 str2int($str); $str = ".123";# 0.123 str2int($str);