[Solved] When is it advantageous to use curly braces for dereferencing in Perl?


You are conflating two concepts.

The first thing you need to learn is that there is there are two syntaxes for deferencing.

 Circumfix            Postfix
 "Block syntax"       "Arrow syntax"

 $BLOCK               EXPR->$*
 @BLOCK               EXPR->@*
 $BLOCK[$i]           EXPR->[$i]
 &BLOCK()             EXPR->()
 ...                  ...

Furthermore, both syntax have a simplification available to them.


Your array example is an example of a simplification available to the block syntax. If the block contains nothing but a simple scalar ($ref), you can omit the 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()

If the block contains anything else, you can’t avail yourself of this simplification.

@{ $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

Your code ref example, on the other hand, is an example of the switching from the block syntax to the arrow syntax. It’s not a simplification per se.

"Block syntax"               "Arrow syntax"
&{ $hash{frogs} }()    ⇒     $hash{frogs}->()

Your code ref example is also an example of a simplification available to the arrow syntax. When the arrow is between [...] or {...}, and [...], {...} or (...), the arrow can be omitted.

$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]()

Finally, which should you use?

The choice of whether to the block syntax or the arrow syntax is one of personal preference, but the following conventions are usually followed to maximize readability:

  • The block syntax is preferred for scalar, array and hash dereferences.

    $$ref                is generally preferred over     $ref->$*
    @$ref                is generally preferred over     $ref->@*
    %$ref                is generally preferred over     $ref->%*
    
  • When using the block syntax, curlies are omitted if possible.

    $$ref                is generally preferred over     ${ $ref }
    @$ref                is generally preferred over     @{ $ref }
    %$ref                is generally preferred over     %{ $ref }
    
  • The arrow syntax is preferred for array element, hash element and code dereferences.

    $ref->[...]          is generally preferred over     $$ref[...]
    $ref->{...}          is generally preferred over     $$ref{...}
    $ref->(...)          is generally preferred over     &$ref(...)
    
  • The arrow itself is omitted when possible, except when used to deference code.

    $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->{...}(...)
    
  • The block syntax is preferred for array slices and hash slices. It’s far less readable than the arrow syntax, but the arrow syntax for these requires Perl 5.24.

    @$ref[...]           is generally preferred over     $ref->@[...]
    @$ref{...}           is generally preferred over     $ref->@{...}
    

5

solved When is it advantageous to use curly braces for dereferencing in Perl?