【问题标题】:How does this call to a subroutine in a Perl module work?这个对 Perl 模块中的子例程的调用是如何工作的?
【发布时间】:2011-08-01 15:08:11
【问题描述】:

我最近看到一些让我感到困惑的 Perl 代码。我把所有额外的部分都拿出来看看它是如何工作的,但我仍然不明白它为什么会起作用。

基本上,我创建了这个虚拟“模块”(TTT.pm):

use strict;
use warnings;

package TTT;
sub new {
    my $class = shift;
    return bless {'Test' => 'Test'}, $class;
}

sub acquire {
    my $tt = new TTT();
    return $tt;
}
1;

然后我创建了这个脚本来使用模块(ttt.pl):

#!/usr/bin/perl
use strict;
use warnings;

use TTT;
our $VERSION = 1;

my $tt = acquire TTT;
print $tt->{Test};

让我感到困惑,我认为行不通的行是:

my $tt = acquire TTT;

我认为它不会起作用,因为“获取”子从未导出过。但它确实有效。 在调用获取后,我对“TTT”感到困惑,所以我删除了它,留下这样的行:

my $tt = acquire;

它抱怨一句空话,就像我想的那样。我添加了括号,如下所示:

my $tt = acquire();

它抱怨说没有main::acquire,就像我想的那样。

我习惯了对象可用的子例程,或导出的子例程,但我从未见过以包名结尾的子例程被调用。我什至不知道如何在 Google 上搜索。

所以我的问题是,在子例程调用之后添加包名如何工作?我以前从未见过这样的事情,这可能不是一个好的做法,但是有人可以解释一下 Perl 的作用吗?

谢谢!

【问题讨论】:

    标签: perl perl-module


    【解决方案1】:

    您正在使用 Perl 允许的间接对象语法(但在现代代码中不鼓励使用)。基本上,如果一个名字没有预先声明,它可以放在一个对象(或类名)前面,用空格隔开。

    所以acquire TTT 这行实际上意味着TTT->acquire。如果您实际上在范围内有一个名为 acquire 的子例程,则它会被解释为 aquire(TTT),这可能会导致歧义(因此不鼓励使用它)。

    您还应该更新方法中的new TTT(); 行以读取TTT->new;

    【讨论】:

    • 非常感谢 - 现在完全有意义了!
    【解决方案2】:

    它是用于方法调用的indirect object syntax,它允许您将方法名称放在对象名称之前

    正如那里的文档显示的那样,最好避免使用它,因为它很笨重,并且可能会以不可预知的方式中断,例如,如果有 一个名为 acquire 的导入或定义子例程 - 但它曾经是比现在更常见,因此您会经常在旧代码和文档中找到它。

    【讨论】:

    • 这个语法的一些仍然被认可的用法是使用包的new方法,所以你可以说$obj = new Object而不是$obj = Object::new。这有助于 C++ 程序员认为他们知道发生了什么。
    • 感谢您的解释,@hobbs - 现在很有意义!
    • @mob:我认为“有点”是指“人们会抱怨,但可能不会打破你的膝盖骨。”太多人认为new Object 中的new 只是一个约定的关键字。
    • @mob 大多数perlers(我知道)不赞成间接调用——即使是new。我建议统一避免间接调用,除非在 DSL 中以这种方式工作得最好。
    • 拨打new Object肯定有缺点。但是让 C++ 程序员参与其中是它的一个可能优势(首先使用该语言然后学习如何使用它是否好,超出了本次讨论的范围,所以我将使用黄鼠狼这个词“可能”) .
    猜你喜欢
    • 2016-06-05
    • 2017-02-25
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 2021-10-05
    • 2017-11-26
    • 2021-10-14
    • 2021-10-05
    相关资源
    最近更新 更多