Когда я должен использовать АВТОЗАГРУЗКУ Perl?

В "Лучших практиках Perl" самая первая строка в разделе по АВТОЗАГРУЗКЕ:

Не используйте АВТОЗАГРУЗКУ

Однако все случаи, которые он описывает, имеют дело с OO или Модулями.

У меня есть одинокий сценарий, в котором, некоторое управление переключателями командной строки который определяются версии конкретных функций. Теперь я знаю, что мог просто взять условные выражения и evals и засунуть их явный наверху моего файла перед всем остальным, но я нахожу это удобным и более чистым для помещения их в АВТОЗАГРУЗКУ в конце файла.

Эта плохая практика / стиль? Если Вы думаете итак, почему, и там другой способ сделать это?

Согласно запросу brian

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

Я не возражаю против некоторой конструктивной критики.

sub AUTOLOAD {
    our $AUTOLOAD;

    (my $method = $AUTOLOAD) =~ s/.*:://s; # remove package name
    if ($method eq 'tcpdump' && $tcpdump) {
        eval q(
        sub tcpdump {
            my $msg = shift;
            warn gf_time()." Thread ".threads->tid().": $msg\n";
        }
        );
    } elsif ($method eq 'loginfo' && $debug) {
        eval q(
        sub loginfo {
            my $msg = shift;
            $msg =~ s/$CRLF/\n/g;
            print gf_time()." Thread ".threads->tid().": $msg\n";
        }
        );
    } elsif ($method eq 'build_get') {
        if ($pipelining) {
            eval q(
            sub build_get {
                my $url = shift;
                my $base = shift;
                $url = "http://".$url unless $url =~ /^http/;
                return "GET $url HTTP/1.1${CRLF}Host: $base$CRLF$CRLF";
            }    
            );
        } else {
            eval q( 
            sub build_get {
                my $url = shift;
                my $base = shift;
                $url = "http://".$url unless $url =~ /^http/;
                return "GET $url HTTP/1.1${CRLF}Host: $base${CRLF}Connection: close$CRLF$CRLF";
            }    
            );
        }    
    } elsif ($method eq 'grow') {
        eval q{ require Convert::Scalar qw(grow); };
        if ($@) {
            eval q( sub grow {} );
        }
        goto &$method;
    } else {
        eval "sub $method {}";
        return;
    }
    die $@ if $@;
    goto &$method;
}

10
задан Robert S. Barnes 17 March 2010 в 21:22
поделиться

3 ответа

Если ваша единственная причина для использования AUTOLOAD - переместить блок в конец, почему бы не поместить его в конец подпрограммы, а затем вызвать его, как только будут определены его зависимые переменные?

sub tcpdump;  # declare your subs if you want to call without parens

# define the parameters

compile();

# code that uses new subs

sub compile {
    *tcpdump = $tcpdump ? sub {
        my $msg = shift;
        warn gf_time()." Thread ".threads->tid().": $msg\n";
    } : sub {};
    # ...
}
# EOF

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

1
ответ дан 3 December 2019 в 22:36
поделиться

Альтернативной стратегией было бы написать скрипт как модуль App :: * и указать параметр командной строки, какой класс загружать, чтобы обеспечить любую подключаемую функциональность в зависимости от вариант. Вам потребуется этот класс точно в срок, если вы узнаете, что это такое. Это немного больше предварительной работы, но если вы собираетесь поддерживать сценарий в течение длительного времени, я уверен, что это окупится. За последние пару лет было создано несколько очень хороших инструментов для создания скриптов, функциональность которых действительно заключается в модулях, включая App :: Cmd , MooseX :: Getopt и ] внебрачный отпрыск обоих .

8
ответ дан 3 December 2019 в 22:36
поделиться

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

sub AUTOLOAD {
    (my $name = our $AUTOLOAD) =~ s/.*:://;
    no strict 'refs';  # allow symbolic references

    *$AUTOLOAD = sub { print "$name subroutine called\n" };    
    goto &$AUTOLOAD;   # jump to the new sub
}

Автозагрузка сложна при создании деревьев наследования.

6
ответ дан 3 December 2019 в 22:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: