【问题标题】:What happens when you pass zero arguments into a subroutine that requires them?当您将零参数传递给需要它们的子例程时会发生什么?
【发布时间】:2015-03-20 08:06:05
【问题描述】:

这里是相关的代码。

Slic3r::Print::Simple 的属性之一:

has '_print' => (
is      => 'ro',
default => sub { Slic3r::Print->new },
handles => [qw(apply_config extruders expanded_output_filepath
                total_used_filament total_extruded_volume
                placeholder_parser process)],
);

相关子程序:

sub new {
# TODO: port PlaceholderParser methods to C++, then its own constructor
# can call them and no need for this new() method at all
my ($class) = @_;
my $self = $class->_new;
$self->placeholder_parser->apply_env_variables;
$self->placeholder_parser->update_timestamp;
return $self;
}

此代码有效,我在网上找不到任何解释它的内容。 几个问题:

  1. $class 分配了什么值?我猜它被分配了调用 Print::Simple 对象,但我无法用一个验证
  2. 我找不到 _new 的代码,但如果 $class 是 Simple 对象,那么它应该是 Moo::Object 的子类,但是我在包中找不到相关的子例程。
  3. 对 placeholder_parser 的调用似乎表明 $self 引用了一个 Simple 对象,但我不明白这个委托是如何被调用的。我认为调用委托将从 Slic3r::Print->new 返回的任何内容中调用相关方法,但这是在方法返回值之前调用委托。此外,我进行了搜索,在该程序的目录或 Perl 库中的任何地方都没有找到 placeholder_parser 子例程的定义。那么,它到底在做什么呢?

基本上我脑子里全是f%ck,我不知道发生了什么。还必须说明该程序 100% 有效。

【问题讨论】:

标签: perl


【解决方案1】:

首先,这个 Slic3r 项目违反了基本的 Perl 约定。运行 perl Build.PL 应该只配置构建,而不是安装依赖项、构建和运行测试。

要实现的第二件事是 Slic3r Perl 模块是 libslic3r C++ 库的包装器。 Perl 代码可能正在调用 C++ 库中定义的方法,而不是 Perl 代码。要真正了解发生了什么,请获取source code 的副本。

$class 分配了什么值?

方法调用的第一个参数是调用者,即-> 左侧的东西。对于类方法,它是类的名称。对于对象方法,它就是对象。

例如...

package Some::Class;
sub foo {
    my $class = shift;
    print "$class\n";
}

Some::Class->foo;  # prints 'Some::Class'

我找不到 _new 的代码,但如果 $class 是一个 Simple 对象,那么它应该是 Moo::Object 的子类,但是我在包中找不到相关的子例程。

Moo 不提供_new 方法。

花了一些时间来追踪,但据我所知,_new 是由 C++ 包装代码创建的构造函数。如果您查看 xs/buildtmp/XS.c,您会看到类似...

XS_EUPXS(XS_Slic3r__Print__new)

这是调用 Slic3r C++ 库并将 C++ 对象转换为 Perl 对象的代码。由Module::Build::WithXSpp自动生成。

对 placeholder_parser 的调用似乎表明 $self 引用了一个简单对象

这可能是正确的。 $self 包含 $class->_new 返回的任何内容,如果行为良好,则可能是 Slic3r::Print::Simple 对象。

但是我不明白这个委托是如何被调用的。我认为调用委托将从 Slic3r::Print->new 返回的任何内容中调用相关方法,但这是在方法返回值之前调用委托。

在 Perl 中 new 没有什么神奇之处。它被用作构造函数只是一个约定。在new 返回之前,您可以使用一个完整的对象。

这就是 _newnew 发挥作用的地方。 _new 是 C++ 对象构造函数。它只从 C++ 库中取回基本的 Slic3r::Print 对象。 new 然后在该对象上调用其他方法。

此外,我进行了搜索,但在该程序的目录或 Perl 库中的任何位置都没有找到 placeholder_parser 子例程的定义。那么,它到底在做什么呢?

placeholder_parser 是 xs/src/libslic3r/Print.cpp 中 libslic3r C++ 库中的一个方法。您可以在 xs/buildtmp/XS.c 中看到包装器代码。

【讨论】:

  • 我认为您的意思是“->”的左侧?
猜你喜欢
  • 1970-01-01
  • 2012-01-03
  • 1970-01-01
  • 2020-04-16
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 2019-11-12
  • 1970-01-01
相关资源
最近更新 更多