Por que você precisa de US $ ao acessar matriz e hash elementos em Perl?
Pergunta
Desde arrays e hashes só pode conter escalares em Perl, por que você tem que usar o $ para dizer o intérprete que o valor é um escalar ao acessar matriz ou de hash elementos? Em outras palavras, supondo que você tem um @myarray
array e um %myhash
de hash, por que você precisa fazer:
$x = $myarray[1];
$y = $myhash{'foo'};
em vez de apenas fazer:
$x = myarray[1];
$y = myhash{'foo'};
Por que o acima ambígua?
Não seria código ilegal Perl se era tudo menos um $ naquele lugar? Por exemplo, não são todos os seguintes ilegal em Perl?
@var[0];
@var{'key'};
%var[0];
%var{'key'};
Solução
As fatias não são ilegais:
@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};
E eu suspeito que é parte da razão por que você precisa para especificar se você deseja obter um valor único para fora do hash / array ou não.
Outras dicas
Eu apenas usei
my $x = myarray[1];
em um programa e, para minha surpresa, aqui está o que aconteceu quando eu corri-lo:
$ perl foo.pl
Flying Butt Monkeys!
Isso porque o programa completo fica assim:
$ cat foo.pl
#!/usr/bin/env perl
use strict;
use warnings;
sub myarray {
print "Flying Butt Monkeys!\n";
}
my $x = myarray[1];
chamadas Então MyArray uma sub-rotina de passá-lo uma referência para um array anônimo contendo um único elemento, 1.
Essa é outra razão que você precisa o sigilo em um acesso de matriz.
O sigilo dar-lhe o tipo de retorno do recipiente. Então, se algo começa com @
, você sabe que ele retorna uma lista. Se ele começa com $
, ele retorna um escalar.
Agora, se houver apenas um identificador após o sigilo (como $foo
ou @foo
, então é um simples acesso variável. Se ele é seguido por um [
, é um acesso em uma matriz, se for seguido por um {
, é uma acesso em um hash.
# 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
Alguns idiomas humanos têm conceitos muito semelhantes.
No entanto, muitos programadores descobriram que confuso, então Perl 6 usa um sigilo invariante.
Em geral, o compilador Perl 5 quer saber em tempo de compilação, se algo está na lista ou no contexto escalar, assim, sem o líder sigilo alguns termos se tornaria ambígua.
Isso é válido Perl: @var[0]
. É uma faixa da matriz de um comprimento. @var[0,1]
seria uma fatia de matriz de comprimento de dois.
@var['key']
é válido Perl porque as matrizes só podem ser indexados por números, e
os outros dois (%var[0] and %var['key']
) não são válidos Perl porque fatias de hash usar o} {para indexar o hash.
@var{'key'}
e @var{0}
são ambos fatias de hash válido, no entanto. Obviamente que não é normal para tomar fatias de um comprimento, mas é certamente válido.
seção fatia de perldata perldoc para obter mais informações sobre o corte em Perl.
As pessoas já têm apontado que você pode ter fatias e contextos, mas sigilos estão lá para separar as coisas que são variáveis ??de tudo o resto. Você não tem que saber todas as palavras-chave ou nomes de sub-rotina de escolher um nome de variável sensível. É uma das grandes coisas que eu perca sobre Perl em outros idiomas.
Não consigo pensar em uma maneira que
$x = myarray[1];
é ambígua - o que se você queria um array chamado m
$x = m[1];
Como você pode dizer que para além de um jogo de regex?
Em outras palavras, a sintaxe é lá para ajudar o intérprete Perl, assim, interpretar!
Em Perl 5 (a ser mudado em Perl 6) um sigilo indica o contexto de sua expressão.
- Você quer um fora escalar particular de um hash por isso é
$hash{key}
. - Você quer que o valor de um determinado slot de um array, por isso é
$array[0]
.
No entanto, como fora apontado por Zigdon, fatias são legais. Eles interpretam os aquelas expressões em um lista ??em> contexto.
- Você quer uma lista de 1 valor em um hash de obras
@hash{key}
-
Mas as listas também maiores funcionar tão bem, como
@hash{qw<key1 key2 ... key_n>}
. -
Você quer um par de slots de fora funciona um conjunto
@array[0,3,5..7,$n..$n+5]
-
@array[0]
é uma lista de tamanho 1.
Não existe um "contexto de hash", então, nem %hash{@keys}
nem %hash{key}
tem significado.
Então você tem "@"
+ "array[0]"
<=>
O sigilo fornece o contexto para o acesso:
-
$
significa contexto escalar (um escalar variável ou um único elemento de um hash ou uma matriz) -
@
significa contexto de lista (a matriz inteira ou uma fatia de um hash ou uma matriz) -
%
é um hash inteira
Em Perl 5 você precisa dos sigilos ($ e @) porque a interpretação padrão do identificador bareword é o de uma chamada de subrotina (eliminando assim a necessidade de uso e na maioria dos casos).