代码之家  ›  专栏  ›  技术社区  ›  Robert S. Barnes Antoni

我应该什么时候使用Perl的AUTOLOAD?

  •  9
  • Robert S. Barnes Antoni  · 技术社区  · 16 年前

    “在” Perl Best Practices “自动加载部分的第一行是:

    不使用自动加载

    然而,他描述的所有案例都是针对OO或模块的。

    我有一个独立的脚本,其中一些命令行开关控制特定函数的哪些版本被定义。现在我知道我可以把条件和eval放在文件的顶部,然后把它们赤裸裸地放在其他所有东西之前,但是我发现把它们放在文件末尾的AUTOLOAD中既方便又干净。

    这种做法/风格不好吗?如果你这么想为什么,还有别的办法吗?

    我基本上是用它来做基于命令行开关的条件编译。

    我不介意一些建设性的批评。

    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;
    }
    
    3 回复  |  直到 16 年前
        1
  •  2
  •   Eric Strom    16 年前

    如果你使用 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 作为论据。

        2
  •  8
  •   hobbs    16 年前

    require 一旦你知道是哪门课,那门课就来不及了。这是一个多一点的前期工作,但如果你打算保持脚本很长一段时间,我打赌它会得到回报。在过去的几年里,我们已经开发了一些非常好的工具来创建脚本,这些脚本的功能确实存在于模块中,包括 App::Cmd , MooseX::Getopt ,和 the bastard offspring of both .

        3
  •  6
  •   Eugene Yarmash    16 年前

    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
    }
    

    自动加载在生成继承树时很棘手。