在Perl中是否有安全解除引用的便利?

在Perl中是否有安全解除引用的便利?,perl,operators,dereference,Perl,Operators,Dereference,所以perl5porters正在讨论添加一个安全的解引用操作符,以允许像这样的东西 $ceo_car_color = $company->ceo->car->color if defined $company and defined $company->ceo and defined $company->ceo->car; 缩短为,例如 $ceo_car_color = $company->>ceo->>ca

所以perl5porters正在讨论添加一个安全的解引用操作符,以允许像这样的东西

$ceo_car_color = $company->ceo->car->color
    if  defined $company
    and defined $company->ceo
    and defined $company->ceo->car;
缩短为,例如

$ceo_car_color = $company->>ceo->>car->>color;
其中
$foo->条
表示
定义的$foo$foo->bar:undef

问题是:是否有一些模块或非结构化的黑客让我得到了这个操作符,或者类似的行为,并且语法直观

为了让你们高兴,我将列出我能想到的想法

  • 多重解除防护方法(看起来很难看)

  • undef
    转换为代理对象(看起来更丑陋)的包装器,该代理对象从所有函数调用返回
    undef

    { package Safe; sub AUTOLOAD { return undef } }
    sub safe { (shift) // bless {}, 'Safe' }
    
    $ceo_car_color = safe(safe(safe($company)->ceo)->car)->color;
    
  • 由于我可以访问
    ceo()
    car()
    color()
    的实现,因此我考虑直接从这些方法返回安全代理,但现有代码可能会中断:

    my $ceo = $company->ceo;
    my $car = $ceo->car if defined $ceo; # defined() breaks
    
    不幸的是,我在
    perldoc重载
    中没有看到任何关于重载我的安全代理中定义的
    /
    的含义的内容


  • 您可以使用
    eval

    $ceo_car_color = eval { $company->ceo->car->color };
    

    但是它当然会捕获任何错误,而不仅仅是在
    undef

    上调用一个方法。也许这不是最有用的解决方案,但它又是一个WTDI(nr.1的一个变体),它是非常罕见的'sreduce的一个非常重要的用例

    代码 输出 注:

    当然应该是

    return unless defined $a;
    $a = $a->$b;
    

    与上面的较短的
    $a和$a=$a->$b
    不同,它可以正确地处理已定义但为假的值,但我这里的重点是使用reduce

    数字2赢得最奇怪的一个。有趣的解决方案。感谢分享。实际上,让multicall成为$obj的成员会使语法非常可爱。对于在大型代码库中偶然发现该文档的人来说,该文档是可以发现的。我现在使用此解决方案,不过我可能会编写类似于
    $obj->multicall(foo=>bar=>baz=>)的调用。
    #!/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!';
    
    42
    undef!
    
    return unless defined $a;
    $a = $a->$b;