caller#
Επιστρέφει πληροφορίες σχετικά με την υπορουτίνα, την eval ή την require που κάλεσε τον κώδικα που εκτελείται αυτή τη στιγμή.
Η caller διατρέχει τη στοίβα κλήσεων. Χωρίς όρισμα επιστρέφει μια σύντομη εγγραφή τριών στοιχείων που προσδιορίζει ποιος μας κάλεσε. Με ένα αριθμητικό όρισμα EXPR διατρέχει EXPR πλαίσια πιο πίσω και επιστρέφει μια εκτενέστερη εγγραφή έντεκα στοιχείων - τη μορφή που χρησιμοποιούν ο debugger, τα αρθρώματα ιχνηλάτησης στοίβας, καθώς και ο μηχανισμός των warn/die για να εμπλουτίζουν τα διαγνωστικά μηνύματα με πληροφορίες αρχείου και γραμμής. Τα πλαίσια XS είναι αόρατα στην caller· στη θέση τους εμφανίζεται το επόμενο πλαίσιο καθαρής Perl.
Σύνοψη#
caller
caller EXPR
Τι επιστρέφεται#
Σε βαθμωτό περιβάλλον, το όνομα του πακέτου του καλούντος, ή undef αν δεν υπάρχει καλών (δηλαδή βρισκόμαστε στο ανώτατο επίπεδο του αρχείου, εκτός από sub, eval ή require):
my $pkg = caller;
Σε περιβάλλον λίστας χωρίς όρισμα, τρία στοιχεία - το πακέτο, το αρχείο και ο αριθμός γραμμής του άμεσου καλούντος:
# 0 1 2
my ($package, $filename, $line) = caller;
Σε περιβάλλον λίστας με αριθμητικό όρισμα, έντεκα στοιχεία που περιγράφουν το πλαίσιο EXPR επίπεδα ψηλότερα. Το 0 είναι ο άμεσος καλών, το 1 είναι ο δικός του καλών, και ούτω καθεξής:
# 0 1 2 3 4
my ($package, $filename, $line, $subroutine, $hasargs,
# 5 6 7 8 9 10
$wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
= caller($i);
Τα έντεκα πεδία, με τη σειρά:
$package,$filename,$line- η τοποθεσία του σημείου κλήσης μέσα στον καλούντα εκείνου του πλαισίου. Οι ίδιες τρεις τιμές που επιστρέφει η σύντομη μορφή.$subroutine- το πλήρως προσδιορισμένο όνομα της υπορουτίνας στην οποία ανήκει το πλαίσιο, π.χ."Foo::bar". Για ένα πλαίσιοevalείναι η κυριολεκτική συμβολοσειρά"(eval)". Αν η υπορουτίνα έχει αφαιρεθεί από τον πίνακα συμβόλων μετά την κλήση, είναι"(unknown)".$hasargs- αληθές αν ένας φρέσκος@_εγκαταστάθηκε για το πλαίσιο. Ψευδές για πλαίσιαevalκαιrequire.$wantarray- το περιβάλλον στο οποίο κλήθηκε το πλαίσιο, όπως θα το είχε αναφέρει ηwantarray: αληθές για λίστα, ορισμένο-αλλά-ψευδές ("") για βαθμωτό,undefγια κενό (void).$evaltext- για ένα πλαίσιοeval EXPR, το κείμενο πηγαίου κώδικα που μεταγλωττίστηκε. Undef γιαeval BLOCKκαι για μη-evalπλαίσια.$is_require- αληθές αν το πλαίσιο δημιουργήθηκε απόrequireήuse(κάθεuseδημιουργεί ένα πλαίσιοrequireεμφωλευμένο μέσα σε ένα πλαίσιοeval EXPR).$hints- η τιμή του$^Hτη στιγμή που μεταγλωττίστηκε ο κώδικας του πλαισίου. Εσωτερικό· η διάταξη δεν είναι σταθερή μεταξύ εκδόσεων της Perl.$bitmask- η τιμή του${^WARNING_BITS}στο ίδιο σημείο. Επίσης εσωτερικό.$hinthash- μια αναφορά στο hash%^Hπου καταγράφηκε κατά τη μεταγλώττιση, ήundefαν ήταν κενό. Μην την τροποποιείτε - η αναφορά δείχνει στο ζωντανό optree.
Καθολική κατάσταση που επηρεάζει#
@DB::args- ορίζεται ως παρενέργεια όταν ηcallerκαλείται με όρισμα μέσα από το πακέτοDB. Η λίστα ορισμάτων του καλούντος ψευδωνυμοποιείται σε αυτόν τον πίνακα για χρήση από τον debugger. Δείτε Οριακές περιπτώσεις παρακάτω - αυτή είναι μια προσπάθεια βέλτιστης πρόθεσης και έχει αιχμηρές γωνίες.$^H,${^WARNING_BITS},%^H- διαβάζονται από τη μεταγλωττισμένη κατάσταση του πλαισίου-στόχου για να συμπληρώσουν τα$hints,$bitmask,$hinthash.
Παραδείγματα#
Βρείτε το πακέτο του άμεσου καλούντος και αναφέρετε στο σωστό αρχείο καταγραφής:
sub log_for_caller {
my $pkg = caller;
warn "[$pkg] @_\n";
}
Παραγάγετε μια ετικέτα τοποθεσίας σε στιλ warn. Η caller επιστρέφει το όνομα αρχείου και τη γραμμή του σημείου κλήσης ένα πλαίσιο ψηλότερα, που είναι σχεδόν πάντα η πληροφορία που πραγματικά θέλετε σε ένα διαγνωστικό:
sub note {
my (undef, $file, $line) = caller;
print STDERR "note at $file line $line: @_\n";
}
Διατρέξτε ολόκληρη τη στοίβα. Επαναλάβετε την caller($i) μέχρι να επιστρέψει κενή λίστα:
sub stacktrace {
my @frames;
for (my $i = 0; my @f = caller($i); $i++) {
push @frames, \@f;
}
return @frames;
}
Ανιχνεύστε αν η τρέχουσα υπορουτίνα κλήθηκε σε περιβάλλον λίστας, βαθμωτό ή κενό. Αυτό είναι η wantarray στο τρέχον επίπεδο, αλλά για το πλαίσιο κάποιου άλλου το προσεγγίζετε μέσω της caller:
sub describe_parent_context {
my $wa = (caller(1))[5];
return !defined $wa ? "void"
: $wa ? "list"
: "scalar";
}
Διακρίνετε ένα πλαίσιο require/use από ένα κανονικό eval:
sub called_from_require {
my @f = caller(1);
return @f && $f[7]; # field 7 is $is_require
}
Αποτυπώστε ένα μεμονωμένο πλαίσιο όπως κάνει ο προεπιλεγμένος μορφοποιητής της die / του Carp - "at FILE line LINE":
sub location_tag {
my $depth = shift // 0;
my (undef, $file, $line) = caller($depth);
return defined $file ? "at $file line $line" : "at top level";
}
Οριακές περιπτώσεις#
Βαθμωτό περιβάλλον, χωρίς καλούντα: στο ανώτατο επίπεδο ενός σεναρίου, η
scalar callerεπιστρέφειundef, ενώ ηcallerσε περιβάλλον λίστας επιστρέφει την κενή λίστα. Ένα κοινό ιδίωμα για το «εκτελούμαι μεrequireως άρθρωμα ή ως σενάριο;» είναι τοcaller() ? ... : ....Τα πλαίσια XS παραλείπονται. Η
callerαναφέρει μόνο πλαίσια καθαρής Perl. Αν μια υπορουτίνα καθαρής Perl κλήθηκε από μια υπορουτίνα XS η οποία με τη σειρά της κλήθηκε από άλλη υπορουτίνα καθαρής Perl, ηcaller(0)από την εσωτερική υπορουτίνα αναφέρει την εξωτερική υπορουτίνα καθαρής Perl - το στρώμα XS είναι αόρατο. Τα βάθη στοίβας που μετρώνται με τηνcallerδεν περιλαμβάνουν επομένως διανομείς XS.Τα πλαίσια
evalδεν έχουν ορίσματα. Το$hasargsείναι ψευδές για πλαίσιαevalκαιrequire, και το$subroutineείναι η κυριολεκτική τιμή"(eval)"- όχι το πακέτο του περιβάλλοντος κώδικα.eval BLOCKέναντιeval EXPR. Και τα δύο δίνουν$subroutine eq "(eval)". Μόνο ηeval EXPRσυμπληρώνει το$evaltext· ηeval BLOCKτο αφήνειundef.Η
useδημιουργεί δύο πλαίσια. Μια εντολήuse Fooμεταγλωττίζεται ωςBEGIN { require Foo; Foo->import; }, ενώ η ίδια ηrequireυλοποιείται ωςeval EXPR. Η διατρέξιμη της στοίβας μέσα από μια γραμμήuseβλέπει επομένως ένα πλαίσιοevalσημασμένο ωςrequireμέσα σε ένα κανονικό πλαίσιοeval. Ελέγξτε το$is_requireγια να τα διακρίνετε.Υπορουτίνες
(unknown). Αν η υπορουτίνα που κατονομάζεται σε ένα πλαίσιο έχει διαγραφεί από τον πίνακα συμβόλων (επεμβάσεις στον πίνακα συμβόλων,delete $Foo::{bar}) μεταξύ της κλήσης και τηςcaller, το$subroutineδιαβάζεται ως"(unknown)".Οι βρόχοι και τα μπλοκ
tryδεν αποτελούν πλαίσια. Ταwhile,for,foreachκαιtryδεν δημιουργούν πλαίσια κλήσης. Ηcallerβλέπει μόνο κλήσεις υπορουτινών καιeval.Πλαίσια που αφαιρεί ο βελτιστοποιητής. Ο βελτιστοποιητής μπορεί να αφαιρέσει πλαίσια ουραίας κλήσης και παρόμοια προτού η
callerμπορέσει να τα παρατηρήσει. Γιαcaller(N)μεN > 1, το πλαίσιο που λαμβάνετε δεν είναι εγγυημένα το πλαίσιο που περιμένατε. Μην κωδικοποιείτε το βάθος στοίβας ως φέρουσα σύμβαση.Το
@DB::argsλειτουργεί με βέλτιστη πρόθεση. Συμπληρώνεται μόνο όταν ηcallerκαλείται με όρισμα μέσα από το πακέτοDB. Οι τιμές είναι ψευδώνυμα προς τον@_του πλαισίου-στόχου, όχι αντίγραφα - οπότε:Οι μεταβολές που έχει ήδη κάνει το πλαίσιο στον
@_είναι ορατές· οι αρχικές τιμές κατά την κλήση δεν διατηρούνται.Το
shift @_μέσα στο πλαίσιο συνήθως αναιρείται στο@DB::args, όμως ταpop @_, οι splices ή η λήψη αναφοράς στον@_σπάνε αυτή τη συμπεριφορά.Τα στοιχεία μπορεί να έχουν απελευθερωθεί και να έχουν επαναχρησιμοποιηθεί για άλλες τιμές μέχρι να τα διαβάσετε.
Παλιά κατάσταση από προηγούμενη κλήση της
callerενδέχεται να παραμένει στο@DB::argsαν η τρέχουσα κλήση δεν προκάλεσε ανανέωση. Χρησιμοποιήστε το για backtraces και εμφάνιση στον debugger· μην βασίζεστε σε αυτό για τη λογική του προγράμματος.
Το
$hinthashείναι ζωντανό. Η αναφορά hash στο πεδίο 10 δείχνει στο πραγματικό στιγμιότυπο%^Hπου έχει ψηθεί στο optree. Η τροποποίηση των περιεχομένων του μεταβάλλει την κατάσταση του μεταγλωττιστή. Διαβάστε το· μην το γράφετε.Το όνομα αρχείου και η γραμμή μπορούν να επανεγγραφούν. Οι οδηγίες
#lineκαι οτιδήποτε άλλο αναγνωρίζει ο μηχανισμός «Plain Old Comments (Not!)» (δείτεperlsyn) αλλάζουν τις τιμές που αναφέρει ηcaller, ακριβώς όπως αλλάζουν τα__FILE__και__LINE__.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
die- εγείρει εξαίρεση· το προεπιλεγμένο μήνυμά της χρησιμοποιεί τις ίδιες πληροφορίες αρχείου-και-γραμμής που εκθέτει ηcallereval- δημιουργεί πλαίσια που ηcallerσημαίνει με$subroutine eq "(eval)"και μπορεί να συμπληρώσει τα$evaltext/$is_requirewantarray- αναφέρει το περιβάλλον κλήσης του τρέχοντος πλαισίου· η ίδια τιμή εμφανίζεται ως πεδίο 5 τηςcaller(N)για το πλαίσιοNεπίπεδα ψηλότερα$^H- bits υπόδειξης κατά τη μεταγλώττιση· εμφανίζονται ως πεδίο 8%^H- hash υπόδειξης κατά τη μεταγλώττιση· εμφανίζεται ως πεδίο 10${^WARNING_BITS}- bitmask προειδοποιήσεων· εμφανίζεται ως πεδίο 9