Преобладающий хриплый клоун исповедует карпа из модуля карпа в Perl

Я знаю, как переопределить встроенные функции в perl и я переопределил diewarnsay и с тех пор print а также printf не может быть переопределено, я привязал его к дескриптору для моей системы ведения журналов.

Пример переопределения warn :

BEGIN{ *CORE::GLOBAL::warn = sub {
                my ($package, $filename, $line, $subroutine) = caller;
                untie *STDERR;
                my $message;
                foreach my $arg (@_) {
                        $message = $message.$arg;
                }
                print STDERR $message;
                tie *STDERR, __PACKAGE__, (*STDERR);
                logmessage("warn",$message,$filename, $line);
                return;
        }
}

Теперь есть способ, которым я могу переопределить croak cluck confess carp от carp модуль в Perl?

1 ответ

Решение

Функции, предоставляемые Carp, являются обычными функциями, которые импортируются в ваши пакеты через Exporter, когда модуль use д. Хитрость заключается в том, чтобы перезаписать их как можно раньше внутри Carp пространство имен, прежде чем кто-либо сможет их импортировать. Затем, когда они это сделают, они получат перезаписанные.

В вашем скрипте или в самом верху вашего собственного модуля логирования:

BEGIN {
    require Carp;

    # save original croak (will create closure ...)
    my $original_croak = \&Carp::croak;

    no warnings 'redefine';
    *Carp::croak = sub { 
        print "Croaking...\n"
          or $original_croak->("cannot fake croak"); # (... here)
    };
}

Вам нужно загрузить Carp один раз, чтобы Perl проанализировал код и установил функции в Carp Пространство имен. Тогда вы можете перезаписать их.

Позже, в каком-то другом модуле в вашем коде:

use Carp 'croak';

croak 'foo';

Это теперь произведет вывод, который мы установили выше.

Если вы хотите назвать оригинал Carp::croak внутри нового сохраните его в coderef и сохраните его, как показано в примере выше.

Обратите внимание, что это работает, только если замена происходит очень рано. Если вы поместите это в свой собственный модуль регистрации, и он будет загружен после загрузки Carp, это не удастся.

package Foo;
use Carp;
use Your::Logging::Framework;

croak 'foo';

Не будет работать, потому что в точке, где вы перезаписать Carp::croak, Foo::croak это уже копия оригинала Carp::croak,

Если вы хотите сделать эту работу, вы всегда можете импортировать свой собственный carp, croak и так далее для вызывающего абонента также. Это бросит кучу предупреждений или пожаловаться под strict, но это должно работать.

Другие вопросы по тегам