Ste*_*sky 5 perl operators dereference
所以perl5porters正在讨论添加一个安全的解除引用运算符,以允许类似的东西
$ceo_car_color = $company->ceo->car->color
if defined $company
and defined $company->ceo
and defined $company->ceo->car;
Run Code Online (Sandbox Code Playgroud)
被缩短为例如
$ceo_car_color = $company->>ceo->>car->>color;
Run Code Online (Sandbox Code Playgroud)
其中$foo->>bar表示defined $foo ? $foo->bar : undef.
问题是:是否有一些模块或不引人注目的黑客攻击我,这个操作符,或类似的行为,具有视觉上令人愉快的语法?
为了您的乐趣,我会列出我能够提出的想法.
多重derefencing方法(看起来很难看).
sub multicall {
my $instance = shift // return undef;
for my $method (@_) {
$instance = $instance->$method() // return undef;
}
return $instance;
}
$ceo_car_color = multicall($company, qw(ceo car color));
Run Code Online (Sandbox Code Playgroud)一个包装器,它变成undef一个undef从所有函数调用返回的代理对象(看起来更加丑陋).
{ package Safe; sub AUTOLOAD { return undef } }
sub safe { (shift) // bless {}, 'Safe' }
$ceo_car_color = safe(safe(safe($company)->ceo)->car)->color;
Run Code Online (Sandbox Code Playgroud)由于我可以访问实现ceo(),car()并且color(),我考虑直接从这些方法返回安全代理,但是现有代码可能会中断:
my $ceo = $company->ceo;
my $car = $ceo->car if defined $ceo; # defined() breaks
Run Code Online (Sandbox Code Playgroud)
不幸的是,我没有看到任何东西perldoc overload约超载的意义defined,并//在我的安全代理.
也许这不是最有用的解决方案,但它又是一个 WTDI(nr.1 的变体),并且是List::Util的reduce的一个重要用例,这是非常罕见的。;)
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use List::Util 'reduce';
my $answer = 42;
sub new { bless \$answer }
sub foo { return shift } # just chaining
sub bar { return undef } # break the chain
sub baz { return ${shift()} } # return the answer
sub multicall { reduce { our ($a, $b); $a and $a = $a->$b } @_ }
my $obj = main->new();
say $obj->multicall(qw(foo foo baz)) // 'undef!';
say $obj->multicall(qw(foo bar baz)) // 'undef!';
Run Code Online (Sandbox Code Playgroud)
42
undef!
Run Code Online (Sandbox Code Playgroud)
笔记:
当然应该是
return unless defined $a;
$a = $a->$b;
Run Code Online (Sandbox Code Playgroud)
而不是$a and $a = $a->$b上面的较短的方法可以正确使用已定义但错误的值,但我的观点是使用reduce。