Ho bisogno di rimuovere un metodo dalla tabella dei simboli Perl in fase di esecuzione. Ho provato a farlo usando undef &Square::area
, che elimina la funzione, ma lascia alcune tracce dietro. In particolare, quando viene chiamato $square->area()
, Perl si lamenta che "Non è un riferimento CODE" anziché "Subroutine non definita & Square :: area called", che è ciò che mi aspetto.Perché questo Perl produce "Non un riferimento CODICE?"
Si potrebbe chiedere "Perché è importante? Hai eliminato la funzione, perché la chiameresti?" La risposta è che non lo sto chiamando, Perl lo è. Square eredita da Rectangle e voglio che la catena di ereditarietà passi $square->area
a &Rectangle::area
, ma invece di saltare Square dove il metodo non esiste e quindi rientra nell'area di Rectangle(), la chiamata al metodo muore con "Not a CODE reference ".
Stranamente, questo sembra accadere solo quando & Square :: area è stata definita dall'assegnazione typeglob (ad esempio *area = sub {...}
). Se la funzione viene definita utilizzando l'approccio standard sub area {}
, il codice funziona come previsto.
Anche interessante, non definendo l'intero glob funziona come previsto. Non solo indefinendo la subroutine stessa.
Ecco un breve esempio che illustra il sintomo, e contrasta con il corretto comportamento:
#!/usr/bin/env perl
use strict;
use warnings;
# This generates "Not a CODE reference". Why?
sub howdy; *howdy = sub { "Howdy!\n" };
undef &howdy;
eval { howdy };
print [email protected];
# Undefined subroutine &main::hi called (as expected)
sub hi { "Hi!\n" }
undef &hi;
eval { hi };
print [email protected];
# Undefined subroutine &main::hello called (as expected)
sub hello; *hello = sub { "Hello!\n" };
undef *hello;
eval { hello };
print [email protected];
Aggiornamento: allora ho risolto questo problema utilizzando Package :: Stash (grazie @Ether), ma sono Sono ancora confuso dal motivo per cui sta accadendo in primo luogo. perldoc perlmod
dice:
package main;
sub Some_package::foo { ... } # &foo defined in Some_package
Questa è solo una scorciatoia per un incarico typeglob in fase di compilazione:
BEGIN { *Some_package::foo = sub { ... } }
ma sembra che esso isn' t solo stenografia, perché i due causano un comportamento diverso dopo aver indefinito la funzione. Sarei grato se qualcuno potesse dirmi se si tratta di (1) documenti errati, (2) bug in perl o (3) PEBCAK.
Dove hai avuto l'idea che 'undef & Square :: area' avrebbe eliminato una subroutine? Non un attacco, solo curioso ... – Ether
Da 'perldoc -f undef'. L'esempio che danno è 'undef &mysub;', ma funziona anche con nomi qualificati. – KingPong
Alternate domande "potreste chiedere". Perché hai definito & Square :: area in primo luogo? Perché non [re] definisci & Square :: area da delegare alla sua superclasse? –