为什么在Perl中访问数组和散列元素时需要$?

为什么在Perl中访问数组和散列元素时需要$?,perl,arrays,hash,sigils,Perl,Arrays,Hash,Sigils,由于数组和哈希在Perl中只能包含标量,为什么在访问数组或哈希元素时必须使用$来告诉解释器该值是标量?换句话说,假设您有一个数组@myarray和一个散列%myhash,为什么需要执行以下操作: $x = $myarray[1]; $y = $myhash{'foo'}; 而不仅仅是做: $x = myarray[1]; $y = myhash{'foo'}; 为什么上面的说法模棱两可 如果Perl代码不是美元,那不是非法的吗?例如,在Perl中不是所有以下内容都是非法的吗 @var[0];

由于数组和哈希在Perl中只能包含标量,为什么在访问数组或哈希元素时必须使用$来告诉解释器该值是标量?换句话说,假设您有一个数组
@myarray
和一个散列
%myhash
,为什么需要执行以下操作:

$x = $myarray[1];
$y = $myhash{'foo'};
而不仅仅是做:

$x = myarray[1];
$y = myhash{'foo'};
为什么上面的说法模棱两可

如果Perl代码不是美元,那不是非法的吗?例如,在Perl中不是所有以下内容都是非法的吗

@var[0];
@var{'key'};
%var[0];
%var{'key'};

我可以想出一个办法

$x = myarray[1];
是不明确的-如果需要一个名为m的数组怎么办

$x = m[1];
你怎么能把它和正则表达式匹配区分开来

换句话说,语法是用来帮助Perl解释器的

切片不是非法的:

@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};

我怀疑这就是为什么需要指定是否要从哈希/数组中获取单个值的部分原因

这是有效的Perl:
@var[0]
。它是长度为1的数组片
@var[0,1]
将是长度为2的数组片

@var['key']
是无效的Perl,因为数组只能由数字索引,并且 另外两个(
%var[0]和%var['key']
)是无效的Perl,因为哈希片使用{}索引哈希

然而,
@var{'key'}
@var{0}
都是有效的哈希片。显然,取长度为1的切片是不正常的,但它肯定是有效的


有关Perl中的切片的更多信息,请参阅。

该符号提供容器的返回类型。因此,如果某个内容以
@
开头,您就知道它返回一个列表。如果它以
$
开头,则返回标量

现在,如果sigil后面只有一个标识符(如
$foo
@foo
),那么它就是一个简单的变量访问。如果它后面跟一个
[
,它就是对数组的访问,如果它后面跟一个
{
,它就是对散列的访问

# variables
$foo
@foo

# accesses
$stuff{blubb} # accesses %stuff, returns a scalar
@stuff{@list} # accesses %stuff, returns an array
$stuff[blubb] # accesses @stuff, returns a scalar
              # (and calls the blubb() function)
@stuff[blubb] # accesses @stuff, returns an array
有些人类语言有非常相似的概念

然而,许多程序员发现这令人困惑,因此Perl6使用了不变的符号


一般来说,Perl 5编译器希望在编译时知道某些内容是在列表中还是在标量上下文中,因此如果没有前导符号,某些术语将变得模棱两可。

符号为访问提供上下文:

  • $
    表示标量上下文(标量 变量或散列或数组的单个元素)
  • @
    表示列表上下文(整个数组或数据片段) (散列或数组)
  • %
    是一个完整的散列
我刚刚用过

my $x = myarray[1];
在一个程序中,让我惊讶的是,下面是我运行它时发生的事情:

$ perl foo.pl 
Flying Butt Monkeys!
这是因为整个程序看起来是这样的:

$ cat foo.pl 
#!/usr/bin/env perl

use strict;
use warnings;

sub myarray {
  print "Flying Butt Monkeys!\n";
}

my $x = myarray[1];
因此myarray调用一个子例程,将引用传递给包含单个元素1的匿名数组

这是在数组访问中需要sigil的另一个原因。

在Perl 5中(将在Perl 6中更改),sigil表示表达式的上下文

  • 您希望从散列中得到一个特定的标量,因此它是
    $hash{key}
  • 您需要数组中某个特定插槽的值,因此它是
    $array[0]
然而,正如zigdon所指出的,切片是合法的,它们在列表上下文中解释这些表达式

  • 您希望哈希
    @hash{key}
    中有一个值的列表
  • 但是更大的列表也可以工作,比如
    @hash{qw}

  • 你需要一个数组中的两个插槽
    @array[0,3,5..7,$n..$n+5]
    工作正常

  • @array[0]
    是大小为1的列表
没有“哈希上下文”,因此
%hash{@keys}
%hash{key}
都没有意义


所以您有了
“@”
+
“数组[0]”
+作为完整的表达式。

人们已经指出,可以有切片和上下文,但sigil是用来将变量与其他事物区分开来的。你不必知道所有的关键字或子例程名称,就可以选择一个合理的变量名称。这很简单关于其他语言中的Perl,我错过了一件大事。

在Perl 5中,您需要符号($和@),因为裸字标识符的默认解释是子程序调用的解释(因此在大多数情况下无需使用。

所有myhash行的形式都应该是myhash{foo'}-花括号表示散列,而不是方括号。这是原始问题中的错误。因为$y=myhash{foo}和$y=myarray[1]参数仍然适用于卷曲和方括号。参数仍然适用,但我将引用MyRayAIT全部是关于上下文。理解您可以更好地看到Perl。SIGLS不决定上下文。请考虑<代码> $x=@数组< /COD>或<代码> $n=KEK%Hash < /代码>。-<代码>和<代码>是一个子程序SIGIL -C。ode>*是指在本次采访(视频)中接触到的typeglob Sigillary Wall…。以@开头的内容返回列表,而不是数组。使用[]索引器也不一定在数组上工作。它可能是一个列表。另外,它是Perl4的阻碍。我明白了。因此,如果您在单色终端上编程,并且没有带语法高亮显示的IDE,并且使用CPAN中的多个模块,则会增加代码可读性。不,IDE和语法高亮显示与此无关。I这就是我在回答中列出的原因。