В чем отличие использования специальной переменной $_ и @_ в Perl?

Пожалуйста, объясните, что именно разница $_ и @_ находится в Perl. Когда использовать, который указан в примере кода.

Ответ 1

Когда в подпрограмме массив @_ дает аргументы, переданные данной подпрограмме. Например:

use strict;
use warnings;

sub print_em
{
  foreach my $arg (@_)
  {
    print "You passed in $arg.\n";
  }
}

print_em("foo","bar","baz");

Выходной сигнал

You passed in foo.
You passed in bar.
You passed in baz.

Скаляр $_ обычно используется как переменная в цикле. Например:

use strict;
use warnings;

# Note that we are not declaring a variable
# that takes on the values 1 through 5.
foreach(1..5) 
{
  print "$_\n";
}

Вывод:

1
2
3
4
5

Аналогично, мы могли бы немного переписать подпрограмму print_em выше как

sub print_em
{
  foreach(@_)
  {
    print "You passed in $_.\n";
  }
}

или даже как более компактный

sub print_em{ print "You passed in $_.\n" foreach(@_);}

Переменная $_ также может использоваться как "аргумент по умолчанию" для определенных функций. Например:

use strict;
use warnings;

$_="foobar";

if(/bar/) #We do not have to write $_=~/bar/
{
  print "matched!\n";
}

который, конечно, выводит matched!.

Взгляните на perldoc perlvar для получения дополнительной информации об этих и других "волшебных переменных" Perl.

Ответ 2

Ответ Jack Maney охватывает ваш точный вопрос, но я также хотел кое-что отметить: вы не должны быть обмануты только частью названия переменной. Сигал тоже. $_ и @_ являются совершенно разными переменными, такими как $foo и @foo, а также $bar и %bar. Perl сохраняет их полностью отдельно друг от друга.

Ответ 3

Один из часто встречающихся примеров связан с I/O. Этот код...

while(<>)
{
  chomp;
  print if(m/^chr1/);
}

... функционально эквивалентен этому коду.

while(my $line = <STDIN>)
{
  chomp($line);
  print($line) if($line =~ m/^chr1/);
}

Всякий раз, когда у вас есть цикл, переменная $_ заполняется, но есть и более явный синтаксис. Этот код...

foreach(@a)
{
  print;
  chomp;
  push(@b, $_)
}

... функционально эквивалентен этому коду.

foreach my $value(@a)
{
  print($value);
  chomp($value);
  push(@b, $value);
}

Одно дело иметь в виду $_ и другие магические переменные - это то, что они могут быть довольно загадочными для нового программиста. Со временем я использовал их все меньше и меньше в пользу более явного синтаксиса, который (надеюсь) облегчает другим понимание намерения кода.

Ответ 4

Ни $_, ни @_ не является неотъемлемо особенным. Помимо того, что они являются глобальными, они являются полностью нормальными переменными. Они не волшебны. Ничего особенного не происходит, когда вы назначаете их или читаете с них.

Причина @_ используется так часто, что Perl помещает аргументы функции. Если вы хотите получить аргументы, переданные вашему суб, вам нужно получить доступ к @_.

 sub f {
    my ($x, $y) = @_;
    ...
 }

Причина $_ используется так часто, что некоторые операторы Perl присваивают ей по умолчанию, а другие используют ее значение по умолчанию для своего аргумента. Это может привести к сокращению кода, если вы его охватите, но вам никогда не придется его использовать.

for my $x (@x) { say $x; }
   vs
for (@x) { say; }