Perl有和吗?

时间:2009-01-08 01:02:41

标签: perl andand

我宁愿这样做:

say $shop->ShopperDueDate->andand->day_name();

VS。这样:

say $shop->ShopperDueDate->day_name() if $shop->ShopperDueDate;

有什么想法吗?

(这个想法的灵感来自Ruby andand扩展。)

(实际上它的灵感来自Groovy语言,但大多数人都不知道; - )

更新:我认为may()和eval {}都是很好的解决方案。这不是ruby,所以我不能期望从左到右阅读所有的方法/功能,所以也许肯定会有所帮助。当然,eval确实是实现它的perl方式。

4 个答案:

答案 0 :(得分:9)

您可以使用Perl的eval语句来捕获异常,包括尝试在未定义的参数上调用方法的异常:

eval {
    say $shop->ShopperDueDate->day_name();
};

由于eval返回最后评估的语句,或者undef失败,您可以将日期名称记录在变量中,如下所示:

my $day_name = eval { $shop->ShopperDueDate->day_name(); };

如果您确实希望检查异常,可以查看特殊变量$@。对于Perl的内置异常,这通常是一个简单的字符串,但如果异常来自autodie或其他使用对象异常的代码,则可能是完整的异常对象。

eval {
    say $shop->ShopperDueDate->day_name();
};

if ($@) {
    say "The error was: $@";
}

也可以使用eval块将一系列命令串在一起。以下内容仅检查是否为周末,前提是我们在查找$day_name时没有任何例外情况。

eval {
    my $day_name = $shop->ShopperDueDate->day_name();

    if ($day_name ~~ [ 'Saturday', 'Sunday' ] ) {
        say "I like weekends";
    }
};

您可以将eval视为与其他语言的try相同;实际上,如果你使用的是CPAN中的Error模块,那么你甚至可以拼写它try。值得注意的是,eval的块形式(我上面已经演示过)并没有性能损失,并且与其他代码一起编译。 eval的字符串形式(我没有显示)完全是一个不同的野兽,如果有的话应该谨慎使用。

eval在技术上被认为是Perl中的一个语句,因此是少数几个在块结尾处看到分号的地方之一。如果您不定期使用eval,很容易忘记这些。

答案 1 :(得分:9)

我认为你的第二个例子最好是:

say $shop->ShopperDueDate ? $shop->ShopperDueDate->day_name() : undef;

而不是它实际上说的。

无论如何,如果没有源过滤器,完全那个语法就不能这样做,因为undef不是一个对象,而是一元运算符,所以它不能有任何方法

相反,请考虑一下:

package noop; 
our $maybe = bless [], 'noop';
sub AUTOLOAD { undef };

这个$noop::maybe是一个对象;它的所有方法都返回undef。在其他地方,你将有这样的常规功能:

sub maybe { $_[0] || $noop::maybe; }

然后你可以这样写:

say maybe($shop->ShopperDueDate)->day_name()

这是因为“maybe”返回如果为true则返回其参数,否则返回我们的$noop::maybe对象,该对象具有始终返回undef的方法。

编辑:更正! ->andand->语法 可以在没有源过滤器的情况下使用XS来解决Perl的内部问题。 Leon Timmermans做了一个采用这条路线的实现。它全局替换undef()函数,因此它可能比我的方法慢很多。

答案 2 :(得分:4)

我想我刚写完了。我刚刚将其上传到CPAN,您可以找到它here

答案 3 :(得分:0)

像(未经测试)的东西:

use Object::Generic::False;
sub UNIVERSAL::andand { $_[0] || Object::Generic::False->false }

UNIVERSAL自动成为所有其他类的子类,因此这为所有对象提供了和。 (显然,在UNIVERSAL中创建方法有可能在远处发生冲突或令人惊讶的行为, 因此不应该不小心使用它。)如果调用andand方法的对象为true,则返回它; 否则返回一个泛型false对象,该对象为其上使用的任何方法调用返回自身。