/ / Dereferência no caso de $ _ [0], $ _ [1] ... so on - perl

Desreferenciação no caso de $ _ [0], $ _ [1]… so on - perl

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 № 1

Muitas 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 elemento 0 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 shifte, 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 10e $ ref_array é sua referência. Portanto, o primeiro passo é obter a matriz $ref_arraye indexe a matriz.