Perl有AND吗?

Perl有AND吗?,perl,andand,Perl,Andand,我宁愿这样做: say $shop->ShopperDueDate->andand->day_name(); 与此相比: say $shop->ShopperDueDate->day_name() if $shop->ShopperDueDate; 有什么想法吗 (这个想法的灵感来自Ruby扩展。) (实际上它的灵感来自Groovy语言,但大多数人并不知道;-) 更新:我认为maybe()和eval{}都是很好的解决方案。这不是ruby,所以我不能期望从左

我宁愿这样做:

say $shop->ShopperDueDate->andand->day_name();
与此相比:

say $shop->ShopperDueDate->day_name() if $shop->ShopperDueDate;
有什么想法吗

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

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


更新:我认为maybe()和eval{}都是很好的解决方案。这不是ruby,所以我不能期望从左到右阅读所有的方法/函数,所以可能会有帮助。当然,eval确实是perl实现这一点的方法。

您可以使用perl的
eval
语句捕获异常,包括试图对未定义参数调用方法时产生的异常:

eval {
    say $shop->ShopperDueDate->day_name();
};
由于
eval
返回最后计算的语句,或在失败时返回
undef
,因此您可以在如下变量中记录日期名称:

my $day_name = eval { $shop->ShopperDueDate->day_name(); };
如果确实希望检查异常,可以查看特殊变量
$@
。对于Perl的内置异常,这通常是一个简单的字符串,但如果异常源于或其他使用对象异常的代码,则可能是一个完整的异常对象

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

if ($@) {
    say "The error was: $@";
}
还可以使用
eval
块将一系列命令串在一起。以下仅检查是否为周末,前提是在查找
$day\u name
时未引发任何异常

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

    if ($day_name ~~ [ 'Saturday', 'Sunday' ] ) {
        say "I like weekends";
    }
};
你可以认为
eval
与其他语言中的
try
相同;事实上,如果您使用的是来自CPAN的模块,那么您甚至可以拼写它
try
。还值得注意的是,eval的块形式(我在上面演示过)没有性能损失,它是与您的其余代码一起编译的。
eval
(我没有展示)的字符串形式是完全不同的,如果可以的话,应该尽量少用

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


保罗

我想你的第二个例子应该是:

say $shop->ShopperDueDate ? $shop->ShopperDueDate->day_name() : undef;
而不是它实际所说的

无论如何,如果没有源过滤器,您就不能完全使用该语法,因为
undef
不是对象,而是一元运算符,因此它不能有任何方法

请考虑这个:

package noop; 
our $maybe = bless [], 'noop';
sub AUTOLOAD { undef };
$noop::可能是一个对象;它的所有方法都返回
undef
。在其他地方,您将有如下常规函数:

sub maybe { $_[0] || $noop::maybe; }
然后你可以写下:

say maybe($shop->ShopperDueDate)->day_name()
这是因为“maybe”如果为true,则返回其参数,否则它将返回
$noop::maybe
对象,该对象的方法总是返回undef

编辑:更正!
->and->
语法可以在没有源代码过滤器的情况下使用,方法是使用一个与Perl内部结构混在一起的过滤器。创建了一个采用此路线的实现。它全局替换了
unde()
函数,因此可能比我的方法慢得多。

类似(未测试):

UNIVERSAL自动成为所有其他类的子类,因此它为所有对象提供AND和。 (显然,在UNIVERSAL中创建方法可能会在远处发生冲突或意外行动, 如果调用AND和方法的对象为true,则返回它;
否则,返回一个泛型的false对象,该对象对于对其使用的任何方法调用都返回自身。

我想我刚刚编写了它。我刚把它上传到CPAN,你可以找到它。

你为什么说这样更好?这完全一样,对吗?在他的例子中,阅读它们的顺序更有意义,IMHOFrew:第一个例子是say($some_值),其中第二个例子大致相当于if($some_值){say($some_值)}——前一个例子总是调用say(),而后一个例子调用say()有条件的。您还将此发布到Perlmonks()。当您将同一问题发布到多个位置时,请让人们知道,这样人们就可以看到所有答案,而不会在您得到答案时浪费时间回答问题。问题是,您不能对未定义的值调用方法。如果需要,始终可以使用autobox pragma将未定义的值提升为第一类对象。然后您可以对其调用方法。;)你能扩展一下“你不能对未定义的值调用方法”吗?我不完全确定您是否阅读了我的所有文章。未定义的值不能作为引用,因此您不能对它们调用方法。这需要相当多的魔法才能实现。
use Object::Generic::False;
sub UNIVERSAL::andand { $_[0] || Object::Generic::False->false }