Неопределенные подпрограммы и основная ошибка в Perl

Я пытаюсь извлечь последовательность ДНК из этого файла FASTA до указанной длины оснований в строке, скажем, 40.

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

Используя этот модуль Perl (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;

И основной сценарий

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;

Это ошибка, которую я получаю

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

Может ли кто-нибудь просветить меня, в какой части я сделал неправильно?


person zebra    schedule 15.11.2014    source источник
comment
Вам нужно либо префиксировать ваши вызовы функций в fasta.pm с помощью fasta:: - т.е. написать fasta::read_fasta($filename) и т. д. - либо вам нужно изменить fasta.pm, чтобы экспортировать функцию, которую вы хотите сделать доступной без префикс.   -  person asjo    schedule 15.11.2014
comment
Обычно только собственные пакеты Perls начинаются со строчной буквы, поэтому вы можете переименовать свой .pm.   -  person asjo    schedule 15.11.2014
comment
Наконец, стоит взглянуть на BioPerl для анализа/генерации форматов, связанных с биоинформатикой: bioperl.org   -  person asjo    schedule 15.11.2014
comment
хотя последняя часть должна работать. Явный вызов с помощью Fasta:: работает и всегда работал у меня. Пожалуйста, опубликуйте конкретное сообщение об ошибке для этого.   -  person bytepusher    schedule 15.11.2014
comment
Сообщение об ошибке для части Fasta:: обновлено в посте   -  person zebra    schedule 15.11.2014
comment
просто используйте мою дополнительную декларацию, которую я отредактировал. Аналогично для других сабвуферов.   -  person bytepusher    schedule 15.11.2014
comment
Вы пытались использовать прототипы perl. Я бы посоветовал вам не делать этого. Если вы хотите, чтобы пользователи знали, что вводить, оставлять комментарии, pod или что-то подобное, это не поддерживается должным образом (относительно sub method ( $arg ){)   -  person bytepusher    schedule 15.11.2014
comment
Я обновил свой текущий основной скрипт и Fasta.pm. Все еще получаю неопределенную подпрограмму и основную ошибку. И если я добавляю префикс Fasta:: в основной скрипт, я получаю сообщение о том, что у меня недостаточно аргументов   -  person zebra    schedule 15.11.2014
comment
Откуда взялся Fasta.pm? Есть серьезные проблемы с ним, которые должны быть исправлены.   -  person Borodin    schedule 15.11.2014
comment
Пожалуйста, не редактируйте свой вопрос, чтобы включить в него советы, которые вам дали другие люди: это делает бессмысленными ответы и комментарии.   -  person Borodin    schedule 15.11.2014
comment
ты проигнорировал меня. sub read_fasta { my $filename = @_; не работает. Я сказал вам просто следовать моему примеру в ответе, который я редактировал. Это не так в вашем посте.   -  person bytepusher    schedule 15.11.2014
comment
Я написал это, могу ли я узнать, в чем проблемы   -  person zebra    schedule 15.11.2014
comment
@bytepusher Я следил за обновлениями в своем посте. Я не знал, что мне не следует продолжать редактировать свой пост, как предложил Бородин.   -  person zebra    schedule 15.11.2014
comment
ну, я обновил, чтобы включить our @ISA = qw( Exporter );, который необходим. Прости. Я также отредактировал объяснение, почему $scalar =@_ — это не то, что вам нужно.   -  person bytepusher    schedule 15.11.2014


Ответы (3)


Похоже, вы никуда не денетесь с этим.

Я думаю, что ваш выбор использовать модуль и подпрограммы немного странный, учитывая, что вы вызываете каждую подпрограмму только один раз и действительно соответствует очень небольшому количеству кода.

И ваша программа, и ваш модуль должны начинаться с use strict и use warnings, и вы не можете использовать подобные прототипы в подпрограммах Perl. Включая ряд других ошибок, это намного ближе к тому коду, который вам нужен.

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);
person Borodin    schedule 15.11.2014

Вам нужно либо:

  • добавить в свой модуль:

    use Exporter;
    our @EXPORT = qw ( read_fasta
                       read_seq ); #etc.
    
  • вызовите код в удаленном модуле явно:

    fasta::read_fasta();
    
  • явно импортировать модуль sub:

    use fasta qw ( read_fasta );
    

Также: Общее соглашение о модулях заключается в том, чтобы заглавная буква имени модуля использовалась в верхнем регистре.

person Sobrique    schedule 15.11.2014
comment
Я попробовал некоторые из предложений, но все равно это не работает. Обновил в посте. - person zebra; 15.11.2014
comment
О да. При повторном просмотре определения ваших функций неверны. Потеряйте прототипирование, и если вы назначаете что-то вне @_, вам нужно делать это в контексте списка. Например. my ( $lines_ref ) = @_; - в противном случае это будет только количество элементов в @_ - person Sobrique; 15.11.2014

В Perl, если вы use fasta;, это автоматически не экспортирует все его методы в пространство имен вашей программы. Вместо этого вызовите fasta::read_fasta.

Или: используйте Exporter для автоматического экспорта методов или включите что-то вроде use Fasta qw/read_fasta/.

Например:

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

Использовать:

use Fasta qw/read_fasta read_seq read_seq40/;

Вы также можете заставить Fasta экспортировать все методы автоматически или определить ключевые слова для групповых методов, хотя последнее вызывало у меня некоторые проблемы в прошлом, и я бы рекомендовал его, только если вы уверены, что это стоит возможных проблем.

Если вы хотите сделать доступными все методы:

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

Обратите внимание, что @EXPORT не является @EXPORT_OK. Последний позволяет импортировать их позже (как это сделал я), первый автоматически экспортирует все. Документация, на которую я ссылался, проясняет это.

Я просто заметил кое-что еще. Вы сглаживаете @_ в $filename в read_fasta. Я не уверен, что это работает. Попробуй это:

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

Чтобы объяснить проблему: $filename = @_; означает: сохранить @_ (МАССИВ) в $filename (СКАЛАР). Perl делает это следующим образом: длина ARRAY сохраняется в $filename. Это не то, что вы хотите. Вам нужен первый элемент массива. Это будет $_[0].

Добавлен @ISA, который, вероятно, необходим, ИЛИ используйте комментарий от Borodir.

person bytepusher    schedule 15.11.2014
comment
Я пытался использовать Exporter, но все равно выдавал ту же ошибку. Обновлено в моем посте. - person zebra; 15.11.2014
comment
используйте @EXPORT_OK или @EXPORT. Импортируйте соответственно. Я обновил свой ответ, включив в него метод @EXPORT. - person bytepusher; 15.11.2014
comment
Я точно следовал вашему предложению в файле pm и основном скрипте, но все еще получаю сообщение об ошибке. Оба файла находятся в одном каталоге, и я переименовал fasta.pm в Fasta.pm. Может ли быть другая причина этой ошибки? - person zebra; 15.11.2014
comment
попробуй с our @EXPORT_OK, я без доков взял, но обычно так делаю. Кроме того, меня смутила новая строка после Fasta, зачем вы это туда поставили :/ Просто чтобы быть уверенным: имя пакета и файла всегда должны быть идентичными. - person bytepusher; 15.11.2014
comment
Это заблуждение. Вам также нужно добавить Exporter в массив @ISA, поэтому use base 'Exporter' лучше, чем require. Кроме того, прототипы подпрограмм неверны, и модуль должен запускаться use strict и use warnings. - person Borodin; 15.11.2014
comment
хороший вопрос: где @ISA? как я сказал выше, пропустите прототипы или научитесь их использовать. Я не понимаю, почему пропуск не должен работать. - person bytepusher; 15.11.2014
comment
Почти во всех практических целях вы должны сильно препятствовать использованию прототипов подпрограмм. Кроме того, ответ на Stack Overflow должен быть автономным решением, а не постоянным диалогом, в котором вы и ОП постепенно вносите изменения в свои сообщения. Помните, что основная и первостепенная цель Stack Overflow — сформировать справочник общих проблем программирования и три решения. Если ответ бесполезен никому, кроме ОП, то он не принадлежит переполнению стека. - person Borodin; 15.11.2014
comment
ладно, возможно, я недостаточно сильно отговаривал. Насчет второго: согласен и буду делать впредь, раньше все равно делал лучше. Помимо моего надзора, это функция вопроса, в который вносятся поправки. Я все равно жалею, что начал с этого :/ - person bytepusher; 15.11.2014