Undefined subroutines &main error in Perl

zebra picture zebra · Nov 15, 2014 · Viewed 16.1k times · Source

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?

Answer

bytepusher picture bytepusher · Nov 15, 2014

In Perl, if you use fasta;, this does not automatically export all its methods into the namespace of your program. Call fasta::read_fasta instead.

Or: use Exporter to automatically export methods or enable something like use Fasta qw/read_fasta/.

For example:

package Fasta;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw/read_fasta read_seq read_seq40/;

To use:

use Fasta qw/read_fasta read_seq read_seq40/;

You can also make Fasta export all methods automatically or define keywords to group methods, though the latter has caused me some problems in the past, and I would recommend it only if you are certain it is worth possible trouble.

If you want to make all methods available:

package Fasta;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw/read_fasta read_seq read_seq40/;

Note @EXPORT is not @EXPORT_OK. The latter allows importing them later (as I did), the former automatically exports all. The documentation I linked to makes this clear.

I just noticed something else. You are flattening @_ into $filename in read_fasta. I am not sure this works. Try this:

sub read_fasta {
   my $filename = $_[0]; # or ($filename) = @_; @_ is an array. $filename not.
}

To explain the problem: $filename = @_; means: store @_ ( an ARRAY ) into $filename (a SCALAR). Perl does this in this way: ARRAY length is stored in $filename. That is not what you want. You want the first element of the array. That would be $_[0].

Added @ISA which is probably needed OR use comment by Borodir.