Perl中的嵌套解除引用箭头:省略或不省略?

时间:2010-03-19 04:46:13

标签: perl syntax coding-style

在Perl中,当你有一个嵌套的数据结构时,允许省略取消引用箭头到2d和更多嵌套级别。换句话说,以下两种语法是相同的:

my $hash_ref = { 1 => [ 11, 12, 13 ], 3 => [31, 32] };

my $elem1 = $hash_ref->{1}->[1]; 
my $elem2 = $hash_ref->{1}[1]; # exactly the same as above

现在,我的问题是,是否有充分理由选择其中一种风格

它似乎是风格争论的流行之骨(就在SO上,我偶然在5分钟的时间内碰到了thisthis。)

到目前为止,几乎所有通常的嫌疑人都没有明确说明:

  • perldoc只是说“你可以省略指针取消引用箭头”。
  • Conway的“Perl最佳实践”说“尽可能使用箭头取消引用”,但它似乎只适用于解除引用主参考的上下文,而不适用于嵌套数据结构的2d级别的可选箭头。
  • “掌握Perl for Bioinfirmatics”作者James Tisdall并没有给出非常可靠的偏好:

      

    “头脑敏锐的读者可能有   注意到我们似乎在忽略   数组之间的箭头运算符   标。 (毕竟,这些都是   匿名数组的匿名数组   匿名数组等等   不应该写它们   [$ array-> [$ i] - > [$ j] - > [$ k]?)Perl   允许这个;只有箭头操作符   变量名和。之间   第一个数组下标是必需的。它   使眼睛和眼睛更容易   有助于避免腕管综合症。上   另一方面,你可能更喜欢保持   解除引用箭头到位   说清楚你正在处理   引用。你的选择。“

  • 更新“中级Perl”,根据其合着者brian d foy,建议省略箭头。请参阅下面的brian的完整答案。

就个人而言,我站在“总是放入箭头,因为它更具可读性和显而易见性,它们正在处理参考”。

UPDATE 更具体的说明:可读性,对于多嵌套表达式,其中下标本身是表达式,箭头有助于“直观地标记”表达式,更明显地将下标与一个分开另一个。

3 个答案:

答案 0 :(得分:14)

除非您真的喜欢打字或排长队,否则请勿在不需要时使用箭头。下标旁边的下标意味着引用,因此有能力的程序员不需要额外的线索来解决这个问题。

我不同意额外的箭头更具可读性。让他们将这个词的有趣部分进一步远离彼此是绝对不同寻常的。

Intermediate Perl中,我们实际教授参考文献,我们告诉您省略不必要的箭头。

另外,请记住没有“可读性”这样的东西。只有你(和其他人)训练你的眼睛才能识别为模式。你不会逐字逐句地阅读它们,然后弄清楚它们的含义。您可以看到之前见过的事物组并识别它们。在您所讨论的基本语法级别,您的“可读性”只是您识别模式的能力。您使用它越多,识别模式就越容易,因此您现在所做的事情对您来说更具“可读性”并不奇怪。新的风格起初看起来很奇怪,但最终变得更容易识别,因此更具“可读性”。

您在评论中提供的示例并不难阅读,因为它缺少箭头。用箭头读起来仍然很难:

 $expr1->[$sub1{$x}]{$sub2[$y]-33*$x3}{24456+myFunct($abc)}
 $expr1->[$sub1{$x}]->{$sub2[$y]-33*$x3}->{24456+myFunct($abc)}

我写这样的代码,使用这些变量名称来提醒下一个编码器每个级别的容器类型:

my $index = $sub1{$x};
my $key1  = $sub2[$y]-33*$x3;
my $key2  = 24456+myFunct($abc);

$expr1->[ $index ]{ $key1 }{ $key2 };

为了做得更好,将细节隐藏在子程序中(这就是它们的用途:)所以你永远不必直接使用那些乱七八糟的数据结构。这比任何一个都更具可读性:

  my $value = get_value( $index, $key1, $key2 );

  my $value = get_value(
  $sub1{$x},
   $sub2[$y]-33*$x3,
   24456+myFunct($abc)
      );

答案 1 :(得分:2)

由于->箭头不可选地用于方法调用,我更喜欢只使用它来调用代码。所以我会使用以下内容:

$object->method;
$coderef->();
$$dispatch{name}->();

$$arrayref[1];
$$arrayref[1][5];
@$arrayref[1 .. 5];
@$arrayref;
$$hashref{foo};
$$hashref{foo}{bar};
@$hashref{qw/foo bar/};
%$hashref;

背靠背的两个符号总是意味着取消引用,并且结构在所有形式的解除引用(标量,切片,全部)中保持一致。

它还将变量的所有部分“保持在一起”,我发现它更具可读性,而且更短:)

答案 2 :(得分:1)

我总是写下所有箭头。我同意你的意见,他们将不同的下标分开。另外,我使用花括号作为正则表达式,所以对我来说{foo}{bar}是替代:s{foo}{bar}$s->{foo}->{bar}更突出,而不是来自$s->{foo}{bar}

我认为这不是一件大事,阅读省略额外箭头的代码不是问题(与任何不是我使用的缩进相反; - )