我看到了一些像这样的代码〜
my @array = @{ $array_ref };
我发现如果将其更改为〜
,它的工作方式也是一样的my @array = @$array_ref;
同样,这个〜
my %hash = (frogs => sub {print "Frogs\n"});
&{$hash{frogs}}();
与〜
的作用相同%hash = (frogs => sub {print "Frogs\n"});
$hash{frogs}();
(虽然我最初尝试将&hash{frogs}();
期望它起作用,但由于产生的错误我不理解 - 不应该将sigil对应于散列中被访问的内容,在这种情况下{{1} 1}}用于子程序?)
所以我想知道为什么这些片段的作者会用另一种方式写出来,当它是额外的字符而没有我能感知到的任何优势时。
这里发生了什么我没有注意到的事情?何时可能存在需要使用花括号而不仅仅是sigil的情况?
答案 0 :(得分:7)
你正在混淆两个概念。
您需要了解的第一件事是有two syntaxes用于引用。
"Block syntax" "Arrow syntax"
$BLOCK EXPR->$*
@BLOCK EXPR->@*
$BLOCK[$i] EXPR->[$i]
&BLOCK() EXPR->()
... ...
此外,两种语法都可以使用它们。
您的数组示例是块语法可用的简化示例。如果块只包含一个简单的标量($ref
),则可以省略curles。
${ $ref } # Can be simplified to $$ref
@{ $ref } # Can be simplified to @$ref
${ $ref }[$i] # Can be simplified to $$ref[$i]
&{ $ref }() # Can be simplified to &$ref()
如果该块包含其他任何内容,则无法利用此简化。
@{ $refs{$key} } # Can't be simplified
@{ f() } # Can't be simplified
@{ my $ref = f(); $ref } # Can't be simplified
&{ $refs{$key} }() # Can't be simplified
&{ f() }() # Can't be simplified
&{ my $ref = f(); $ref } # Can't be simplified
另一方面,您的代码示例是从块语法切换到箭头语法的示例。这不是简化本身。
"Block syntax" "Arrow syntax"
&{ $hash{frogs} }() ⇒ $hash{frogs}->()
您的代码参考示例也是箭头语法可用的简化示例。当箭头位于[...]
或{...}
以及[...]
,{...}
或(...)
之间时,箭头可以省略。
$ref->{$k}->[$i] # Can be simplified to $ref->{$k}[$i]
$ref->{$k}->{$l} # Can be simplified to $ref->{$k}{$l}
$ref->{$k}->() # Can be simplified to $ref->{$k}()
$ref->[$i]->[$j] # Can be simplified to $ref->[$i][$j]
$ref->[$i]->{$k} # Can be simplified to $ref->[$i]{$k}
$ref->[$i]->() # Can be simplified to $ref->[$i]()
最后,您应该使用哪个?
是否对块语法或箭头语法的选择是个人偏好之一,但通常遵循以下约定以最大化可读性:
块语法是标量,数组和散列解引用的首选。
$$ref is generally preferred over $ref->$*
@$ref is generally preferred over $ref->@*
%$ref is generally preferred over $ref->%*
使用块语法时,如果可能,将省略curlies。
$$ref is generally preferred over ${ $ref }
@$ref is generally preferred over @{ $ref }
%$ref is generally preferred over %{ $ref }
箭头语法是数组元素,哈希元素和代码解引用的首选。
$ref->[...] is generally preferred over $$ref[...]
$ref->{...} is generally preferred over $$ref{...}
$ref->(...) is generally preferred over &$ref(...)
尽可能省略箭头本身,除非用于参考代码。
$ref->[...][...] is generally preferred over $ref->[...]->[...]
$ref->[...]{...} is generally preferred over $ref->[...]->{...}
$ref->[...]->(...) is generally preferred over $ref->[...](...)
$ref->{...}[...] is generally preferred over $ref->{...}->[...]
$ref->{...}{...} is generally preferred over $ref->{...}->{...}
$ref->{...}->(...) is generally preferred over $ref->{...}(...)
块语法是数组切片和散列切片的首选。它的可读性远远低于箭头语法,但这些箭头语法需要Perl 5.24。
@$ref[...] is generally preferred over $ref->@[...]
@$ref{...} is generally preferred over $ref->@{...}
答案 1 :(得分:2)
您的代码 主要 供其他人和编译器/解释器阅读。初级程序员往往倾向于将他们的创作视为纯粹为了他们自己的消费,作为一种生活记事本,但是编写设计笔记确实有比用编程语言编码更好的方法。
它向(人类)读者清楚地解释了你的代码在做什么。你@$array_ref
的例子(除非你真的需要两份相同的数据列表,否则没有意义)很好,但是你怎么读$$array_ref{key}
?
大多数人都没有在他们的头脑中保留运算符优先级表,因此通过编写$array_ref->{key}
或{{更容易解释您的意图1}}取决于你的意思
鉴于你提到这个
${ $array_ref{key} }
我认为你正在阅读一些相当陈旧的东西,或者由一个对Perl特别不熟悉的人写的东西。只有当您将子例程称为第一类数据对象(例如获取引用)并且仅调用子例程时,&{$hash{frogs}}()
前缀才是必需的
Perl允许您在连续的结束和左括号之间省略间接运算符&
,但它通常更清楚地包含它。我通常在卷括号和方括号(索引哈希值或数组)之间省略它,但保留它用于过程调用
我会将该行写为
->