何时在Perl中使用花括号进行解除引用是有利的?

tem*_*ame -4 perl

我看到了一些像这样的代码〜

my @array = @{ $array_ref };
Run Code Online (Sandbox Code Playgroud)

我发现如果我把它改成〜它的工作原理是一样的

my @array = @$array_ref;
Run Code Online (Sandbox Code Playgroud)

同样,这个〜

my %hash = (frogs => sub {print "Frogs\n"});
&{$hash{frogs}}();
Run Code Online (Sandbox Code Playgroud)

与〜一样工作

%hash = (frogs => sub {print "Frogs\n"});
$hash{frogs}();
Run Code Online (Sandbox Code Playgroud)

(虽然我最初尝试过,因为&hash{frogs}();期望它能够工作,但由于产生的错误我不明白 - 这个sigil是否应该与哈希中访问的东西相对应,在这种情况下&对于子程序?)

所以我想知道为什么这些片段的作者会以另一种方式编写它们,当它是额外的字符而没有我能感知到的任何优势时.

在这里发生的事情我没有注意到吗?什么时候你可能需要使用花括号而不仅仅是sigil?

ike*_*ami 7

你在混淆两个概念.

您需要学习的第一件事是有两种用于引用的语法.

 "Block syntax"       "Arrow syntax"

 $BLOCK               EXPR->$*
 @BLOCK               EXPR->@*
 $BLOCK[$i]           EXPR->[$i]
 &BLOCK()             EXPR->()
 ...                  ...
Run Code Online (Sandbox Code Playgroud)

此外,两种语法都可以使用它们.


您的数组示例是块语法可用的简化示例.如果块只包含一个简单的标量($ref),则可以省略curlies.

${ $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()
Run Code Online (Sandbox Code Playgroud)

如果该块包含其他任何内容,则无法利用此简化.

@{ $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
Run Code Online (Sandbox Code Playgroud)

另一方面,您的代码示例是从块语法切换到箭头语法的示例.这本身并不简单.

"Block syntax"               "Arrow syntax"
&{ $hash{frogs} }()    ?     $hash{frogs}->()
Run Code Online (Sandbox Code Playgroud)

您的代码示例也是箭头语法可用的简化示例.当箭头之间[...]{...},和[...],{...}(...),箭头可以省略.

$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]()
Run Code Online (Sandbox Code Playgroud)

最后,你应该使用哪个?

是否对块语法或箭头语法的选择是个人偏好之一,但通常遵循以下约定以最大化可读性:

  • 块语法是标量,数组和散列解引用的首选.

    $$ref                is generally preferred over     $ref->$*
    @$ref                is generally preferred over     $ref->@*
    %$ref                is generally preferred over     $ref->%*
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用块语法时,如果可能,将省略curlies.

    $$ref                is generally preferred over     ${ $ref }
    @$ref                is generally preferred over     @{ $ref }
    %$ref                is generally preferred over     %{ $ref }
    
    Run Code Online (Sandbox Code Playgroud)
  • 箭头语法是数组元素,哈希元素和代码解引用的首选.

    $ref->[...]          is generally preferred over     $$ref[...]
    $ref->{...}          is generally preferred over     $$ref{...}
    $ref->(...)          is generally preferred over     &$ref(...)
    
    Run Code Online (Sandbox Code Playgroud)
  • 尽可能省略箭头本身,除非用于参考代码.

    $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->{...}(...)
    
    Run Code Online (Sandbox Code Playgroud)
  • 块语法是数组切片和散列切片的首选.它的可读性远远低于箭头语法,但这些箭头语法需要Perl 5.24.

    @$ref[...]           is generally preferred over     $ref->@[...]
    @$ref{...}           is generally preferred over     $ref->@{...}
    
    Run Code Online (Sandbox Code Playgroud)