在Perl中使用未知方法

Sta*_*ski 5 perl prototype

我无法理解,为什么Perl在像这样的程序中执行大括号中的代码:

unknown_method {
    # some code
};
Run Code Online (Sandbox Code Playgroud)

我的节目:

文件Transaction.pm:

package Transaction;
use strict;
use warnings;
use feature qw/ say /;

sub transaction(&) {
    say 'BEGIN TRANSACTION';
    eval {
        shift->()
    };
    if ( $@ ) {
        say 'ROLLBACK TRANSACTION';
        die($@);  # reraise error
    } else {
        say 'COMMIT TRANSACTION';
    }
}
1;
Run Code Online (Sandbox Code Playgroud)

文件run_properly.pl:

use feature qw/ say /;
use Transaction;
eval {
    Transaction::transaction {
        say "insert some data to DB";
        die("KnownException")
    }
};
warn $@;
Run Code Online (Sandbox Code Playgroud)

文件run_wrong.pl:

use feature qw/ say /;
# I forgot to import Transaction
eval {
    Transaction::transaction {
        say "insert some data to DB";
        die("KnownException")
    }
};
warn $@;
Run Code Online (Sandbox Code Playgroud)

执行:

$ perl run_properly.pl 
BEGIN TRANSACTION
insert some data to DB
ROLLBACK TRANSACTION
KnownException at run_properly.pl line 6.
Run Code Online (Sandbox Code Playgroud)

$ perl run_wrong.pl 
insert some data to DB
KnownException at run_wrong.pl line 6.
Run Code Online (Sandbox Code Playgroud)

为什么Perl允许这样的事情?

amo*_*mon 9

Perl在语法上是灵活的,并且通常有多种语法可以做.例如,调用方法.这是常规和推荐的语法:

  Foo  ->  new       (1, 2, 3);
# ^-object ^- method ^- arguments
Run Code Online (Sandbox Code Playgroud)

这是间接语法:

  new       Foo       1, 2, 3;
# ^- method ^- object ^- arguments, parens are optional
Run Code Online (Sandbox Code Playgroud)

这一切都很好,但是当我们想要将复杂计算的结果用作间接对象表示法的对象时会发生什么?

# set up some constructors for demonstration purposes
*Foo::new = *Bar::new = sub {say "@_"};

# This obviously fails
# new (rand > .5 ? "Foo" : "Bar") 1, 2, 3;
Run Code Online (Sandbox Code Playgroud)

解决方案是一个dative块:

new {rand > .5 ? "Foo" : "Bar"} 1, 2, 3;
Run Code Online (Sandbox Code Playgroud)

您可能已经知道文件句柄中的dative块:print {$handles[-1]} $_.

在方法解析之前执行dative块,因为方法解析通常(但不是在你的情况下)取决于对象的类型.但是,如果块dies 没有解决方法.


间接符号仍然非常受构造函数的欢迎,因为它使Perl看起来像C++.但是,Perl(与C++不同)没有new 运算符:它只是一种常规方法.这种灵活性可能是一个坏主意,所以no indirect如果您对此有强烈的兴趣,可以通过使用来"修复"它.