Perl noob.
I am having trouble understanding returning an array value from a subroutine in a module.
The script has the following:
print "Enter your first and last name.\n";
chomp(my $fullname = <STDIN>); #input is 'testing this' all lower case
Jhusbands::Loginpass->check_name($fullname);
print "$fullname\n";
The module includes the following subroutine:
sub check_name {
my $class = shift;
if ($_[0] =~ /^\w+\s+\w+$/ ) {
@_ = split( / /, $_[0]);
foreach $_ (@_) {
$_ = ucfirst lc for @_;
@_ = join(" ", @_);
print Dumper(@_) . "\n";
return @_;
}
}
}
I am taking the name, checking it for only first and last (I'll get to else statements later), splitting it, correcting the case, and joining again. Dumper displays the final array as:
$VAR1 = 'Testing This';
So it appears to be working that far. However, the return vale for $fullname
in the script displays the all lower case:
testing this
Why is it not taking the corrected uppercase variable that Dumper displays as the last array iteration?
You don't assign the return to anything. Also, the sub manipulates @_
which it shouldn't be doing, as discussed below. It can also be greatly simplified
sub check_name {
my ($class, $name) = @_;
if ($name =~ /^\w+\s+\w+$/) {
return join ' ', map { ucfirst lc } split ' ', $name;
}
return; # returns "undef" (as input wasn't in expected format)
}
Then the caller can do
my $fullname = Jhusbands::Loginpass->check_name($name);
print "$fullname\n" if $fullname;
A sub's return should always be checked but in this case even more so, since it processes its input conditionally. I renamed the input to sub (to $name
), for clarity.
If the code in the sub is meant to change the $fullname
by writing directly to @_
(and you had no return for that reason), that fails since after the specific manipulations $_[0]
isn't any more aliased to the argument that was passed.
In any case, doing that is very tricky, can lead to opaque code -- and is unneeded. To directly change the argument pass it as a reference and write to it. However, it is probably far clearer and less error prone to return the result in this case.
It should be noted that the above name "processing" runs into the standard problems with processing of names, due to their bewildering variety. If this needs to be comprehensive then the name parsing should be dispatched to a rounded library (or procedure) that can deal with the possible dirersity.
Thanks to ikegami for comments bringing this up with examples, as well as a more direct way:
$name =~ s/(\w+)/\u\L$1/g;
return $name;
which with /r
introduced in v5.14 can be written as
return $name =~ s/(\w+)/\u\L$1/gr;
If $name
has no word-characters (\w
) and there is no match this returns the same string.