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 }