有这个有效的短代码
use 5.014;
package Module;
use warnings;
use Moose;
use Method::Signatures::Simple;
has 'commands' => (
is => 'ro',
isa => 'HashRef',
default => sub{{
open => 'my_open',
close => 'my_close',
}},
);
method run($cmd, $args) {
my $met = $self->commands->{$cmd} if exists $self->commands->{$cmd};
$self->$met($args) if $met;
#-----
#how to write the above two lines in one command?
#the next doesn't works
# $self->commands->{$cmd}($args) if exists $self->commands->{$cmd};
#-----
}
method my_open { say "module: open" }
method my_close { say "module: close" }
package main;
my $ef = Module->new();
$ef->run('open');
主要问题在于代码 - 如何在一行中编写“run”方法 - 没有辅助变量$met
。
并且,这是更好的方法来执行上述方案 - 所以基于输入调用方法?
答案 0 :(得分:4)
首先,请不要my $foo = $x if $y
。您会遇到意外和未定义的行为,因此最好避免使用该语法。
这段代码
my $met = $self->commands->{$cmd} if exists $self->commands->{$cmd};
$self->$met($args) if $met;
相当于
if (my $met = $self->commands->{$cmd}) {
$self->$met($args);
}
因为exists
测试在这里是多余的(如果条目存在,则条目只能为真)。
如果我们不想引入另一个变量,我们有两个选择:
使用$_
:
$_ and $self->$_($args) for $self->commands->{$cmd};
这不会将for
用作循环,而是用作局部化器。
使用标量引用:
$self->${\( $self->commands->{$cmd} )}($args) if $self->commands->{$cmd};
或
$self->${\( $self->commands->{$cmd} || "no_op" )}($args);
...
method no_op { }
不要做这样的事情,因为无法读取线路噪音。
这些都不是特别优雅,最好使用我上面展示的清理过的解决方案。
仅仅因为可以在一行中完成,并不意味着应该完成。 “这是Perl,而不是 ......哦,没关系。”