Как я могу ввести несколько строк с помощью Devel:: Declare?
Я хочу использовать Devel::Declare
для ввода нескольких строк кода Perl. Однако Devel::Declare::set_linestr()
не может иметь дело с несколькими строками.
Обычно я хотел бы объединить несколько операторов вместе как одну строку. Эти утверждения должны быть в отдельных строках, чтобы сохранить номера строк для целей сообщения об ошибках. Это необходимо решить эту ошибку в методе:: Подписи и эта связанная ошибка. Я открыт для альтернативных решений.
Например, метод:: Signatures в настоящее время включает этот код...
use Method::Signatures;
func hello(
$who = "World",
$greeting = get_greeting($who)
) {
die "$greeting, $who";
}
... в это...
func \&hello; sub hello { BEGIN { Method::Signatures->inject_scope('') }; my $who = (@_ > 0) ? ($_[0]) : ( get_greeting($who)); my $greeting = (@_ > 1) ? ($_[1]) : ( "Hello"); Method::Signatures->too_many_args_error(2) if @_ > 2;
die "$greeting, $who";
}
die $who
после этого сообщает строку 4 вместо строки 7.
Я бы хотел, чтобы это было вместо этого (или, возможно, с участием #line
).
func \&hello; sub hello { BEGIN { Method::Signatures->inject_scope('') };
my $who = (@_ > 0) ? ($_[0]) : ( "World");
my $greeting = (@_ > 1) ? ($_[1]) : ( get_greeting($who));
Method::Signatures->too_many_args_error(2) if @_ > 2;
die "$greeting, $who";
}
Не только это верно воспроизводит номера строк, если get_greeting
сжимает, он будет сообщать, что был вызван из правильной строки.
Ответы
Ответ 1
В соответствии с вашим собственным ответом, следующие работы:
sub __empty() { '' }
sub parse_proto {
my $self = shift;
return q[print __LINE__."\n"; Foo::__empty(
);print __LINE__."\n"; Foo::__empty(
);print __LINE__."\n";];
}
Но вводит неприемлемые служебные данные, потому что функция __empty()
должна вызываться для каждого параметра. Накладные расходы можно устранить, вызвав __empty()
условно, используя условие, которое никогда не будет оцениваться как true.
sub __empty() { '' }
sub parse_proto {
my $self = shift;
return q[print __LINE__."\n"; 0 and Foo::__empty(
);print __LINE__."\n"; 0 and Foo::__empty(
);print __LINE__."\n";];
}
Ответ 2
Я понял способ сделать это, но он взломан и медленный.
Я заметил, что вы можете вводить строки с буквальными символами новой строки в них, и они будут работать. Я считаю, что синтаксический анализатор знает достаточно, чтобы продолжать следовать за новой строкой в строке. Я решил, что можно использовать это, чтобы обмануть парсер, чтобы он продолжал идти.
package Foo;
use strict;
use warnings;
use v5.12;
use parent "Devel::Declare::MethodInstaller::Simple";
sub import {
my $class = shift;
my $caller = caller;
$class->install_methodhandler(
into => $caller,
name => 'method'
);
}
sub parse_proto {
my $self = shift;
return q[print __LINE__."\n"; my $__empty = q{
};print __LINE__."\n"; $__empty = q{
};print __LINE__."\n";];
}
1;
И он работает... кроме __LINE__
не увеличивается. Сбой в Perl-парсере? Я попробовал регулярное выражение с новой строкой в нем, которая также не увеличивала строку.
Но работает подпрограмма!
sub __empty() { '' }
sub parse_proto {
my $self = shift;
return q[print __LINE__."\n"; Foo::__empty(
);print __LINE__."\n"; Foo::__empty(
);print __LINE__."\n";];
}
И это постоянный вызов подпрограммы, Perl должен оптимизировать его, правильно? Увы, нет. Кажется, что новая линия в вызове обманывает оптимизатора. С другой стороны, это предотвращает предупреждение "Бесполезное использование константы в пустоте". С нижней стороны он вводит вызов подпрограммы для каждого параметра и недопустимое количество служебных данных для добавления к каждому вызову подпрограммы.
Может кто-то может придумать умный способ проклинать новую строку в синтаксисе Perl?