MaroonBalloon has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I realize this may a bit of code...I am including a large portion because I am having trouble returning the variable $ofound so that I may print it (and use it for more calculation...) outside of the subroutine.

Any thoughts?

THANKS!

my $search =$ARGV[0]; summary_o(); #summary_no(); my @count; my @matches; my $ofound =""; #my $nfound; sub summary_o { open INPUT,"/home/perlcourse/derek/final/oncogenic_E1.txt" or die +$!; my $count =-1; #I have added a last ">" symbol into my text + file to make this code run. my $seq =(); my $hits; my $header; my $pos; my %o; my $contains =0; my $searchline; my @poz; while (my $line =<INPUT>) { if ($line =~m/^>/) { if ($seq) { $o{$header} = "$seq"; } $count++; print "\n\n"; print "$line"; $header = "$line"; $seq=(); } else { chomp $line; print $line; $seq .= "$line"; } #Q: How many times is the $search found inside all the hash values?? } while (my ($key,$value) = each(%o)) { $hits++ while $value =~ /$search/gi; } #Q: How many hash values contain at least one “$search” inside of them +? #################### #FOREACH LOOP START# #################### foreach my $key (keys %o) { $searchline = $o{$key}; if ($searchline =~ /$search/gi) { $contains ++; } } ################### # FOREACH LOOP END# ################### print "\n\t\t*****Summary of input*****\n"; if ($hits) { print "\nThere are " . $hits. " matches of " .$search ." in " . +$count ." sequences."; } else { print "\n\nThere are 0 matches in " . $count . " sequences."; } print "\n$contains" . " sequences out of ".$count." contain the qu +ery sequence at least once." if ($contains); print "\n\n"; if ($count) { my $ofound = ($hits)/($count); } elsif ($count ==0) { } close (INPUT); #print $ofound; print "\n"; return $ofound; }

Replies are listed 'Best First'.
Re: Returning from a subroutine.
by jwkrahn (Abbot) on Dec 13, 2009 at 07:35 UTC

    You should start your Perl program with these two pragmas:

    use warnings; use strict;

    They will help you find mistakes in your code, like why $ofound is not visible at the end of the subroutine.

    12 my $seq =();

    It looks like you are attempting to assign a list to a scalar variable, but that is impossible as there is no such thing as a list in scalar context.

    23 $o{$header} = "$seq"; 27 print "$line"; 28 $header = "$line"; 33 $seq .= "$line";

    What's wrong with always quoting "$vars"?

    35 #Q: How many times is the $search found inside all the hash va +lues?? 37 while (my ($key,$value) = each(%o)) { 38 $hits++ while $value =~ /$search/gi; 39 } 40 41 #Q: How many hash values contain at least one <93>$search<94> +inside of them? 42 #################### 43 #FOREACH LOOP START# 44 #################### 45 foreach my $key (keys %o) { 46 $searchline = $o{$key}; 47 if ($searchline =~ /$search/gi) { 48 $contains ++; 49 } 50 } 51 ################### 52 # FOREACH LOOP END# 53 ###################

    These two loops do the same thing.    So that code could be simplified to:

    my $hits; $hits += () = /$search/gi for values %o; my $contains = $hits;
    68 if ($count) { 69 my $ofound = ($hits)/($count); 70 } elsif ($count ==0) { 71 }

    my creates a variable that is lexically scoped inside the current block or file so $ofound can only be seen on line 69 of your program.    You need to declare it outside of that block:

    my $ofound; if ($count) { $ofound = ($hits)/($count); } elsif ($count ==0) { }

    Or just return that value:

    if ($count) { return $hits / $count; } elsif ($count ==0) { }
      35 #Q: How many times is the $search found inside all the hash values? +? ... 41 #Q: How many hash values contain at least one "$search" inside of t +hem? ...
      These two loops do the same thing. ...

      But 'how many times is X found in all hash values?' and 'how many values contain at least one X?' are two different questions. A hash might have many values, but only one or two of those values might have an X. However, the total number of Xs in those few values might be very many.

      >perl -wMstrict -le "my %hash = ( x => '---------', y => '-----x---', z => '-XxX-x-X-', ); my $Xs_in_values = 0; $Xs_in_values += () = /X/gi for values %hash; print $Xs_in_values; my $values_with_X = grep /X/i, values %hash; print $values_with_X; " 6 2

      Update: The code of the OP for answering these two questions seems correct, although a bit klunky.

      You should start your Perl program with these two pragmas:
      use warnings; use strict;
      They will help you find mistakes in your code, like why $ofound is not visible at the end of the subroutine.
      EWRONGDOGMA

      Had the OP not used strict, and not use my, he wouldn't have had the problem. His problem is the overuse of my, as you point out. Adding either use warning; or use strict; does diddly-squat to solve the problem.