【问题标题】:rules (?) of parens/brackets usage in perlperl 中括号/括号的使用规则 (?)
【发布时间】:2013-04-15 17:44:20
【问题描述】:

做了一些搜索,但找不到任何有用的东西。 我想知道是否有一个排序汇总表供初学者了解使用括号/括号的“规则”,特别是 ()、[]、{} 之间的区别。 不幸的是,根据我的经验,use strictuse warnings 不会告诉我我是否使用了错误的括号。

例如,以下是合法代码(b/c 它们来自 ikegami)。

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

但是下面的这些也是合法的吗?很多时候(对我来说)很难知道是否是代码的其他部分(逻辑)导致了问题。对我(一个初学者)来说,对我(初学者)进行排序似乎对良好的编码来说是微不足道的。任何关于如何正确使用括号的指南都会很棒。

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

【问题讨论】:

  • 您阅读参考教程了吗? perldoc.perl.org/perlreftut.html
  • Perl Intro 开始,然后阅读Perl data structures
  • 这些链接中的大多数都没有专门讨论括号/括号的用法,除非我在阅读中错过了它们。他们提供了与特定用法相关的示例,但我希望在了解具体情况之前先获得一个总体视图(如果存在) - 一个总体视图,例如函数总是带有大括号或数组总是带有方括号或引用总是带有大括号。 Amon 的回答确实为像我这样的初学者提供了一个很好的总结。谢谢大家。

标签: perl square-bracket curly-brackets


【解决方案1】:

在 Perl 中,方括号、大括号和圆括号都有多种含义,但花括号的含义可能最多。

  • 括号
    • 排序优先级2 * 3 + 42 * (3 + 4)
      • 为函数分隔参数列表是这种情况的一个子案例:join "", 1, 2, 3join("", 1, 2), 3
      • 用箭头运算符包围方法调用的参数列表:$foo->bar(1, 2)(空 arglist 不需要)
    • 强制将前一个裸字解释为子例程调用。比较Foo->newFoo()->new
    • 使用箭头运算符调用 coderefs:$code->()
    • 子程序原型sub foo ($$;$%) { ... }
  • 方括号
    • 数组下标运算符my @array = 1 .. 5; $array[1]
    • Arrayref 字面量my $aref = [1 .. 5]
  • 花括号
    • 块(用于dosubmapgrep、条件、循环结构、裸块、标记块……)
    • 哈希下标运算符$hash{foo}
    • Hashref 字面量my $hashref = { a => 3, b => 2 }
    • 与格块print { $filehandles[5] } "Hello world"
    • Circumfix 取消引用运算符@{ $aref }%{ $hashref }、...
    • 包块package Foo { ... }

...几乎所有字符都可以用作类似引号的运算符q//qq//qr//qx//m//s///tr///y///、导致有趣的东西,比如s(foo){bar}g


@{"genotype".($i)} 使用花括号进行符号解引用,并使用括号(不必要地)整理优先级。

@{$genotype[$i]} 使用方括号作为数组下标运算符,使用花括号作为解引用

$genotype[$i] = [ split (/:/, $original_line[$i])] 有不同的部分:$genotype[$i]$original_line[$i] 使用括号进行数组下标。 = [ ... ] 使用方括号来创建匿名数组引用。 split(/:/, ...) 中的括号只是分隔 split 的参数列表(排序优先级)。

my @genotype = map {[split /:/]} @original_line[6..14]@original_line[6..14] 中使用方括号作为数组下标运算符,在[split /:/] 中使用方括号作为匿名数组。花括号用于形成一个块作为map 的第一个参数。

【讨论】:

  • Parens 也可以用作需要表达式的空操作(@a = ();$count = () = f();
  • 我喜欢你没有声称括号创建列表的方式。
  • 卷曲也用于分隔插值中的变量(例如"${foo}bar")。实际上,您也可以在插值之外执行此操作(例如 $a = $foo;),尽管没有任何理由这样做。
  • 我在那个帖子上搜索括号列出的情况以及何时排序优先级。我有点害怕,因为我不确定括号什么时候列出一个元素。奇怪的是,在那篇文章中没有提到。
  • @MiroslavPopov Parens () 不要列出清单。列表取决于列表与标量上下文。但是,在分配列表时确实需要括号,因为= 的优先级高于逗号。标量赋值示例,不涉及列表:my $x = 1, 2, 3; my $y = (1, 2, 3); say "x=$x y=$y"x=1 y=3。列表分配示例:my @x = 1, 2, 3; my @y = (1, 2, 3); my ($z) = (1, 2, 3); say "x=(@x) y=(@y) z=$z"x=(1) y=(1 2 3) z=1
【解决方案2】:

map 有两种语法

map BLOCK LIST
map EXPR, LIST

在这两种情况下,parens 都可以像普通的 sub 一样在 args 周围使用。

map(BLOCK LIST)
map(EXPR, LIST)

需要注意的一点是,虽然 LIST 可以返回一个空列表,但它不能像 subs 一样完全省略。


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

map BLOCK LIST的一个例子,而

map([split /:/])

非法提供 EXPR,但没有 LIST。以下是可接受的语法:

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

如果表达式类似于 (2+$_)*3,则只有以下选项:

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

如果你从最后删除括号,你最终会得到非法

map(2+$_)

您可以使用 + 消除歧义

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

但最好切换到map BLOCK LIST 表示法。

【讨论】:

    猜你喜欢
    • 2022-01-09
    • 2017-07-30
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    相关资源
    最近更新 更多