4

我宁愿这样做:

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

与这个:

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

有任何想法吗?

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

(实际上它是受到 Groovy 语言的启发,但大多数人并不知道 ;-)

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

4

4 回答 4

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经常使用,很容易忘记这些。

保罗

于 2009-01-08T01:32:06.337 回答
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()

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

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

于 2009-01-08T01:32:36.697 回答
4

I think I've just written it. I've just uploaded it to CPAN, you can find it here.

于 2009-01-08T16:25:07.673 回答
0

类似(未经测试):

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

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

于 2009-01-08T06:03:09.130 回答