【发布时间】:2016-09-25 04:13:15
【问题描述】:
我经常使用 Perl 中的 Moose 包,这些包使用 MooseX::Params::Validate 来定义接口。这些接口往往相当灵活,并允许多个可选参数。不幸的是,这是 Perl,因此返回类型将根据可选参数而有所不同,并且在大多数情况下,当在调用者中定义时传递可选参数是有好处的。此代码库中使用了从MooseX::Params::Validate 导出的各种方法,因此由于处理包的各种方式undef 参数我无法传递它无论如何都会很优雅。我倾向于使用以下方法,但它在评论中出现了很多,我想问是否有另一种方法可以实现这种灵活性。
use strict;
use warnings;
my $bar;
Foo->foo({
foo => 'I, Foo need a VERY flexible interface. ',
$bar ? ( bar => $bar ) : ()
});
$bar = "Very flexible...";
Foo->foo({
foo => 'I, Foo need a VERY flexible interface. ',
$bar ? ( bar => $bar ) : ()
});
package Foo;
use Moose;
use MooseX::Params::Validate;
sub foo {
my $self = shift;
my ( $foo, $bar ) = validated_list(
\@_,
foo => { isa => 'Str' },
bar => { isa => 'Str', optional => 1 },
);
print $foo . $bar . "\n";
}
1;
检查变量defined 状态的三元运算符总是让我想要一个// 类型参数选项,但我看不到任何支持这种类型操作的地方。
caller 的答案是首选,因为我不想(不会)更改各种包的接口,但我愿意接受显示处理 undef 传递的参数值的方法的答案.
【问题讨论】:
-
对于调用者来说,你的“成语”似乎很费力[更重要的是,容易出错]。用更直接的辅助函数替换三进制怎么样:
sub defme { my(@arr); push(@arr,$_[0],$_[1]) if ($_[1]); @arr; }?然后,你有defme("bar",$bar)而不是三元。或者,在构造函数中,根据需要在调用validated_list之前执行//或//=,因为第一个参数始终指向一个临时值? -
@CraigEstey 你能解释一下它是如何更容易出错和费力的(我主要关心的是可读性),以及你的解决方案是如何工作的,因为我没有看到它是如何适用的?
-
我的函数,AFAICT,做三元组所做的事情——产生一个填充有
($sym,$val)或空的数组。而且,IMO,defme("bar",$bar)比 [longer]$bar ? (bar => $bar) : ()更具可读性。 fnc 调用比三元语法更短更简单。并且,如果需要,您可以将调试 printfs 添加到 fnc。但是,最好让所有调用者只做(bar => $var)并让foo处理它,而不是把责任放在调用者身上。即使您仍然想要三元,foo仍然需要防御性地检查这一点。那么,如果检查为什么不修复呢? -
如果
$bar是 undef,如果它得到bar => $bar,它看起来像foo中断。但是,正如我所说,让每个调用者都进行检查(通过三元)?我只是通过任何东西并让foo从哈希中删除 undef 值:@sym = keys(%$hash); for $sym (@sym) { delete{$hash->{$sym}} unless (defined($hash->{$sym})); }