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

hello all, I have written a small subroutine and there seems to be some error in passing my variables to the subroutine. I am probably making an easy mistake in syntax, or it has to do with scope and private variables etc? Any help would be appreciated. Below is the part of the script related to the subroutine. In the subroutine the variable $proph is now =1 ?.
########### subroutine get host and taxid ### sub getDetails { my $proph=@_; my $host;my $taxid;my $genNum_proph; print "$proph\tproph inside sub"; my @proph_columns=split(/\_/,$proph); # get host info if ($proph_columns[0] =~ /^FP92/){ $host=$proph_columns[0]; } else { $host=join("_",$proph_columns[0],$proph_columns[1]); } if ($host =~ /^NZ/){ ## for wgs genomes just match first 7 cha +racters as only NZ_XXXX000000 are in tax2locus my $host=substr $host, 0, 7; } print "$host\t"; #get taxid my ($matching_key)= grep { /^$host/ } keys %tax2loc; $taxid=$tax2loc{$matching_key}; ## get number of proteins in the prophage if (exists $genesPerProphGen{$proph}){ $genNum_proph=$genesPerProphGen{$proph}; } else{ print "$proph doesn't have number of genes\n" } return($host,$taxid,$genNum_proph); } ##### Now make table with numbers ##### my $shared_table="$mci_file.sharedTab"; my $genNum_prophA;my $genNum_prophB;my $host_prophA;my $host_prophB; open (OUTs,">$shared_table"); print OUTs "# This table was generated using $0 on\t".scalar(localtime +(time))."\n"; print OUTs "#".join("\t",qw(Proph_genomeA Proph_genomeB hostA taxidA h +ostB taxidB Jacc Prots_Shared Protsin_prophA Protsin_prophB))."\n"; foreach my $prophA (keys %$overlap){ print "$prophA\tfrom overlap\t"; my($hostA,$taxidA,$genNum_prophA)=&getDetails($prophA); foreach my $prophB (keys %{$overlap->{$prophA}}){ my($hostB,$taxidB,$genNum_prophB)=&getDetails($prophB) +; my $A_notShared=$genNum_prophA-$overlap->{$prophA}{$pr +ophB}; my $B_notShared=$genNum_prophB-$overlap->{$prophA}{$pr +ophB}; my $Jac_denom=$overlap->{$prophA}{$prophB}+$A_notShare +d+$B_notShared; my $Jac=$overlap->{$prophA}{$prophB}/$Jac_denom; print OUTs join("\t",$prophA,$prophB,$host_prophA,$tax +idA,$host_prophB,$taxidB,$Jac,$overlap->{$prophA}{$prophB},$genNum_pr +ophA,$genNum_prophA)."\n"; } } close(OUTs);
FP929058_PFPR05 from overlap 1 proph inside sub1_ 1 does +n't have number of genes

Replies are listed 'Best First'.
Re: passing variables to a subroutine
by moritz (Cardinal) on Jul 04, 2012 at 09:02 UTC
    my $proph=@_;

    Using an array (here @_) in scalar context returns the number of elements in the array , and is not what you want.

    Typical solutions are (use only one of them)

    my $proph = shift; # defaults to @_ my ($proph) = @_; # list context instead my $proph = $_[0]; # be explicit about wanting the first element

    See perlintro and perlsub for more details.

      thanks for the explanation, my $proph = $_[0]; # be explicit about wanting the first element helps, I now have some other errors to try and fix

        Just to pound the point completely into the ground:

        >perl -wMstrict -le "F('success'); ;; sub F { my $scalar_context = @_; my ( $list_context ) = @_; ;; print qq{in scalar context: '$scalar_context'}; print qq{in list context: '$list_context'}; } " in scalar context: '1' in list context: 'success'
Re: passing variables to a subroutine
by Corion (Patriarch) on Jul 04, 2012 at 09:04 UTC

    So, what is the error you see, what values are you expecting, and what have you done to diagnose that? Can you reduce your code to a short example that does not need BioPerl?

    Maybe you want to explain what the following line is doing, and compare that with what the line is actually doing when run by Perl:

    # sub getDetails { my $proph=@_;

    As a hint, using print in strategic locations usually helps to verify that values are passed around the way you think they are.