# Phasers: `BEGIN`, `UNITCHECK`, `CHECK`, `INIT`, `END` Πέντε ειδικά ονομασμένα μπλοκ επιτρέπουν στον κώδικα να συνδεθεί με τις μεταβάσεις που κάνει ένα πρόγραμμα ανάμεσα στο να μεταγλωττίζεται και στο να εκτελείται. Μοιάζουν με υπορουτίνες αλλά δεν είναι: μπορείτε να γράψετε πολλά από το καθένα, κανένα δεν έχει καλέσιμο όνομα, και το καθένα πυροδοτείται αυτόματα στη δική του στιγμή. ```perl BEGIN { ... } # during compilation, as soon as defined UNITCHECK { ... } # right after this compilation unit is compiled CHECK { ... } # after the whole program is compiled INIT { ... } # just before the runtime begins END { ... } # just before the interpreter exits ``` Το πρόθεμα `sub` (`sub BEGIN { ... }`) γίνεται αποδεκτό αλλά δεν προσθέτει τίποτα και αποθαρρύνεται. Αυτά είναι μπλοκ, όχι ονομασμένες υπορουτίνες· δεν μπορείτε να τα καλέσετε, μόνο να τα αφήσετε να πυροδοτηθούν. ## Πότε εκτελείται το καθένα Ένα πρόγραμμα Perl ζει σε δύο φάσεις: μια **φάση μεταγλώττισης** που αναλύει τον πηγαίο κώδικα σε μια εσωτερική μορφή, και μια **φάση εκτέλεσης** που τον εκτελεί. Οι phasers σημαδεύουν το όριο. - Το `BEGIN` εκτελείται τη στιγμή που αναλύεται η αγκύλη κλεισίματός του, προτού καν διαβαστεί το υπόλοιπο του αρχείου. Έτσι λειτουργεί η [`use`](../perlfunc/use.md): ένα `use` είναι μια [`require`](../perlfunc/require.md) τυλιγμένη σε `BEGIN` συν [`import`](../perlfunc/import.md), οπότε τα εισαγόμενα ονόματα υπάρχουν για τον κώδικα που ακολουθεί. Μόλις εκτελεστεί ένα `BEGIN`, γίνεται απροσδιόριστο και η μνήμη του ανακτάται. - Το `UNITCHECK` εκτελείται μόλις η **μονάδα μεταγλώττισης** που το περιέχει ολοκληρώσει τη μεταγλώττισή της. Μια μονάδα είναι το κύριο πρόγραμμα, ένα άρθρωμα που φορτώνεται με [`require`](../perlfunc/require.md), ένα string [`eval`](../perlfunc/eval.md), ένα [`do`](../perlfunc/do.md) FILE, ή κώδικας που μεταγλωττίζεται από την κατασκευή regex `(?{ })`. Επειδή οι μονάδες ολοκληρώνουν τη μεταγλώττισή τους σε διαφορετικές στιγμές, το `UNITCHECK` είναι ο μόνος phaser του οποίου ο χρονισμός παρακολουθεί το μεμονωμένο αρχείο και όχι το πρόγραμμα ως σύνολο. - Το `CHECK` εκτελείται μία φορά, αφού τελειώσει η **αρχική** φάση μεταγλώττισης ολόκληρου του προγράμματος και πριν ξεκινήσει η φάση εκτέλεσης. - Το `INIT` εκτελείται μία φορά, λίγο πριν αρχίσει η φάση εκτέλεσης, μετά από όλα τα μπλοκ `CHECK`. - Το `END` εκτελείται μία φορά, όσο πιο αργά γίνεται: αφού έχει τελειώσει το πρόγραμμα (συμπεριλαμβανομένου του μετά από μια [`die`](../perlfunc/die.md)), λίγο πριν εξέλθει ο διερμηνευτής. Τα `BEGIN` και `UNITCHECK` είναι δεμένα με την *ανάλυση*, όχι με τη φάση του διερμηνευτή, οπότε μπορούν να πυροδοτηθούν κατά τη διάρκεια οποιασδήποτε φάσης: ένα string `eval` κατά τον χρόνο εκτέλεσης εξακολουθεί να μεταγλωττίζει το σώμα του, και κάθε `BEGIN` ή `UNITCHECK` μέσα του εκτελείται εκεί και τότε. Τα `CHECK` και `INIT`, αντιθέτως, σημαδεύουν το εφάπαξ όριο μεταγλώττισης/εκτέλεσης του κύριου προγράμματος. ## Πολλαπλότητα και σειρά εκτέλεσης Μπορείτε να γράψετε οποιονδήποτε αριθμό από το κάθε μπλοκ. Όλα εκτελούνται, με καθορισμένη σειρά: - `BEGIN`: first in, first out (FIFO) όπως συναντώνται κατά τη μεταγλώττιση. Το πρώτο `BEGIN` στη σειρά του πηγαίου κώδικα εκτελείται πρώτο. - `UNITCHECK`: last in, first out (LIFO) μέσα σε κάθε μονάδα, αφού μεταγλωττιστεί αυτή η μονάδα. - `CHECK`: LIFO, μετά από όλη τη μεταγλώττιση. - `INIT`: FIFO, λίγο πριν τον χρόνο εκτέλεσης. - `END`: LIFO κατά την έξοδο. Το τελευταίο `END` που ορίζεται είναι το πρώτο που εκτελείται. Η διδακτική περίπτωση είναι ένα αρχείο που αναμειγνύει συνηθισμένες εντολές με τα και τα πέντε είδη μπλοκ. Τα μπλοκ δεν εκτελούνται εκεί όπου είναι γραμμένα· εκτελούνται στη φάση τους, με τη σειρά τους ανά φάση, ενώ οι συνηθισμένες εντολές εκτελούνται ενδιάμεσα κατά τον χρόνο εκτέλεσης. Εννοιολογικά, για ένα μεμονωμένο αρχείο: ```default 1. BEGIN blocks -- FIFO, during compilation 2. UNITCHECK blocks -- LIFO, after this unit compiles 3. CHECK blocks -- LIFO, after all compilation 4. INIT blocks -- FIFO, just before runtime 5. ordinary code -- run phase, in source order 6. END blocks -- LIFO, at exit ``` Έτσι τα `BEGIN` και `UNITCHECK` εκτελούνται πριν από οποιοδήποτε `CHECK`· το `CHECK` εκτελείται πριν το `INIT`· το `INIT` εκτελείται πριν την πρώτη γραμμή συνηθισμένου κώδικα· και κάθε `END` εκτελείται μετά την τελευταία. Μέσα στα `BEGIN` και `INIT`, τα νωρίτερα γραμμένα μπλοκ εκτελούνται νωρίτερα· μέσα στα `UNITCHECK`, `CHECK` και `END`, τα αργότερα γραμμένα μπλοκ εκτελούνται νωρίτερα. ## Τα μπλοκ `END` αναλυτικά Το `END` είναι ο phaser καθαρισμού. Εκτελείται με LIFO ώστε η αποδόμηση να ξετυλίγεται με την αντίστροφη σειρά της εγκατάστασης, όπως το περιμένουν οι εμφωλευμένοι πόροι. Μέσα σε ένα μπλοκ `END`, το [`$?`](../perlvar/error.md) κρατά την τιμή που το πρόγραμμα πρόκειται να περάσει στην [`exit`](../perlfunc/exit.md). Μπορείτε να το διαβάσετε για να μάθετε πώς τελειώνει το πρόγραμμα, και μπορείτε να του αναθέσετε τιμή για να αλλάξετε τον κωδικό εξόδου: ```perl END { $? = 0 if $? == 42; # rewrite one exit code on the way out } ``` Προσέξτε μην αλλοιώσετε το `$?` κατά λάθος. Η εκτέλεση οτιδήποτε μέσω της [`system`](../perlfunc/system.md) μέσα σε ένα μπλοκ `END` αντικαθιστά το `$?` με την κατάσταση του παιδιού, που στη συνέχεια γίνεται ο κωδικός εξόδου του προγράμματος εκτός αν το αποθηκεύσετε και το επαναφέρετε. Τα μπλοκ `END` **δεν** εκτελούνται σε αρκετές περιπτώσεις: - Υπό τον διακόπτη `-c` (έλεγχος σύνταξης μόνο μεταγλώττισης). Ο κύριος κώδικας δεν εκτελείται, ούτε και τα μπλοκ `END`. - Όταν η μεταγλώττιση αποτυγχάνει. Ένα πρόγραμμα που δεν μεταγλωττίζεται δεν φτάνει ποτέ στο σημείο όπου θα πυροδοτούνταν τα μπλοκ `END`. - Όταν η διεργασία αντικαθιστά τον εαυτό της με [`exec`](../perlfunc/exec.md). Η εικόνα έχει χαθεί· δεν απομένει τίποτα για να εκτελέσει το μπλοκ. - Όταν η διεργασία τερματίζεται από ένα μοιραίο σήμα που δεν παγιδεύετε. Πιάστε το σήμα μόνοι σας (μέσω [`%SIG`](../perlvar/signals.md)) αν χρειάζεται να εκτελεστεί ο καθαρισμός. Ένα μπλοκ `END` που δημιουργείται μέσα σε ένα string [`eval`](../perlfunc/eval.md) **δεν** εκτελείται όταν τελειώνει αυτό το `eval`. Καταχωρείται όπως κάθε άλλο μπλοκ `END` του πακέτου του και εκτελείται με σειρά LIFO λίγο πριν εξέλθει ο διερμηνευτής. ## Το `${^GLOBAL_PHASE}` και οι φάσεις Η μεταβλητή μόνο για ανάγνωση [`${^GLOBAL_PHASE}`](../perlvar/interpreter.md) ονομάζει την τρέχουσα φάση του διερμηνευτή. Οι τιμές της επιτρέπουν σε κώδικα που εκτελείται σε περισσότερες από μία φάσεις να βρει πού βρίσκεται. Κατά τη διάρκεια ενός μπλοκ `CHECK` διαβάζεται `CHECK`· κατά το `INIT`, `INIT`· κατά τον συνηθισμένο κώδικα χρόνου εκτέλεσης, `RUN`· κατά τη διάρκεια ενός μπλοκ `END`, `END`. Δείτε το [`${^GLOBAL_PHASE}`](../perlvar/interpreter.md) για την πλήρη λίστα τιμών και τη χρονογραμμή των φάσεων. ## Μπλοκ `defer` Ένα μπλοκ [`defer`](../perlfunc/defer.md) είναι ο μικρής κλίμακας ξάδελφος του `END`. Εκτελείται όταν εξέρχεται η περικλείουσα **εμβέλεια μπλοκ**, για οποιονδήποτε λόγο, αντί όταν εξέρχεται ολόκληρο το πρόγραμμα. Καταφύγετε στο `defer` για να ζευγαρώσετε την απόκτηση με την αποδέσμευση μέσα σε μια υπορουτίνα ή βρόχο· καταφύγετε στο `END` για αποδόμηση σε επίπεδο διεργασίας που πρέπει να γίνει μία φορά, στο τέλος τέλος. ## Δείτε επίσης - [`BEGIN` και `use`](../perlfunc/use.md) - το `use` είναι μια φόρτωση-και-εισαγωγή τυλιγμένη σε `BEGIN`· ο πιο συνηθισμένος λόγος για να ενδιαφέρεστε για τον χρονισμό της φάσης μεταγλώττισης. - [`${^GLOBAL_PHASE}`](../perlvar/interpreter.md) - διαβάστε την τρέχουσα φάση από μέσα σε οποιοδήποτε μπλοκ για να μάθετε πού βρίσκεστε. - [`defer`](../perlfunc/defer.md) - καθαρισμός με εμβέλεια μπλοκ, το σωστό εργαλείο όταν η εμβέλεια του `END` σε όλο το πρόγραμμα είναι υπερβολικά ευρεία. - [`$?`](../perlvar/error.md) - η κατάσταση εξόδου που ένα μπλοκ `END` μπορεί να διαβάσει και να ξαναγράψει. - [`%SIG`](../perlvar/signals.md) - παγιδεύστε τα σήματα που διαφορετικά θα παρέκαμπταν εντελώς τα μπλοκ `END`. - [`exit`](../perlfunc/exit.md) - αυτό λίγο πριν το οποίο εκτελούνται τα μπλοκ `END`· η τιμή που φέρει είναι το `$?` που βλέπει ένα μπλοκ `END`.