#perl
Вопрос:
У меня есть следующий сценарий:
package T;
use strict;
use warnings;
sub fn1 {
my( $var1, $var2 ) = @_;
T::fn2 $var1, $var2;
}
sub fn2 {
print ">>@_<<"; # >>x1<<
}
package main;
use strict;
use warnings;
T::fn1 'x1', 'x2'; # >>x1<<
Здесь T::fn2
вызывается с двумя аргументами, но он получает только один параметр.
Я понимаю, что вызываю подпрограмму переадресации, которая не видна во время синтаксического анализа и считается пустым словом.
Но у меня есть use strict
, use warnings
поэтому я ожидаю, что будет выдано предупреждение или программа вообще не должна работать, вместо этого она работает неправильно.
Так почему же он все еще работает и T::fn2
вызывается фактически с одним аргументом?
версия perl-5.30.3
Комментарии:
1. Вы можете опустить только парены в списке параметров для объявленных вложенных элементов.
2. @ikegami: или когда объявлена переадресация 😉
3. С каких это пор прямая декларация не является декларацией? Мои комментарии стоят сами по себе.
Ответ №1:
Бежать
perl -MO=Deparse,-p
чтобы увидеть, как компилятор понимает код:
sub fn1 {
(my($var1, $var2) = @_);
($var1->T::fn2, $var2);
}
Таким образом, вызов интерпретируется как косвенная объектная нотация вызова метода, и подпрограмма возвращает два значения: результат вызова метода и $var2
.
Чтобы заставить его работать правильно, у вас есть два варианта:
- Используйте круглые скобки вокруг аргументов подпрограммы
T::fn2($var1, $var2);
- Убедитесь, что функция объявлена перед ее вызовом
sub fn2 {
print ">>@_<<";
}
sub fn1 {
my ($var1, $var2) = @_;
T::fn2 $var1, $var2;
}
- Убедитесь, что функция объявлена до ее вызова (прямое объявление).
sub fn2;
sub fn1 {
my ($var1, $var2) = @_;
T::fn2 $var1, $var2;
}
sub fn2 {
print ">>@_<<";
}
Комментарии:
1. Однако немного странно, что код принимает
$var1
его в качестве законного объекта. Какnew FOO
и должно бытьFOO->new
, но здесь это строка.2.
method $obj
тоже работает. Косвенные обозначения объектов должны быть запрещены!3. @choroba,
no indirect;
4. @ikegami: Я знаю. Но это должно быть по умолчанию 🙂
5. @choroba Обратная совместимость. Но предполагалось, что он будет включен-э-э, выключен — по умолчанию в Perl 7