2010-10-15 18 views
11

Poniżej znajduje się sesja debugowania w Perlu 5.12. Czy to ma jakiś sens? Czy UNIVERSAL buforuje wersję zmiennej @ISA, która jeśli na zawsze używa później. Wcześniej przed Class::ISA został przestarzały, kiedyś zadzwonić pod numer Class::ISA::self_and_super_path, aby uzyskać wnętrze do przeoczenia w tablicy @ISA. Ponieważ jest to teraz uważane za niepotrzebne, jak uzyskać perl, aby kontrolować jego wewnętrzne rekordy?Czy jest jakiś problem w perlu 5.12.2 przy użyciu splice na @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' 

To jest kod testowy (oczywiście). Otrzymuje takie same wyniki, działa na płasko, uruchamia się jako test lub uruchamia debugowanie. Powinienem powiedzieć, że przed tym @ISA = qw<Babushka> i wykonywane

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

Czy to problem? Powinieneś tylko push na @ISA?

Odpowiedz

14

Zamiennikiem dla Class::ISA::self_and_super_path jest mro::get_linear_isa. Jest to dostępne zarówno z poziomu mro, jak i, jeśli chcesz wspierać stare perły, przez MRO::Compat.

Również, @ISA jest zmienną magiczną.

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

Uwaga na PERL_MAGIC_isa. To właśnie napędza ten konkretny mechanizm.

Po każdej zmianie zawartość wszelkich pamięci podręcznych zależnych od jego wartości powinna zostać zaktualizowana.

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

Widocznie znalazłeś przypadek, gdy unieważnienie cache nie dzieje. Uważam to za błąd. Szanse są splice, z jakiegoś powodu, nie powołują się poprawnie na magię isa. Możesz spróbować zmodyfikować @ISA w inny sposób, na przykład używając unshift lub przydziału, lub ewentualnie wypróbować mro::method_changed_in, co unieważni pamięci podręczne rozdzielczości metod, które są powiązane z różnymi sami @ISA.

Jeśli mógłbyś zredukować ten błąd do minimalnej wersji testowej, byłby bardzo pomocny w naprawieniu tego błędu.

Aktualizacja:

Minimalny testcase okazało się proste:

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

Jest to spowodowane pp_splice nie robi coś podobnego mg_set((SV *)ary). push, unshift, a regularne przypisania robią to poprawnie, więc użycie jednego z nich powinno rozwiązać problem.

Kolejna aktualizacja:

This change, który po prostu zaangażowana w Perl, rozwiązuje ten problem. Jednak, ponieważ dziwne zachowanie się niezwiązane z magią jest już obecne w 5.8 i 5. 10, nie jest to regresja, a zatem nie będzie częścią 5.12.3 w ciągu kilku miesięcy. 5.13.6, które ukaże się w przyszłym tygodniu, a 5.14.0, następne północne źródło, prawdopodobnie będzie je mieć.

+0

Łatka na zwycięstwo! Dzięki. – Axeman

+1

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

+0

Dzięki za poprawkę rafl !! – Ether

4

Tak, istnieje pamięć podręczna. Ale jeśli możesz zmodyfikować @ISA bez unieważniania tej pamięci podręcznej, uważam to za błąd w perlu.

Czy problem zniknie po dodaniu linii @ISA = @ISA; po linii splice?

+0

Zdecydowanie spróbuję '@ ISA = @ ISA'. Chyba że będzie bardziej podobny do '@ $ isa_ref = @ $ isa_ref'. Gdzie '$ isa_ref = * Papushka :: ISA {ARRAY}'. – Axeman