【问题标题】:Nested dereferencing arrows in Perl: to omit or not to omit?Perl 中的嵌套取消引用箭头:省略还是不省略?
【发布时间】:2010-03-19 04:46:12
【问题描述】:

在 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 级别嵌套数据结构的可选箭头。
  • “Mastering Perl for Bioinfirmatics”作者 James Tisdall 也没有给出非常明确的偏好:

    “机敏的读者可能有 注意到我们似乎忽略了 数组之间的箭头运算符 下标。 (毕竟这些 匿名数组的匿名数组 匿名数组等,所以 他们不应该写吗 [$array->[$i]->[$j]->[$k]?) Perl 允许这样做;只有箭头运算符 在变量名和 第一个数组下标是必需的。它 让眼睛更轻松, 有助于避免腕管综合症。在 另一方面,您可能更愿意保留 取消引用箭头到位, 明确你正在处理 参考。你的选择。”

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

就我个人而言,我支持“始终插入箭头,因为它更具可读性并且更明显他们正在处理参考”。

更新更具体地说:可读性,在下标本身就是表达式的多嵌套表达式的情况下,箭头通过更明显地将下标与一个下标分开来帮助“视觉标记”表达式另一个。

【问题讨论】:

  • brian - 系统没有告诉我你更新了你的答案,抱歉迟到了。

标签: perl syntax coding-style


【解决方案1】:

除非您真的喜欢打字或行太长,否则不要在不需要时使用箭头。下标旁边的下标暗示着引用,所以称职的程序员不需要额外的线索来弄清楚这一点。

我不同意有额外的箭头更具可读性。让他们将术语中有趣的部分远离彼此绝对是非常规的。

Intermediate Perl 中,我们实际教授引用,我们告诉您省略不必要的箭头。

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

您在 cmets 中给出的示例不难阅读,因为它没有箭头。用箭头仍然很难阅读:

 $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)
      );

【讨论】:

  • 尽管 brian 不需要我的投票,但我真的很喜欢“术语的有趣部分”这一点。
  • brian - 我对 Jefromi 的观点有什么意见吗?例如。下标之间的额外间距有助于“直观地标记”它们 - 在编写 $a->[2]{c} 时它无关紧要,但更多涉及的表达式如 "$expr1->[$sub1{$x}]{$ sub2[$y]-33*$x3}{24456+myFunct($abc)}" (不是我的实际代码!)
  • P.S.完全不相关——但你对这个元问题有什么答案吗? meta.stackexchange.com/questions/42797/…
  • @DVK:通过这种嵌套,我想说你可以从括号内的空格而不是它们之间的箭头中获得清晰的信息。
  • @Jefromi - 我总是在括号内放置空格,因为下标值比单个变量更复杂 - 在这里我担心评论空间用完并有意识地跳过它们......真糟糕。跨度>
【解决方案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;

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

它还将变量的所有部分“放在一起”,我发现它更易读,而且更短:)

【讨论】:

  • 但并非所有的取消引用都有两个背靠背的印记:)
  • 没错,因为有解引用的选择,而不是方法调用......“我认为视觉隐喻非常重要。它看起来如何。不同的东西应该看起来不同。相似的东西应该看起来相似。” 〜拉里沃尔。调用代码与其他形式的解引用非常不同。
  • 考虑 ${$hash{a}}{b} 和 $$hash{a}{b},让没有经验的 Perler 告诉你为什么它们不同。使用引导箭头使这些东西看起来不同要容易得多。正如拉里所说,不同的事物看起来应该不同。
【解决方案3】:

我总是写下所有的箭头。我同意你的观点,它们更好地区分不同的下标。另外,我在正则表达式中使用了花括号,所以对我来说,{foo}{bar} 是一个替代品:s{foo}{bar}$s->{foo}->{bar} 中比在$s->{foo}{bar} 中更突出。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多