2

在我们的代码库中,我们经常使用这个结构来处理我们程序的选项:

Readonly my $ARGS => Getopt::Declare->new(
   join( "\n",
      '[strict]',
      "--option1 <some-option-description> [required]",
   )
) or exit(1);

问题是,当违反严格性Getopt::Declare->new(...)时,它会返回undef,这通常是可以的,只是它undef存储在Readonly变量中,当在布尔上下文中评估时为true

  1. 一个明显的解决方案是删除Readonly并且代码将按预期运行;但是我真的不喜欢这个解决方案,因为改变它会允许$ARGS被修改。

    my $ARGS => Getopt::Declare->new(
       join( "\n",
          '[strict]',
          "--option1 <some-option-description> [required]",
       )
    ) or exit(1);
    
  2. 另一种解决方案是将 in parens 包装起来,以便在分配给Readonly变量Getopt::Declare->new(...) or exit(1)之前对它们进行评估。

    Readonly my $ARGS => (
       Getopt::Declare->new(
          join( "\n",
             '[strict]',
             "--option1 <some-option-description> [required]",
          )
       ) or exit(1);
    )
    
  3. 我想另一种方法是使用 or 的更高优先级版本||,它的绑定比强,=>但我不确定它是否可读。

    Readonly my $ARGS => Getopt::Declare->new(
       join( "\n",
          '[strict]',
          "--option1 <some-option-description> [required]",
       )
    ) || exit(1);
    
4

2 回答 2

3
Readonly my $ARGS => Getopt::Declare->new(
# ...
);
$ARGS or exit(1);

ought to work as well.

于 2013-08-02T14:37:47.570 回答
1

正如@choroba 所建议的,当前的问题是优先事项之一:

只读我的 $v => ... 或者死;# 这个构造...
Readonly(my $v, ...) 或死;#真的是这个……
绑定我的 $v, 'Readonly', ... 或者死;# 这或多或少是 this,计算结果为 ...  
ReadOnly::Scalar=SCALAR(0x123)要么死;#tie() 下面
的对象...

所以你永远不会碰到右半边,or因为返回的对象评估为真。

现在,如果您真的想继续使用该语法,您可以执行以下操作来强制使用 tie()d 变量而不是底层对象:

use Readonly ();
sub MakeReadonly(\[$@%]@) {
  &Readonly::Readonly;               # tie() ${$_[0]} to Readonly implementation
  ${$_[0]};                          # ... but return the tied variable, not the object
}

....

MakeReadonly my $e => ... or die;    # This ...
MakeReadonly(my $e, ...)  or die;    # becomes this ...
$e or die;                           # which is effectively this.

顺便说一句,我建议小心这个结构。的吸引力Readonly在于它允许一种看似类似于分配给属性标量的语法,就好像您正在这样做一样:

my $v : Readonly = something() or die;    # XXX Doesn't work!  Not even Attribute::Constant
                                          # works like this, unfortunately.

......但它完全不同。您在帖子标题和正文中的措辞表明您至少最初是这样考虑的。(例如,“只读变量评估为真” - 好吧,它们的基础对象会,绑定变量本身可能不是。或者,“在分配之前评估” - 好吧,你并不是真正分配本身,但再次 tie( )。)

于 2013-08-02T13:55:52.683 回答