2010-10-15 14 views
11

La siguiente es una sesión de depuración en Perl 5.12. ¿Tiene esto algún sentido? ¿UNIVERSAL almacena en caché una versión de la variable @ISA, que si se usa para siempre thereafer? Antes de que Class::ISA estuviera en desuso, solía llamar al Class::ISA::self_and_super_path para obtener las partes internas para que revisaran la matriz @ISA. Dado que ahora se considera innecesario, ¿cómo se obtiene Perl para auditar sus registros internos?¿Hay algún problema en Perl 5.12.2 usando empalme en @ISA?

DB<34> p $papa 
Papushka=HASH(0x16bc0300) 

DB<35> p $papa->isa('Nanushka') 

DB<36> p $papa->isa('Babushka') 
1 

DB<37> x @Papushka::ISA 
0 'Nanushka' 
1 'Babushka' 

Código de prueba (obviamente). Está obteniendo los mismos resultados, se ejecuta sin problemas, se ejecuta como prueba o se ejecuta en depuración. Debo decir que antes de esta @ISA = qw<Babushka> y realizado

splice(@ISA, 0, 0, 'Nanushka'); 

es que el problema? ¿Solo debe push en @ISA?

Respuesta

14

La sustitución de Class::ISA::self_and_super_path es mro::get_linear_isa. Está disponible en el propio mro o, si desea admitir perls antiguos, a través del MRO::Compat.

Además, @ISA es una variable mágica.

$ perl -MDevel::Peek -e'Dump \@ISA' 
SV = IV(0x1b92e20) at 0x1b92e28 
    REFCNT = 1 
    FLAGS = (TEMP,ROK) 
    RV = 0x1bbcd58 
    SV = PVAV(0x1b93cf8) at 0x1bbcd58 
    REFCNT = 2 
    FLAGS = (SMG,RMG) 
    MAGIC = 0x1bc0f68 
     MG_VIRTUAL = &PL_vtbl_isa 
     MG_TYPE = PERL_MAGIC_isa(I) 
     MG_OBJ = 0x1bbcd40 
    ARRAY = 0x0 
    FILL = -1 
    MAX = -1 
    ARYLEN = 0x0 
    FLAGS = (REAL) 

Tenga en cuenta que PERL_MAGIC_isa. Eso es lo que impulsa este mecanismo en particular.

Cada vez que se cambia, se supone que el contenido de las cachés que dependen de su valor se debe actualizar.

$ perl -E'say Foo->isa(q[Bar]) || 0; @Foo::ISA = qw(Bar Baz); say Foo->isa(q[Bar]) || 0' 
0 
1 

Al parecer, usted ha encontrado un caso en el que la invalidación de caché no sucede. Considero esto un error. Las posibilidades son splice, por alguna razón, no invoca la magia isa apropiadamente. Puede intentar modificar @ISA de forma alternativa, por ejemplo usando unshift o una asignación, o posiblemente intente con mro::method_changed_in, lo que invalidaría las cachés de resolución del método, que están asociadas a las diversas @ISA s.

Si pudieras reducir este error a un caso de prueba mínimo, eso sería de gran ayuda para solucionar este error.

Actualización:

Un caso de prueba mínima resultó ser fácil:

$ perl -E'say Foo->isa(q[Bar]) || 0; splice @Foo::ISA, 0, 0, q[Bar]; say Foo->isa(q[Bar]) || 0' 
0 
0 

Esto es causado por pp_splice no hacer algo como mg_set((SV *)ary). push, unshift, y las asignaciones regulares lo hacen correctamente, por lo que usar uno de estos debería solucionar su problema.

Otro Actualización:

This change, que Acabo de enviar a perl, corrige el problema. Sin embargo, como el comportamiento extraño de splice que no invoca magia ya está presente en 5.8 y 5.10, no es una regresión y, por lo tanto, no va a ser parte de 5.12.3 en unos pocos meses. 5.13.6, que se lanzará la próxima semana, y 5.14.0, próxima primavera del norte, probablemente lo tendrá.

+0

¡Un parche para la victoria! Gracias. – Axeman

+1

@Ether: http://rt.perl.org/rt3/Public/Bug/Display.html?id=78400 – Axeman

+0

Gracias por el parche rafl !! – Ether

4

Sí, hay un caché. Pero si puede modificar @ISA sin invalidar ese caché, lo consideraría un error en Perl.

¿Desaparece su problema si agrega la línea @ISA = @ISA; después de su línea splice?

+0

Definitivamente probará '@ ISA = @ ISA'. Excepto que será más como '@ $ isa_ref = @ $ isa_ref'. Donde '$ isa_ref = * Papushka :: ISA {ARRAY}'. – Axeman

Cuestiones relacionadas