Question

I've just started learning perl and I am am confused by this exercise (from Learning Perl Chapter 4).

At the beginning of the greet() subroutine, I am trying to assign the argument $_ to my $name (my $name = $_) variable but it doesn't work. The book says to use "my name = shift;" but I don't understand why. shift is used to remove a value from an array and my argument is not an array as far as I can tell, it's a string inside a scalar!

Could anyone explain what I'm not understanding?

Thanks! Here is the entirety of the code.

use 5.012;
use warnings;
use utf8;

sub greet {
   my $name = $_;
   state $last_person ;
   if (defined $last_person ) {
          print "Hi $name! $last_person is also here!\n";

   } else {
          print "Hi $name! You are the first one here!\n";
   }
   $last_person = $name;
}

greet( 'Fred' );
greet( 'Barney' );
greet( 'Wilma' );
greet( 'Betty' );
Was it helpful?

Solution

In chapter 4 of Learning Perl (6th edition) there's a section called Arguments. There it states the following:

This means that the first subroutine parameter is in $_[0], the second one is stored in $_[1], and so on. But - and here's an important note - these variables have nothing whatsoever to do with the $_ variable, any more than $dino[3] (an element of the @dino array) has to do with $dino (a completely distinct scalar variable). It's just that the parameter list must be in some array variable for your subroutine to use it, and Perl uses the @_ for this purpose.

(Learning Perl, 6th Edition, Chapter 4)

So you're probably mistaken in using $_, when you should either be using my $name = $_[0];, or my $name = shift @_;. As a convenience, when you're inside of a subroutine, shift defaults to shifting off of @_ if you provide no explicit argument, so the common idiom is to say my $name = shift;.

For those in need of another resource, perldoc perlintro also has a good (and appropriately brief) explanation of passing parameters to subroutines and accessing them via @_ or shift.

Here's a brief snippet from perlintro:

What's that shift? Well, the arguments to a subroutine are available to us as a special array called @_ (see perlvar for more on that). The default argument to the shift function just happens to be @_ . So my $logmessage = shift; shifts the first item off the list of arguments and assigns it to $logmessage.

OTHER TIPS

It sounds like you have skipped part of the chapter. Did you read the section on Arguments (on page 66 in the latest, sixth edition). It says

Perl passes the list to the subroutine; that is, Perl makes the list available for the subroutine to use however it needs to. Of course, you have to store this list somewhere, so Perl automatically stores the parameter list (another name for the argument list) in the special array variable named @_ for the duration of the subroutine. You can access this array to determine both the number of arguments and the value of those arguments.

This means that the first subroutine parameter is in $_[0], the second one is stored in $_[1], and so on. But—and here’s an important note—these variables have nothing whatsoever to do with the $_ variable, any more than $dino[3] (an element of the @dino array) has to do with $dino (a completely distinct scalar variable). It’s just that the parameter list must be in some array variable for your subroutine to use it, and Perl uses the array @_ for this purpose.

The arguments of all perl subroutines live inside an array of parameters, which your book fails to mention.

This array is @_, and in your case by shift you shall get your first argument, which will be a scalar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top