Tengo un código que llama a la función. Pero no sé el módulo al que pertenece esta función. Necesito que modifique esta función.En Perl, ¿cómo puedo verificar desde qué módulo se importó una función determinada?
¿Cómo puedo comprobarlo?
Tengo un código que llama a la función. Pero no sé el módulo al que pertenece esta función. Necesito que modifique esta función.En Perl, ¿cómo puedo verificar desde qué módulo se importó una función determinada?
¿Cómo puedo comprobarlo?
Si la función se importan automáticamente desde otro módulo usando Exporter
, que se pueden encontrar en @EXPORT
variable global de este módulo:
perl -MEncode -e 'print join "\n", @Encode::EXPORT'
decode
decode_utf8
...
le puede proporcionar una lista de funciones a use
. De esta manera usted siempre sabrá qué paquete pertenece a una función:
use Encode qw[ encode ]; # encode() imported from the Encode module
use Data::Dumper qw[]; # no functions imported from Data::Dumper
El módulo Devel::Peek
es muy útil para obtener todo tipo de información acerca de las variables. Una de las cosas que puede hacer con él es volcar una referencia a una subrutina y obtener el nombre de la glob vino:
$ perl -MDevel::Peek -MList::Util=first -e'Dump(\&first)'
SV = IV(0x1094e20) at 0x1094e28
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x11183b0
SV = PVCV(0x10ff1f0) at 0x11183b0
REFCNT = 3
FLAGS = (POK,pPOK)
PROTOTYPE = "&@"
COMP_STASH = 0x0
XSUB = 0x7f7ecbdc61b0
XSUBANY = 0
GVGV::GV = 0x11183c8 "List::Util" :: "first"
FILE = "ListUtil.c"
DEPTH = 0
FLAGS = 0x800
OUTSIDE_SEQ = 0
PADLIST = 0x0
OUTSIDE = 0x0 (null)
la parte GVGV::GV
allí es la parte importante.
Una solución alternativa sería Sub::Identify
, que realmente solo le da nombres para las referencias de código que le entrega. Sin embargo, saber acerca de Devel::Peek
es útil en muchas otras situaciones también, así que lo mencioné primero.
Esto es mucho mejor de lo que hubiera hecho. Me habría agregado en '()' después de cada módulo que se utiliza hasta que el código no se pudo compilar. –
El depurador de Perl puede buscar el camino que desee. Por ejemplo:
main::(-e:1): 0 DB<1> sub foo {} DB<2> x \&foo 0 CODE(0xca6898) -> &main::foo in (eval 5)[/usr/share/perl/5.10/perl5db.pl:638]:2-2
Para ello, utiliza Devel::Peek:
=head2 C<CvGV_name_or_bust> I<coderef>
Calls L<Devel::Peek> to try to find the glob the ref lives in; returns
C<undef> if L<Devel::Peek> can't be loaded, or if C<Devel::Peek::CvGV> can't
find a glob for this ref.
Returns C<< I<package>::I<glob name> >> if the code ref is found in a glob.
=cut
sub CvGV_name_or_bust {
my $in = shift;
return unless ref $in;
$in = \&$in; # Hard reference...
eval { require Devel::Peek; 1 } or return;
my $gv = Devel::Peek::CvGV($in) or return;
*$gv{PACKAGE} . '::' . *$gv{NAME};
} ## end sub CvGV_name_or_bust
que te pueden ejercer con
#! /usr/bin/perl
use warnings;
use strict;
package Foo;
sub bar {}
package main;
BEGIN { *baz = \&Foo::bar }
sub CvGV_name_or_bust { ... }
print CvGV_name_or_bust(\&baz), "\n";
Salida:
Foo::bar
Tenga en cuenta que el ejemplo anterior es Foo:bar
tiene un nombre diferente, pero obtiene tanto el paquete donde reside el submarino con alias y también su nombre allí.
se puede pasar a Sub::Identify::sub_fullname
cualquier referencia subrutina y se le mostrará el módulo en el que se definió este sub:
use Sub::Identify qw/sub_fullname/;
sub foo {
print sub_fullname(\&foo); # main::foo
print sub_fullname(sub{}); # main::__ANON__
}
foo();
Para más detalles ver Sub::Identify
Cuál es el problema que intenta resolver conociendo esto? Puede haber una manera de arreglar eso antes de que suceda. :) –
Las funciones de modificación de otras clases pueden ser comunes en Ruby, pero es una obra de arte negra en Perl que debe reservarse para situaciones * extremadamente * raras. ¿Por qué necesitas hacer esto? – Ether
@ 'brian d foy' Tres años más tarde intento escribir una prueba unitaria para confirmar que obtengo correctamente una versión de Perl pura de una función bajo una condición, o una versión XS bajo otra condición diferente, y de repente tengo lo que siento es un caso de uso legítimo para la pregunta de este OP. ;) – DavidO