2009-11-04 11 views
14

Wiem, co robią wszyscy, ale nigdy nie znalazłem się w sytuacji, w której potrzebowałem któregokolwiek z nich. Używałem wielu bloków BEGIN i od czasu do czasu używam END. BEGIN jest szczególnie przydatny, gdy trzeba zmodyfikować środowisko przed uruchomieniem kodu, a w niektórych sytuacjach debugowania użyłem END, aby przechwycić ważne informacje o stanie dla trudnych do wykrycia śmiertelnych błędów.Jaka jest przydatność bloków CHECK, UNITCHECK i INIT w Perlu?

Czy kiedykolwiek używałeś CHECK, UNITCHECK lub INIT? Jeśli tak, po co? A czy blok z BEGIN nie był wystarczający z jakiegoś powodu?

Dokumentacja bloków znajduje się pod numerem PerlDoc.

Odpowiedz

5

Posiadałem funkcję paczki import, która wykonałaby ciężką pracę, a następnie wykonałaby połączenie eval. Jak debugujesz coś takiego? Funkcja importu zostanie uruchomiona, gdy use moduł, który ma miejsce w czasie kompilacji (tak, jakby był wewnątrz bloku BEGIN). Z jakiegoś powodu (myślę, że to dlatego, że musiałem przekazać parametry do import z notacją heredoc, ale mogło to być coś innego), nie było wystarczająco dobre, aby powiedzieć require Module; Module->import(@args).

Tak więc moim obejściem było zbudowanie ciągu znaków dla eval w import i zapisanie innej zmiennej. Następnie uruchomiłem blok eval w bloku INIT. Po uruchomieniu debugera pierwszy punkt wykonawczy znajdował się na początku bloku INIT i mogłem użyć debuggera do przejrzenia instrukcji eval.

+0

Teraz pamiętam, dlaczego nie chciałem "wymagać modułu, modułu-> import (@stuff)". To dlatego, że miałem już zestaw skryptów testowych, które chciałem móc debugować, i nie chciałem edytować instrukcji 'use Module' w każdym pliku. – mob

+9

Nie trzeba przechodzić przez te wygłuszenia, aby debugować kod kompilacji. Wystarczy umieścić $ DB :: single = 1 w dowolnym miejscu źródła, a debugger zatrzyma się w tym momencie, bez względu na to, w której fazie przetwarzania znajduje się program. (Patrz http://perldoc.perl.org/perldebug.html#Debugging -compile-time-statement) –

+0

Dzięki Brian! Dobrze wiedzieć. – mob

7

Interesującym zastosowaniem bloków CHECK jest "Advanced Perl programming" autorstwa Simona Cozensa (O'Reilly) w rozdziale 1, w sekcji "Robienie rzeczy później z CHECK". Pokazuje, jak zaimplementować "ostateczny" atrybut podobny do java.

Również, Devel :: Sub :: Trace używa bloków INIT do wstawiania śladów (ta informacja pochodzi z POD dla Devel :: Hook, który jest modułem używanym do pracy z te nazwane bloki)

+0

Ponadto, nigdy tego nie próbowałem, ale te * mogą * można wiarygodnie wykorzystać na kilka interesujących, szyderczych podejść - jeśli ktoś ma pomysł, nie wahaj się rozszerzyć tej możliwości jako oddzielnej odpowiedzi. – DVK

3

Cóż BEGIN bloki są uruchamiane w czasie kompilacji, jak wiadomo. Zachowuję więc kod, który należy uruchomić, aby mój moduł mógł zostać zaimportowany.

Napisałem opakowanie skryptu, aby zrobić wszystko, co było robione w kodzie, który pojawił się w kilkuset skryptach.

  • Było rzeczy, które musiałem zrobić, aby odczyt modułu był use -d. Że uruchomiłem w blokach BEGIN sub i import sub.
  • Ale był też cały zestaw, który zainicjował usługi, których użyłby skrypt. Dlatego uruchomiłem te działania w blokach INIT.
  • Uruchomiono niezbędne kody czyszczenia i zakończenia w blokach END.

Myślę, że kontrola jest sensowna, jeśli piszemy moduły z silnikami XS, ale użyłem jej tylko kilka razy. Pewnego razu myślę, że to było sprawdzić sugestie w Intermediate Perl. I nie mogę sobie bez przeszkód pamiętać o innych przyczynach.

Ale używam bloków INIT, gdy czuję, że kod jest częścią skryptu, niż konfigurowanie modułu. Zasadniczo robię tylko to, co jest konieczne podczas kompilacji.

+0

Axeman - czy mógłbyś wyjaśnić, jakie były twoje użytki, w których blok INIT zapewniał coś specjalnego, czego nie można osiągnąć, umieszczając kod init na początku zwykłego programu? Czy chodzi tylko o wizualizację/łatwość konserwacji? – DVK

+1

@DVK: Użyłem bloków INIT w modułach do przeprowadzenia inicjalizacji klasy; użytkownik nie powinien wiedzieć o takich rzeczach. Niestety PAR :: Packer ma problemy z zaplanowanymi blokami (w szczególności INIT i CHECK), więc nie działa to w przypadku modułów, które mogą być dystrybuowane w ten sposób. Zwykle kończę wyrzucanie bloku INIT na rzecz 'initialize()' sub, która jest wywoływana przy pierwszym wywołaniu konstruktora. –

+0

Bloki CHECK nie mają nic wspólnego z modułami XS. – rurban

1

perlmod wyjaśnia te specjalne bloki, ale rzeczywiście tylko BEGIN i END są powszechnie używane. Są to tylko tablice CV, LIFO lub FIFO. Te bloki pozwalają na oddzielne taktowanie po uruchomieniu kodu, niezależnie od lokalizacji w pliku źródłowym. Możesz więc zachować sekcje kodu razem, ale są one wykonywane o różnych porach (PHASES).

KONTROLA dodano początkowo do uruchomienia pakietu kompilatora O (-MO=C...) w ustalonej kolejności po inicjalizacji modułu (pakiet użytku), a przed głównym programem, aby móc przechowywać kontekst wykonanie tam. Oddziela to czas kompilacji (przed) od czasu wykonywania (po). perl -c zatrzymuje się po SPRAWDŹ.

Ponieważ jestem opiekunem kompilatorów, używam CHECK i -MO = szeroko. Moje moduły compile() są wywoływane przez O w bloku CHECK. Z Od (debugowania O) Wywołuję metodę compile nie w CHECK, ale później w INIT, więc debugger wkracza w to. Debugger nie wkracza do bloków CHECK domyślnie, należy go wymusić za pomocą $DB::single=1 lub użyć Od.

UNITCHECK został dodany później do kompilacji i ładowania modułów drobnoziarnistych, zwł. Pliki .pmc.

Nigdy dotąd tego nie używałem. Może się również zdarzyć w czasie wykonywania, więc mogę go użyć do sprawdzenia typów modułów ładowanych podczas pracy.

INIT został dodany, aby umożliwić oddzielną inicjalizację klasy.

Ja rzadko używam tego, ale jest to przydatne.

+0

Najwyraźniej przegapiłeś: "Czy kiedykolwiek użyłeś CHECK, UNITCHECK lub INIT? Jeśli tak, to po co? A blok BEGIN nie byłby wystarczający z jakiegoś powodu?" Takie cienkie wyjaśnienie, OP może osiągnąć wszędzie. – Axeman

Powiązane problemy