por favor veja o código abaixo:
$scalar = 10;
subroutine($scalar);
sub subroutine {
my $subroutine_scalar = ${$_[0]}; #note you need the {} brackets, or this doesn"t work!
print "$subroutine_scalarn";
}
No código acima você pode ver o comentário escrito "note que você precisa dos {} colchetes, ou isto não funciona!". Explique por que não podemos usar a mesma declaração como:
my $subroutine_scalar = $$_[0];
ou seja, sem usar as chaves.
Respostas:
8 para resposta № 1Muitas pessoas já deram respostas corretas aqui. Eu queria adicionar um exemplo que encontrei iluminando. Você pode ler a documentação em perloc perldoc Para maiores informações.
Seu problema é de ambigüidade, você tem duas operações $$
e [0]
trabalhando no mesmo identificador _
e o resultado depende de qual operação é executada primeiro. Nós podemos torná-lo menos ambíguo, usando o suporte de chaves ${ ... }
. $$_[0]
poderia (para um humano de qualquer maneira) possivelmente significar:
${$$_}[0]
- desreferenciar o escalar$_
, então pegue seu primeiro elemento.${$_[0]}
- pega elemento0
da matriz@_
e desreferenciá-lo.
Como você pode ver, esses dois casos se referem a variáveis completamente diferentes, @_
e $_
.
Claro, para Perl não é ambíguo, nósbasta obter a primeira opção, pois a desreferenciação é realizada antes da pesquisa de chave. Precisamos do suporte de chaves para substituir essa desreferenciação, e é por isso que seu exemplo não "funciona" sem chaves de suporte.
Você pode considerar uma funcionalidade um pouco menos confusa para sua sub-rotina. Em vez de tentar fazer duas coisas ao mesmo tempo (obtenha o argumento e desreferencie-o), você pode fazê-lo em dois estágios:
sub foo {
my $n = shift;
print $$n;
}
Aqui, retiramos o primeiro argumento @_
com shift
e, em seguida, desreferencie-o. Limpo e simples.
Na maioria das vezes, você não usará referências a variáveis escalares. E nesses casos, você pode usar o operador de seta ->
my @array = (1,2,3);
foo(@array);
sub foo {
my $aref = shift;
print $aref->[0];
}
Acho que usar o operador de seta é preferível ao $$
sintaxe.
2 para resposta № 2
${ $x }[0]
pega o valor do elemento 0 na matriz referenciada por $x
.
${ $x[0] }
pega o valor de escalar referenciado pelo elemento 0 da matriz @x
.
>perl -E"$x=["def"]; @x="abc"; say ${ $x }[0];"
def
>perl -E"$x=["def"]; @x="abc"; say ${ $x[0] };"
abc
$$x[0]
é curto para ${ $x }[0]
.
>perl -E"$x=["def"]; @x="abc"; say $$x[0];"
def
2 para resposta № 3
my $subroutine_scalar = $$_[0];
é o mesmo que
my $subroutine_scalar = $_->[0]; # $_ is array reference
Por outro lado,
my $subroutine_scalar = ${$_[0]};
desreferências referência escalar para o primeiro elemento de @_
matriz e pode ser escrito como
my ($sref) = @_;
my $subroutine_scalar = ${$sref}; # or $$sref for short
1 para resposta № 4
Porque $$_[0]
significa ${$_}[0]
.
Considere esses dois pedaços de código que ambos imprimem 10
:
sub subroutine1 {
my $scalar = 10;
my $ref_scalar = $scalar;
my @array = ($ref_scalar);
my $subroutine_scalar = ${$array[0]};
print "$subroutine_scalarn";
}
sub subroutine2 {
my @array = (10);
my $ref_array = @array;
my $subroutine_scalar = $$ref_array[0];
print "$subroutine_scalarn";
}
Dentro subroutine1
, @array
é uma matriz que contém a referência de $scalar
. Portanto, o primeiro passo é obter o primeiro elemento $array[0]
e depois deferência.
Enquanto em subroutine2
, @array
é uma matriz que contém um escalar 10
e $ ref_array é sua referência. Portanto, o primeiro passo é obter a matriz $ref_array
e indexe a matriz.