Subroutines – Get Efficient
Total Page:16
File Type:pdf, Size:1020Kb
Subroutines – get efficient So far: The code we have looked at so far has been sequential: Subroutines – getting efficient with Perl do this; do that; now do something; finish; Problem Bela Tiwari You need something to be done over and over, perhaps slightly [email protected] differently depending on the context Solution Environmental Genomics Thematic Programme Put the code in a subroutine and call the subroutine whenever needed. Data Centre http://envgen.nox.ac.uk Syntax: There are a number of correct ways you can define and use Subroutines – get efficient subroutines. One is: A subroutine is a named block of code that can be executed as many times #!/usr/bin/perl as you wish. some code here; some more here; An artificial example: lalala(); #declare and call the subroutine Instead of: a bit more code here; print “Hello everyone!”; exit(); #explicitly exit the program ############ You could use: sub lalala { #define the subroutine sub hello_sub { print "Hello everyone!\n“; } #subroutine definition code to define what lalala does; #code defining the functionality of lalala more defining lalala; &hello_sub; #call the subroutine return(); #end of subroutine – return to the program } Syntax: Outline review of previous slide: Subroutines – get efficient Syntax: #!/usr/bin/perl Permutations on the theme: lalala(); #call the subroutine Defining the whole subroutine within the script when it is first needed: sub hello_sub {print “Hello everyone\n”;} ########### sub lalala { #define the subroutine The use of an ampersand to call the subroutine: &hello_sub; return(); #end of subroutine – return to the program } Note: There are subtle differences in the syntax allowed and required by Perl depending on how you declare/define/call your subroutines. 1 #!/usr/bin/perl Subroutines – get efficient my $thing1 = “something”; my $thing2 = “anotherthing”; Parameters and Return Values some code here; some more here; Parameters giving the subroutine values/information to work with my $whatIwant = lalala($thing1, $thing2); #call the subroutine here given by putting the required information in between the #and put whatever is returned into subroutine brackets when the subroutine is called () #the variable $whatIwant a bit more code here; e.g. lalala($firsthing, $secondthing) exit(); #explicitly exit the program Return values getting information out of the subroutine ######### subroutines always return a value sub lalala { #define the subroutine if you provide a return statement with no explicit value to code to get the values of $thing1 and $thing2 into subroutine variables send back, it will return true (1) if it succeeded code to define what lalala does; #code defining lalala code to give a value to a variable called $output ; if you provide no return statement, the subroutine will return the value of the last statement it evaluated return($output); #end of subroutine – return the value $output you can program subroutines to return values of } your choice $whatIwant = lalala($thing1, $thing2); $thing1 and $thing2 are now in an array called @_ $thing1 is now $_[0] #the first element of @_ $thing2 is now $_[1] #the second element of @ ######### my $whatIwant = lalala($thing1, $thing2); sub lalala { #need to retrieve the values from @_ array and put them into variables #within our subroutine ######### my $funcvar1 = shift (@_); #take the first element of the array (has the same value as $thing1) sub lalala { code to get the values of $thing1 and $thing2 into subroutine variables my $funcvar2 = shift (@_); #take the second element of the array (the same value as $thing2) return(); return(); } } $whatIwant = lalala($thing1, $thing2); ######### $whatIwant = lalala($thing1, $thing2); sub lalala { my $funcvar1 = shift; #where is @_ Hey, wait! Does that look familiar? #$funcvar1 has the value of $thing1 my $funcvar2 = shift; #where is @_ $seq_length = length($seq); #$funcvar2 has the value of $thing2 $last_thing = pop(@array1); return(); } Functions are really built-in subroutines!! ######################################################## Subroutines are just you writing your own functions! Even easier: (or using someone else’s functions) my ($funcvar1, $funcvar2) = @_; 2 More on getting values out of a subroutine Subroutines so far: Recall: Return values getting information out of the subroutine •What a subroutine is subroutines always return a value •How to call a subroutine if you provide a return statement with no explicit value to •How to pass parameters into a subroutine send back, it will return true (1) if it succeeded if you provide no return statement, the subroutine will return the value of the last statement it evaluated you can program subroutines to return values of Now: your choice ############## More on getting values out of a subroutine sub lalala { code to define what lalala does; more defining lalala; return(); # if lalala executes successfully, this would return the value 1 to your main program . } More on getting values out of a subroutine More on getting values out of a subroutine You can return a single value from a subroutine: If you do not specify a return statement, the subroutine will return the result of the final statement evaluated: sub lalala { code to give a value to a variable called $output ; sub lalala { return($output); #end of subroutine – return the value of $output bunchacode; } morecode; $total = $thing1 + $thing2; # $total will be returned in this case } Even more on getting values out of a subroutine More on “my”, variables and subroutines You can return a single value from a subroutine. You can return multiple values from a subroutine using a list. E.g. return (@array_of_values); So far we have declared our variables using “my” return ($val1, $val2); So far we have written “use strict” at the top of our scripts An Aside: When you are returning something very large, you can just give its address, So far we have glossed over why we do this…. rather than pass the whole thing in or out of the subroutine. That is, you can specify the location of values instead of their names. In other words, if you return the location of an array, you can use this location to access all the elements of that array 3 More on “my”, variables and subroutines #!/usr/bin/perl #simplesubfunc.pl use strict; use warnings; Variables declared using my are visible only to the block my ($number1, $number2); #declare scalar variables of code { } they are in. print "Enter a number: "; #main chomp ($number1 = (<STDIN>)); #body print "Enter another number :"; #of So, if you declare them at the top of a script, the whole chomp ($number2 = (<STDIN>)); #code script can see them. my $total = addition_sub ($number1, $number2); #go to subroutine #$total collects return value print "$number1 plus $number2 equals $total\n"; If you declare them inside a subroutine, only the exit(); subroutine can see them. ########## sub addition_sub { The term “lexical scoping” essentially refers to coding such that variables are “seen” my $number3 = $number1 + $number2; #declare a variable and add the numbers only where they should be, so that changing the values of variables in certain parts of return ($number3); #$number3 is only “seen” by the subroutine your program doesn’t inadvertently affect what happens to those variables in other #return value of $number3 from subroutine parts of your program. } #!/usr/bin/perl #simplesubfunc.pl #!/usr/bin/perl #simplesubfunc2.pl use strict; use strict; use warnings; use warnings; my ($number1, $number2); #declare scalar variables my ($number1, $number2, $number3 ); #now $number3 seen by #whole program print "Enter a number: "; #main chomp ($number1 = (<STDIN>)); #body print "Enter a number: "; print "Enter another number :"; #of chomp ($number1 = (<STDIN>)); chomp ($number2 = (<STDIN>)); #code print "Enter another number :"; chomp ($number2 = (<STDIN>)); my $total = addition_sub ($number1, $number2); #go to subroutine #$total collects return value addition_sub (); #nothing catches the return value print "$number1 plus $number2 equals $total\n"; #don’t need $number1 or $number2 b/c sub knows about them exit(); print "$number1 plus $number2 equals $number3\n"; ########## exit(); sub addition_sub { ########## my $number3 = $number1 + $number2; #declare a var and add the numbers #$number3 is only “seen” by the subroutine sub addition_sub { #no explicit return statement $number3 = $number1 + $number2; #don’t declare $number3 with my } #no explicit return statement } More on “my”, variables and subroutines – catinhat2.pl More on “my”, variables and subroutines – catinhat.pl #!/usr/bin/perl Recall: use strict; Variables declared using my are visible only to the block of code they are in. use warnings; my $catinhat = 5; # declare $catinhat in main program Thus – true for subroutines, but also foreach loops , while loops , if/else statements – anything where a block of code { } is defined. print “\nThe catinhat in my main program is $catinhat\n”; #!/usr/bin/perl subrout($catinhat); #pass value of main prog $catinhat to subrout use strict; use warnings; print “\nThe catinhat in my main program is still equal to $catinhat\n”; my $catinhat = 5; #declare and give value 5 to main prog’s $catinhat exit(); my @numarray = (1,2,3,4,5); ########### print “\nThe catinhat in my main program is $catinhat\n”; sub subrout { my $catinhat = shift; #declare $catinhat in subroutine foreach my $catinhat (@numarray) { #declare foreach block’s $catinhat print “\nThe catinhat in my subroutine is $catinhat\n”; $catinhat +=5; #play with foreach block’s $catinhat