Можно ли символически ссылаться на основной модуль Perl?

Я знаю, я мог бы легко сделать что-то вроде

sub sin {
    sin($_[0]);
}

и символически ссылаюсь на то, что для каждой функции мне нужно symb ref, но я просто хотел бы знать, есть ли способ сделать что-то вроде

{$foo}(123);

против

&{$foo}(123);

который работает, но не для основных функций.

Благодарю.

3 ответа

Решение

AFAIK нет, вы не можете сделать это. По причинам производительности CORE функции никогда не смотрят на таблицу символов, ЕСЛИ ЭТО CORE::GLOBAL функция была объявлена ​​во время компиляции. К сожалению, вы должны написать, что CORE::GLOBAL функция и получить его правильно моделировать соглашения о вызовах реальной функции. Немного CORE функции не могут быть полностью воспроизведены без массивных взломов, print а также open например. поскольку CORE::GLOBAL Это глобальный эффект, влияющий на весь ваш код и весь библиотечный код, который вы должны быть уверены, что получите его правильно, или будете очень трудно отлаживать ошибки. Некоторые модули, такие как autodie, должны идти на все, чтобы обернуть основные функции.

Но здесь, позвольте мне показать вам, где находятся шкафчик с оружием и боеприпасы...

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);

Похоже, вам нужно переопределить основные функции во время компиляции, а затем вы можете возиться с ними. Тем не менее, мне больше нравится подход рассылки (или скалярный).

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";
Другие вопросы по тегам