Ροή ελέγχου

LINE#

Ένα διακριτικό μεταγλώττισης που αποτιμάται στον αριθμό γραμμής στην οποία εμφανίζεται μέσα στον πηγαίο κώδικα.

Το __LINE__ δεν είναι συνάρτηση. Είναι ένα ειδικό διακριτικό που ο αναλυτής αντικαθιστά, κατά τη μεταγλώττιση, με έναν κυριολεκτικό ακέραιο - τον αριθμό γραμμής της θέσης στο αρχείο όπου βρίσκεται το διακριτικό. Είναι ο τυπικός τρόπος για να σφραγίσετε ένα διαγνωστικό, μια γραμμή καταγραφής ή μια εκτύπωση αποσφαλμάτωσης με την ακριβή θέση που την παρήγαγε, χωρίς το κόστος μιας αναζήτησης caller κατά τον χρόνο εκτέλεσης.

Σύνοψη#

__LINE__

Τι επιστρέφεται#

Ένας ακέραιος: ο αριθμός γραμμής του διακριτικού, με αρίθμηση από το 1, μέσα στην τρέχουσα μονάδα μεταγλώττισης. Η τιμή είναι ένας απλός αριθμός, χρησιμοποιήσιμος οπουδήποτε δέχεται αριθμό - σε αριθμητικές πράξεις, σε παρεμβολή σε συμβολοσειρά, ως κλειδί πίνακα κατακερματισμού, ως όρισμα σε die ή warn.

print __LINE__, "\n";        # prints the line number of this line
my $where = "line " . __LINE__;

Επειδή η αντικατάσταση γίνεται κατά την ανάλυση, κάθε εμφάνιση του __LINE__ είναι ουσιαστικά μια διαφορετική σταθερά. Δύο αντίγραφα σε δύο διαφορετικές γραμμές παράγουν δύο διαφορετικούς αριθμούς· ένα μεμονωμένο __LINE__ μέσα σε βρόχο παράγει τον ίδιο αριθμό σε κάθε επανάληψη.

Κατά τη μεταγλώττιση, όχι κατά τον χρόνο εκτέλεσης#

Η τιμή παγώνει όταν μεταγλωττίζεται ο πηγαίος κώδικας. Μια συνηθισμένη παρανόηση:

sub where { return __LINE__ }     # returns the line where `__LINE__`
                                  # was written, i.e. the `sub` body's
                                  # line - NOT the caller's line

Για να αποτυπώσετε τον αριθμό γραμμής του καλούντος, χρησιμοποιήστε την caller:

sub where { my (undef, undef, $line) = caller; return $line }

Μέσα σε eval συμβολοσειράς, το __LINE__ αριθμεί τις γραμμές της συμβολοσειράς που μεταγλωττίζεται (ξεκινώντας από 1 για την πρώτη γραμμή της συμβολοσειράς), όχι τις γραμμές του περιβάλλοντος αρχείου.

Αλλαγή του αναφερόμενου αριθμού γραμμής#

Ο αριθμός γραμμής που αναφέρει το __LINE__ είναι ο αριθμός γραμμής στον οποίο ο λεκτικός αναλυτής πιστεύει ότι βρίσκεται. Μια οδηγία #line επαναφέρει αυτή την πεποίθηση:

#line 1000 "virtual.pl"
print __LINE__, "\n";        # prints 1001

Το #line NNN από μόνο του ρυθμίζει μόνο τον αριθμό γραμμής· το #line NNN "NAME" αλλάζει επίσης ό,τι αναφέρει το __FILE__. Γεννήτριες κώδικα, μηχανές προτύπων και προεπεξεργαστές το χρησιμοποιούν για να κάνουν τα διαγνωστικά να δείχνουν πίσω στον αρχικό πηγαίο κώδικα αντί στο παραγόμενο αρχείο. Δείτε το Plain Old Comments (Not!) στην ενότητα perlsyn της αναφοράς για την ακριβή σύνταξη και τους κανόνες εμβέλειας.

Παραδείγματα#

Σφραγίστε ένα διαγνωστικό με την προέλευσή του:

die "bad input at ", __FILE__, " line ", __LINE__, "\n"
    unless defined $x;

Η die με μήνυμα που δεν τελειώνει σε newline προσαρτά ήδη " at FILE line LINE.\n". Χρησιμοποιήστε την παραπάνω ρητή μορφή μόνο όταν θέλετε να ελέγξετε τη μορφοποίηση, ή όταν έχετε καταστείλει το αυτόματο επίθημα με ένα τελικό newline.

Καταγραφή με πρόθεμα αρχείου και γραμμής:

