Что означает $ dummy и непараметрическое разделение в Perl? - PullRequest
2 голосов
/ 17 декабря 2011

Мне нужна помощь в расшифровке этого сценария Perl.$ dummy не инициализируется нигде в скрипте.Что означает следующая строка в скрипте?и почему это означает, что функция разделения не имеет какого-либо параметра?

($dummy, $class) = split;

Программа пытается проверить, является ли утверждение истинным или ложным, используя какой-либо метод статистической классификации.Допустим, он вычисляет и присваивает «истинность» и «ложь» следующее число, а затем проверяет, является ли детектор лжи верным или нет.

# some code, some code...
$_ = "truth"
# more some code, some code ...

$Truthsity = 9999
$Falsity = 2134123

if ($Truthsity > $Falsity) {   
    $newClass = "truth";      
} else {
    $newClass = "lie";     
}

($dummy, $class) = split;

if ($class eq $newClass) {
    print "correct";
} elsif ($class eq "true") {
    print "false neg";
} else {
    print "false pos"
}

Ответы [ 3 ]

5 голосов
/ 17 декабря 2011
($dummy, $class) = split;

Split возвращает массив значений. Первое помещается в $dummy, второе - в $class, и любые дальнейшие значения игнорируются. Первый аргумент, скорее всего, называется dummy, потому что автор планирует игнорировать это значение. Лучший вариант - использовать undef для игнорировать возвращенную запись: ( undef, $class ) = split;

Perldoc может показать вам, как работает функция разделения. При вызове без аргументов функция split будет работать против $_ и будет разделяться пробелами. $_ - это переменная по умолчанию в perl, воспринимайте ее как подразумеваемое «это», как определено контекстом.

Использование подразумеваемого $ _ может сделать короткий код более кратким, но его использование в больших блоках является плохой формой. Вы не хотите, чтобы читатель запутался в том, с каким «этим» вы хотите работать.

split ;                      # split it
for (@list) { foo($_) }      # look at each element of list, foo it.
@new = map { $_ + 2 } @list ;# look at each element of list, 
                             # add 2 to it, put it in new list
while(<>){ foo($_)}          # grab each line of input, foo it.

perldoc -f split

Если EXPR опущен, разбивает строку $ _. Если PATTERN также опущен, разбивается на пробел (после пропуска любого начального пробела). Все, что соответствует ШАБЛОНУ считается разделителем полей. (Обратите внимание, что разделитель может быть длиннее одного символа.)

Я большой поклонник троичного оператора ? : для установки строковых значений и проталкивания логики в блоки и подпрограммы.

my $Truthsity = 9999
my $Falsity   = 2134123

print test_truthsity( $Truthsity, $Falsity, $_ );

sub test_truthsity {
  my ($truthsity, $falsity, $line ) = @_;
  my $newClass = $truthsity > $falsity ? 'truth' : 'lie';
  my (undef, $class) = split /\s+/, $line ;

  my $output = $class eq $newClass ? 'correct' 
             : $class eq 'true'    ? 'false neg'
             :                       'false pos';
  return $output;
}

В этой версии может быть небольшая ошибка. split без аргументов - это не то же самое, что split(/\s+/, $_), они ведут себя иначе, если строка начинается с пробелов. В полностью определенном разбиении возвращаются пустые ведущие поля. split без аргументов отбрасывает начальные пробелы.

$_ = "  ab cd";
my @a = split             # @a contains ( 'ab', 'cd' );
my @b = split /\s+/, $_;  # @b contains ( '', 'ab', 'cd')
3 голосов
/ 17 декабря 2011

Из документации для split:

split / PATTERN /, EXPR

Если EXPR опущен, разбивает строку $ _.Если PATTERN также опущен, разделяется на пробел (после пропуска любого начального пробела).Все, что соответствует ШАБЛОНУ, считается разделителем полей.(Обратите внимание, что разделитель может быть длиннее одного символа.)

Таким образом, поскольку и шаблон, и выражение опущены, мы разделяем переменную по умолчанию $_ на пробел.

Цель переменной $dummy состоит в том, чтобы захватить первый элемент списка, возвращенный из split, и игнорировать его, поскольку код заинтересован только во втором элементе, который помещается в $class.

Вам нужно взглянуть на окружающий код, чтобы узнать, что $_ находится в этом контексте;это может быть переменная цикла или элемент списка в блоке map, или что-то еще.

2 голосов
/ 17 декабря 2011

Если вы прочитаете документацию , вы обнаружите, что:

  • Значение по умолчанию для первого операнда " ".
  • Значение по умолчанию длявторой операнд - $_.
  • По умолчанию для третьего операнда 0.

, поэтому

split

- это сокращение от

split " ", $_, 0

и это означает:

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

Первое результирующее поле помещается в $dummy, ивторое в $class.

Исходя из его имени, я предполагаю, что вы больше никогда не используете $dummy, так что он просто действует как заполнитель.Вы можете избавиться от этого, однако.

my ($dummy, $class) = split;

можно записать как

my (undef, $class) = split;   # Use undef as a placeholder

или

my $class = ( split )[1];     # Use a list slice to get second item
...