|
The simplest way for reusing code is building subroutines. They allow executing the same code in several places in you application, and they allow it to be executed with different parameters. In some languages there is a distinction between functions and subroutines. In Perl there is only one thing. It is created with the sub keyword and it always returns a value. We often use the two words function and subroutine interchangeably.
Simple function exampleFor example, let's say you'd like to prompt the user and ask a question:
ask_question();
my $answer = get_answer();
# some code
ask_question();
my $second_answer = get_answer();
########## sub declarations come here
sub ask_question {
print "Have we arrived already?";
return;
}
sub get_answer {
my $answer = <STDIN>;
chomp $answer;
return $answer;
}
sub terminate {
die "Hasta La Vista";
}
In the first part of the code we called the "ask_question" function twice and also called the "get_answer" function twice. In the second part of the code, after the #####, we have the declaration of three subroutines. The first one is very simple. It only prints a hard coded string to he screen and then returns nothing. The second combines the read-line operator and chomp into a single function call. It will wait for some input and upon pressing ENTER it will return the string you typed in without the trailing newline. The third one is again very simple but it is never called in the code and thus it is never executed. That's an important point - for people not familiar with functions and subroutines. Their code - regardless of their location in the file - only gets executed when they are called using their name. Just as we called the other two functions.
promptIt would be probably much more interesting to combine the two functions so you can write:
my $answer = prompt();
# some code
my $second_answer = prompt();
sub prompt {
print "Have we arrived already?";
my $answer = <STDIN>;
chomp $answer;
return $answer;
}
Of course in different situations you will want the prompt to display different text. Probably you'd want something like this:
my $first_name = prompt("First name: ");
my $last_name = prompt("Last name: ");
sub prompt {
my ($text) = @_;
print $text;
my $answer = <STDIN>;
chomp $answer;
return $answer;
}
In this example we called the prompt() function twice. In each case we passed a string that is the text of the question we are asking. It was printed. The response collected by the sub and returned to the caller. The new thing in this example is the way we passed the parameter. Even more interesting how the subroutine accepted it. When you call a subroutine you can pass any number of arguments for that subroutine and the values will be placed in the internal @_ variable. This variable belongs to the current subroutine. Each subroutine has its own @_. You could access its elements just as you do with any other array $_[0] being the first element but that's not very nice. It is usually better to copy the values of @_ using a list assignment to internal variables. That's what we did in the above example. with my ($text) = @_;. A common error here is leaving out the parentheses in the assignment.
sub prompt {
my $text = @_; # BAD! this is not what you want!!!
...
}
This will place the array in SCALAR context and in that context it will return the number of elements. So you'll get a number in the $text variable. If this whole context business isn't clear, you can read more about SCALAR and LIST context and get back to here later.
PrototypesCertain languages allow or even require you to create "prototypes" before creating the actual subroutine. No prototypes are needed in Perl. There is something called prototypes available in Perl but they don't do what you would expect and I don't recommend their usage. Certainly not for beginners. There are very few cases when prototypes in Perl are useful.
Parameters or signatureIn Perl 5 you don't need or can declare the signature of a function. That is, the list of expected parameters. This also means that you won't get any parameter checking from the language. There are several modules on CPAN that help creating something that resembles signature. You are welcome to experiment with those.
sub do_somethig() { # BAD !
}
You should not write parentheses after the name of the subroutine when declaring it! Though you can use the parentheses when calling a function:
ParenthesesUsing parenthesis () after the function name is optional if the sub has been already defined and if it is clear what do you mean. So if you load a module via a use statement and it imports a function. You can use that in your code without parentheses. OTOH if you put your function definitions at the end of the script - and I recommend you to do that - then you need to put parentheses when you are calling the function.
Return valuesPerl functions always return a value. Either explicitly by calling return or the result of the last statement. It is recommended to always use explicit call to return. There is even Perl::Critic policy that will check your code and point out every function that does not have explicit return call. If there is nothing to return just call return; without any argument. That will ensure that you really return nothing and not the result of the last statement that will change as you change your subroutine. In the comments, please wrap your code snippets within <pre> </pre> tags and use spaces for indentation. blog comments powered by Disqus |
Follow me: