Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rules (?) of parens/brackets usage in perl

Did some search but couldn't find anything useful. I was wondering if there is a summary table of sort for beginners to learn about the "rules" of using parens/brackets, specifically, the differences among (), [], {}. Unfortunately, in my experience, use strict and use warnings don't tell me if I use the wrong parens.

For example, below are the legit codes (b/c they came from ikegami).

@{"genotype".($i)}
@{$genotype[$i]}
$genotype[$i] = [ split (/:/, $original_line[$i])]
my @genotype = map {[split /:/]} @original_line[6..14]

But are these below also legit ? Often times it's hard enough (for me) to know if it's other parts (logic) of the codes that cause the problem. Sorting through parens to me (a beginner) seems trivial to good coding. Any guide on how to properly use parens will be great.

@{"genotype".[$i]}
@["genotype".($i)]
@("genotype".($i))
@{$genotype($i)}
@[$genotype($i)]
$genotypes[$i] = ( split (/:/, $original_line[$i]))
my @genotype = map ([split /:/]) @original_line[6..14]
like image 721
B Chen Avatar asked Apr 22 '13 17:04

B Chen


2 Answers

In Perl, brackets, braces and parens all have multiple meanings, but curly braces probably have the most.

  • Parens
    • Sort out precedence 2 * 3 + 4 vs. 2 * (3 + 4).
      • Delimiting argument lists for functions is a subcase of this: join "", 1, 2, 3 vs. join("", 1, 2), 3
      • Surround argument list of method call with arrow operator: $foo->bar(1, 2) (not needed for empty arglist)
    • Force interpretation of the previous bareword as a subroutine call. Compare Foo->new and Foo()->new.
    • Invoke coderefs with arrow operator: $code->()
    • Subroutine prototypes sub foo ($$;$%) { ... }
  • Square Brackets
    • Array subscript operator my @array = 1 .. 5; $array[1]
    • Arrayref literals my $aref = [1 .. 5]
  • Curly braces
    • Blocks (for do, sub, map, grep, conditionals, looping constructs, bare blocks, labeled blocks, ... )
    • Hash subscript operator $hash{foo}
    • Hashref literal my $hashref = { a => 3, b => 2 }
    • Dative block print { $filehandles[5] } "Hello world"
    • Circumfix dereference operators @{ $aref }, %{ $hashref }, ...
    • package blocks package Foo { ... }

… and nearly all characters can be used as delimiters for quote-like operators q//, qq//, qr//, qx//, m//, s///, tr///, y///, leading to interesting stuff like s(foo){bar}g


@{"genotype".($i)} uses curlies for symbolic dereferencing, and parens to (unneccessarily) sort out precedence.

@{$genotype[$i]} uses brackets as array subscript operator, and curlies for dereferencing

$genotype[$i] = [ split (/:/, $original_line[$i])] has various parts: $genotype[$i] and $original_line[$i] use brackets for array subscripting. The = [ ... ] uses brackets to make an anonymous arrayref. The parens in split(/:/, ...) just delimit the argument list for split (sorting out the precedence).

my @genotype = map {[split /:/]} @original_line[6..14] uses brackets as the array subscript operator in @original_line[6..14], and for an anonymous array in [split /:/]. The curlies are used to form a block as first argument to map.

like image 91
amon Avatar answered Oct 23 '22 03:10

amon


map has two syntaxes

map BLOCK LIST
map EXPR, LIST

In both cases, parens can be used around the args like a normal sub.

map(BLOCK LIST)
map(EXPR, LIST)

One thing of note is that while LIST can return an empty list, it cannot be omitted entirely as you can for subs.


map { [split /:/] } @original_line[6..14]

is an example of map BLOCK LIST, while

map([split /:/])

illegally provides EXPR, but no LIST. Here are acceptable syntaxes:

map({ [split /:/] } @original_line[6..14])
map { [split /:/] } @original_line[6..14]
map([split /:/], @original_line[6..14])
map [split /:/], @original_line[6..14]

If the expression was something like (2+$_)*3, you only have these options:

map({ (2+$_)*3 } ...)
map { (2+$_)*3 } ...
map((2+$_)*3,  ...)

If you remove the parens from that last, you end up with the illegal

map(2+$_)

You can disambiguate using +

map +(2+$_)*3, ...

but it's better to switch to the map BLOCK LIST notation.

like image 41
ikegami Avatar answered Oct 23 '22 01:10

ikegami