Search code examples
perlbioinformaticssubroutinefasta

Undefined subroutines &main error in Perl


I am trying to extract a DNA sequence from this FASTA file to a specified length of bases per line, say 40.

> sample dna  (This is a typical fasta header.)
agatggcggcgctgaggggtcttgggggctctaggccggccacctactgg
tttgcagcggagacgacgcatggggcctgcgcaataggagtacgctgcct
gggaggcgtgactagaagcggaagtagttgtgggcgcctttgcaaccgcc
tgggacgccgccgagtggtctgtgcaggttcgcgggtcgctggcgggggt

Using this Perl module (fasta.pm):

package fasta;
use strict;

sub read_fasta ($filename) {
    my $filename = @_;
    open (my $FH_IN, "<", $filename) or die "Can't open file: $filename $!";
    my @lines = <$FH_IN>;
    chomp @lines;
    return @lines;
}

sub read_seq (\@lines) {
    my $linesRef = @_;
    my @lines = @{$linesRef};
    my @seq;
    foreach my $line (@lines) {
        if ($line!~ /^>/) {
            print "$line\n";
            push (@seq, $line);
        }
    }
    return @seq;
}

sub print_seq_40 (\@seq) {
    my $linesRef = @_;
    my @lines = @{$linesRef};
    my $seq;
    foreach my $line (@lines) {
        $seq = $seq.$line;
    }

    my $i= 0;
    my $seq_line;
    while (($i+1)*40 < length ($seq)) {
        my $seq_line = substr ($seq, $i*40, 40);
        print "$seq_line\n";
        $i++;
    }
    $seq_line = substr ($seq, $i*40);
    print "$seq_line\n";
}
1;

And the main script is

use strict;
use warnings;
use fasta;

print "What is your filename: ";
my $filename = <STDIN>;
chomp $filename;

my @lines = read_fasta ($filename);
my @seq = read_seq (\@lines);
print_seq_40 (\@seq);
exit;

This is the error I get

Undefined subroutine &main::read_fasta called at q2.pl line 13, <STDIN> line 1.

Can anyone please enlighten me on which part I did wrong?


Solution

  • It looks like you're getting nowhere with this.

    I think your choice to use a module and subroutines is a little strange, given that you call each subroutine only once and the correspond to very little code indeed.

    Both your program and your module need to start with use strict and use warnings, and you cannot use prototypes like that in Perl subroutines. Including a number of other bugs, this is a lot closer to the code that you need.

    package Fasta;
    
    use strict;
    use warnings;
    use 5.010;
    use autodie;
    
    use base 'Exporter';
    
    our @EXPORT = qw/ read_fasta read_seq print_seq_40 /;
    
    sub read_fasta {
      my ($filename) = @_;
    
      open my $fh_in, '<', $filename;
      chomp(my @lines = <$fh_in>);
    
      @lines;
    }
    
    sub read_seq {
      my ($lines_ref) = $_[0];
    
      grep { not /^>/ } @$lines_ref;
    }
    
    sub print_seq_40 {
      my ($lines_ref) = @_;
    
      print "$_\n" for unpack '(A40)*', join '', @$lines_ref;
    }
    
    1;
    

    q2.pl

    use strict;
    use warnings;
    
    use Fasta qw/ read_fasta read_seq print_seq_40 /;
    
    print "What is your filename: ";
    my $filename = <STDIN>;
    chomp $filename;
    
    my @lines = read_fasta($filename);
    my @seq = read_seq(\@lines);
    print_seq_40(\@seq);