sub logf {
    my ($file, $line) = (__FILE__, __LINE__);
    warn "[$file:$line] @_\n";
}

Αυτό καταγράφει τη γραμμή όπου γράφτηκε το __LINE__ - μέσα στην logf - κάτι που σπάνια είναι αυτό που θέλετε. Το σωστό μοτίβο χρησιμοποιεί την caller:

sub logf {
    my (undef, $file, $line) = caller;
    warn "[$file:$line] @_\n";
}

Χρησιμοποιήστε το __LINE__ απευθείας όταν σημειώνετε αυτό το κομμάτι κώδικα, όχι τον καλούντα:

print STDERR "checkpoint at line ", __LINE__, "\n";

Μετατοπίστε τα διαγνωστικά με #line:

#line 42 "user-input.pl"
die "syntax error\n";        # dies reporting user-input.pl line 42

Οριακές περιπτώσεις#

  • Δεν είναι συνάρτηση, δεν καλείται. Το __LINE__() είναι συντακτικό σφάλμα. Το διακριτικό δεν δέχεται ορίσματα και δεν έχει μορφή με παρενθέσεις.

  • Δεν παρεμβάλλεται μέσα σε συμβολοσειρές σε διπλά εισαγωγικά. Το "see line __LINE__" εκτυπώνει την κυριολεκτική συμβολοσειρά see line __LINE__. Συνενώστε αντ’ αυτού: "see line " . __LINE__.

  • Δεν είναι έγκυρο bareword κλειδιού πίνακα κατακερματισμού στη συνηθισμένη σύντομη μορφή. Μέσα σε περιβάλλον κλειδιού πίνακα κατακερματισμού { ... }, το $h{__LINE__} λειτουργεί επειδή το διακριτικό αναλύεται ως έκφραση, αλλά και το $h{ __LINE__ } λειτουργεί και είναι σαφέστερο. Το $h{__LINE__ => 1} αναλύει το __LINE__ ως bareword παχιού κόμματος (δηλαδή τη συμβολοσειρά "__LINE__"), κάτι που σχεδόν ποτέ δεν είναι αυτό που θέλετε - γράψτε (__LINE__, 1) ή (__LINE__() => 1) αν θέλετε την κυριολεκτική τιμή.

  • Μέσα σε eval συμβολοσειράς, το __LINE__ μετράει από τη γραμμή 1 της αποτιμημένης συμβολοσειράς. Προθέστε τη δική σας οδηγία #line στη συμβολοσειρά για να κάνετε τα διαγνωστικά να δείχνουν στο περικλείον αρχείο:

    my $code = qq{#line @{[__LINE__+1]} "@{[__FILE__]}"\n} . $user_code;
    eval $code;
    
  • Μέσα στο σώμα ενός here-doc, το __LINE__ αποτιμάται στη γραμμή του ανοίγματος << στη γραμμή όπου αναφέρεται το here-doc, όχι σε γραμμές μέσα στο σώμα - τα σώματα here-doc είναι δεδομένα, όχι κώδικας.

  • Heredoc και οδηγίες γραμμής. Το #line μέσα σε σώμα here-doc δεν έχει καμία επίδραση· είναι απλώς κείμενο. Το #line λειτουργεί μόνο ως οδηγία στην αρχή γραμμής, σε περιβάλλον κώδικα.

  • Αρνητικοί ή μηδενικοί αριθμοί γραμμής. Το #line 0 είναι νόμιμο και κάνει την επόμενη φυσική γραμμή να αναφέρεται ως γραμμή 1 (η ίδια η οδηγία είναι γραμμή 0, η γραμμή μετά είναι γραμμή 1). Οι αρνητικοί αριθμοί γίνονται δεκτοί αλλά παράγουν εκπληκτικά διαγνωστικά· μην το κάνετε.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • __FILE__ - το συνοδευτικό διακριτικό για το όνομα του τρέχοντος αρχείου πηγαίου κώδικα· τα δύο σχεδόν πάντα χρησιμοποιούνται μαζί

  • __PACKAGE__ - διακριτικό μεταγλώττισης για το όνομα του τρέχοντος πακέτου, ίδια οικογένεια ειδικών διακριτικών

  • caller - το ισοδύναμο χρόνου εκτέλεσης όταν χρειάζεστε τον αριθμό γραμμής του καλούντος, όχι τη γραμμή του ίδιου του σημείου κλήσης

  • die - προσαρτά αυτόματα at FILE line LINE όταν το μήνυμα δεν έχει τελικό newline, καταργώντας την ανάγκη για ρητό __LINE__

  • warn - ίδια αυτόματη συμπεριφορά εντοπισμού θέσης με την die για μη μοιραία διαγνωστικά