При попытке реализовать макрос C assert()
в Perl возникает фундаментальная проблема.Сначала рассмотрим этот код:
sub assert($$) {
my ($assertion, $failure_msg) = @_;
die $failure_msg unless $assertion;
}
# ...
assert($boolean, $message);
Хотя это работает, это не похоже на C: в C я написал бы assert($foo <= $bar)
, но с этой реализацией мне пришлось бы написать assert($foo <= $bar, '$foo <= $bar')
, то есть повторить условие в виде строки.
Теперь мне интересно, как эффективно реализовать .Простой вариант, кажется, передает строку в assert()
и использует eval
для оценки строки, но вы не можете получить доступ к переменным при оценке eval.Даже если бы это работало, это было бы совершенно неэффективно, так как условие каждый раз анализировалось и оценивалось.
При передаче выражения я понятия не имею, как сделать из него строку, тем более что она уже оценена.
Другой вариант, использующий assert(sub { $condition })
, где, вероятно, проще сделать строку из кода ref, считается слишком уродливым.
Конструкция assert(sub { (eval $_[0], $_[0]) }->("condition"));
с
sub assert($)
{
die "Assertion failed: $_[1]\n" unless $_[0];
}
сделал бы, но уродливо звонить. решение , которое я ищу, состоит в том, чтобы записать условие для проверки только один раз , в то время как возможность воспроизвести исходное (не оцененное) условие и эффективно оценивают состояние .
Так что же является более элегантным решением?Очевидно, что решения были бы проще, если бы в Perl был макрос или сопоставимый синтаксический механизм, который позволяет преобразовывать ввод перед компиляцией или оценкой.