Можно ли символически ссылаться на основной модуль Perl?
-
05-10-2019 - |
Вопрос
Я знаю, что легко мог бы сделать что-то вроде
sub sin {
sin($_[0]);
}
и символически указать, что для каждой функции мне нужно указать символ ref, но мне просто хотелось бы знать, есть ли способ сделать что-то вроде
{$foo}(123);
против.
&{$foo}(123);
который работает, но не для основных функций.
Спасибо.
Решение
AFAIK нет, ты не можешь этого сделать.По соображениям производительности, CORE
функции никогда не просматривают таблицу символов, ЕСЛИ нет эквивалента CORE::GLOBAL
функция была объявлена во время компиляции.К сожалению, вам придется это написать. CORE::GLOBAL
функцию и сделать так, чтобы она правильно имитировала соглашения о вызовах реальной функции.Некоторый CORE
функции невозможно полностью воспроизвести без масштабных хаков, print
и open
например.С CORE::GLOBAL
является глобальным и влияет на весь ваш код и весь библиотечный код, который вы должны обязательно получить точно правильно или вызвать очень трудные для отладки ошибки.Некоторые модули, такие как автоумирание, придется приложить немало усилий, чтобы охватить основные функции.
Но позвольте мне показать вам, где находится оружейный шкафчик и патроны...
my @return = eval "$function(\@args)";
...конечно, это огромная дыра в безопасности и ремонтопригодности.Не делай этого.
Другие советы
Если я прочитал Это так вопрос Правильно, вы не можете принять ссылку на встроенную функцию. Я подозреваю, что аналогичные трудности помешают вам вызовывать встроенные встроенные символические ссылки.
Что касается использования символических ссылок, чтобы вызвать код, я бы предположил, чтобы вы вместо этого используете таблицу диспетчера. Например:
use strict;
use warnings;
sub sin_deg { sin $_[0] * atan2(1, 1) / 45 }
my %dt = (
sin_deg => \&sin_deg,
attack => sub { print "Attacking: @_\n" },
);
print $dt{sin_deg}->(60), "\n";
$dt{attack}->(1, 2, 3);
Похоже, вам нужно переопределить основные функции во время компиляции, а затем вы можете возиться с ними. Хотя мне нравятся лучшее приближение Hash (или скаляр).
use strict;
use warnings;
our $s;
BEGIN {
*CORE::GLOBAL::sin= sub { sin($_[0])*2 };
*CORE::GLOBAL::cos= sub { cos($_[0])*2 };
our $s= *CORE::GLOBAL::sin;
}
*CORE::GLOBAL::sin= *CORE::GLOBAL::cos;
print sin(0.01)."\n";
print $s->(0.01)."\n";