Τελεστές#

Η Perl γράφει τους λογικούς τελεστές δύο φορές, σε δύο διαφορετικές κλάσεις προτεραιότητας. Οι συμβολικές μορφές σε στιλ C (&&, ||, !) δένουν σφιχτά· οι λεκτικές μορφές (and, or, not) δένουν πολύ χαλαρά. Υπάρχει επίσης το // για το ιδίωμα defined-or, το xor για το αποκλειστικό «ή», και ο τριαδικός ?: που είναι λογική επιλογή σε μεταμφίεση.

Ο πλήρης κατάλογος#

Τελεστής

Διαβάζεται ως

Επιστρέφει

Προτεραιότητα

!

όχι

κανονικοποιημένο 1 ή κενή συμβολοσειρά

υψηλή

&&

και

αριστερό αν ψευδές, αλλιώς δεξί (ο τελεστέος)

υψηλή

||

ή

αριστερό αν αληθές, αλλιώς δεξί (ο τελεστέος)

υψηλή

//

defined-or

αριστερό αν ορισμένο, αλλιώς δεξί (ο τελεστέος)

υψηλή

xor

αποκλειστικό ή

κανονικοποιημένο 1 ή κενή συμβολοσειρά

πολύ χαμηλή

not

όχι

κανονικοποιημένο 1 ή κενή συμβολοσειρά

πολύ χαμηλή

and

και

αριστερό αν ψευδές, αλλιώς δεξί (ο τελεστέος)

πολύ χαμηλή

or

ή

αριστερό αν αληθές, αλλιώς δεξί (ο τελεστέος)

πολύ χαμηλή

?:

τριαδικός

μεσαίο αν η συνθήκη αληθής, αλλιώς δεξί (τελεστέος)

χαμηλή

Δύο πράγματα σε αυτόν τον πίνακα κάνουν το μεγαλύτερο μέρος της δουλειάς:

  • Τα && και || επιστρέφουν τελεστέο, όχι λογική τιμή. Αυτή είναι η ιδιότητα που κάνει τα ιδιώματα της Perl να λειτουργούν όπως λειτουργούν. Δείτε παρακάτω.

  • Οι συμβολικές και λεκτικές μορφές διαφέρουν στην προτεραιότητα, όχι στο νόημα. Τα && και and υπολογίζουν την ίδια λογική συνάρτηση. Διαφέρουν στο πόσο σφιχτά δένουν με τους άλλους τελεστές γύρω τους. Γι” αυτό βλέπετε or die μετά από κλήσεις συναρτήσεων αλλά || μέσα σε εκφράσεις — το κεφάλαιο για το ιδίωμα or die εξηγεί.

Βραχυκύκλωμα και ο κανόνας επιστροφής τελεστέου#

Τα && και || αποτιμώνται από αριστερά προς τα δεξιά και σταματούν μόλις προσδιοριστεί το αποτέλεσμα.

  • A && B — αν το A είναι ψευδές, επιστρέφει το A χωρίς να αποτιμήσει το B. Αλλιώς επιστρέφει το B.

  • A || B — αν το A είναι αληθές, επιστρέφει το A χωρίς να αποτιμήσει το B. Αλλιώς επιστρέφει το B.

Καθοριστικά, η τιμή επιστροφής είναι ο ίδιος ο τελεστέος, όχι ένα κανονικοποιημένο αληθές/ψευδές. Αυτό κάνει μοτίβα όπως $config{port} || 8080 να λειτουργούν: αν το $config{port} έχει οριστεί (αληθές), η έκφραση είναι η τιμή του $config{port}· αν όχι, είναι το 8080.

my $port = $config{port} || 8080;
my $name = $user_input  || "anonymous";
my $list = shift        || [];

Η ίδια ιδιότητα τροφοδοτεί το or die:

open my $fh, '<', $path  or die "open $path: $!";
#  ^^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^
#  if open returns true,  the right-hand operand
#  the whole expression   is never evaluated
#  is true and we move on

Το open επιστρέφει αληθές στην επιτυχία, undef στην αποτυχία. Στην επιτυχία το βραχυκύκλωμα σταματά στα αριστερά και το die ποτέ δεν εκτελείται. Στην αποτυχία αποτιμάται ο δεξής τελεστέος, που είναι η κλήση die.

// — defined-or#

Το || χειρίζεται τα 0, "", και "0" το ίδιο με το undef. Μερικές φορές αυτό είναι λάθος: ένα ρυθμισμένο 0 είναι πραγματική τιμή, όχι ελλείπουσα. Το // βραχυκυκλώνει με βάση τον ορισμό αντί της αλήθειας:

  • A // B — αν το A είναι ορισμένο, επιστρέφει το A. Αλλιώς επιστρέφει το B.

my $port    = $config{port} || 8080;   # 0 means "use default" — wrong
my $port    = $config{port} // 8080;   # 0 means "0", undef means "use default"
my $verbose = $opt{verbose} // 0;       # 0 is a real choice

Οι σύνθετες μορφές ανάθεσης ||= και //= σας απαλλάσσουν από την επανάληψη της μεταβλητής στα αριστερά:

$config{port} //= 8080;   # set only if currently undef
$cache{$key}  ||= compute($key);   # set if currently false

Το xor και η απουσία μορφής υψηλής προτεραιότητας#

Δεν υπάρχει ^^ στην Perl. Το xor υπάρχει μόνο ως λεκτική μορφή πολύ χαμηλής προτεραιότητας, και σε αντίθεση με τα and/or δεν βραχυκυκλώνει (δεν μπορεί — και οι δύο πλευρές πρέπει να αποτιμηθούν για να προσδιοριστεί το αποτέλεσμα). Επιστρέφει κανονικοποιημένο 1 ή "", όχι τελεστέο.

if ($admin xor $guest) { ... }   # exactly one of the two

Για xor πάνω σε τιμές αντί για αλήθεια, το κατά bit ^ εφαρμόζεται σε ακεραίους — καλύπτεται στο κεφάλαιο εφαρμογών.

! και not#

Και τα δύο αρνούνται. Το ! είναι η συμβολική μορφή υψηλής προτεραιότητας· το not είναι η λεκτική μορφή χαμηλής προτεραιότητας. Και τα δύο επιστρέφουν κανονικοποιημένη τιμή: 1 για «ο τελεστέος ήταν ψευδής», κενή συμβολοσειρά "" για «ο τελεστέος ήταν αληθής».

my $missing = ! $config{port};       # 1 if port is unset/0/""/"0"
return if not @items;                # cleaner reading than `if !@items`

Ο τριαδικός ?:#

COND ? X : Y είναι λογική επιλογή: αν το COND είναι αληθές η τιμή είναι X, αλλιώς Y. Δεν είναι απλώς συντακτική ζάχαρη για if/else επειδή είναι έκφραση — έχει τιμή, μπορεί να ανατεθεί, να επιστραφεί, να περάσει ως όρισμα.

my $label = $count == 1 ? "1 item" : "$count items";
return $ok ? \%result : undef;

Προσοχή στην εμφώλευση: το $a ? $b : $c ? $d : $e αναλύεται ως $a ? $b : ($c ? $d : $e) — το αλυσιδωτό ?: είναι δεξιά προσεταιριστικό, που συνήθως είναι αυτό που θέλετε για μια κλιμάκωση if/elsif/else αλλά αξίζει να το γνωρίζετε αντί να μαντεύετε.

Γιατί υπάρχουν οι λεκτικές μορφές: προτεραιότητα, όχι στιλ#

Το || δένει σφιχτότερα από το =. Το or δένει χαλαρότερα από το = (ή το ,, ή οτιδήποτε άλλο συμβατικού βάρους). Αυτός είναι ο μοναδικός λόγος που υπάρχουν οι λεκτικές μορφές.

my $fh = open $h, '<', $path || die "no $path: $!";
#                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
# parses as: open $h, '<', ($path || die "no $path: $!")
# which is: open the file named "either $path or the die-message"
# which is: catastrophe.

my $fh = open $h, '<', $path or die "no $path: $!";
# parses as: ($fh = open $h, '<', $path) or die "no $path: $!"
# which does what you meant.

Εμπειρικός κανόνας:

  • Μέσα σε μια έκφραση, όπου θέλετε η τιμή να ρέει σε μια μεταβλητή ή σε άλλον τελεστή: χρησιμοποιήστε &&, ||, !, //.

  • Μετά από μια πρόταση, όπου θέλετε μια παρενέργεια (die, warn, return) να ενεργοποιηθεί υπό συνθήκη: χρησιμοποιήστε or, and, not.

Τι πρέπει να θυμάστε από αυτό το κεφάλαιο#

  • Τα && και || δεν είναι κατηγορήματα που επιστρέφουν 1 ή 0 — επιστρέφουν έναν από τους τελεστέους τους. Αυτό είναι το θεμέλιο των ||, ||=, or die, και των περισσότερων σύντομων ιδιωμάτων προεπιλογής.

  • Το // είναι το || για ορισμό, όχι αλήθεια. Χρησιμοποιήστε το όταν το 0 είναι έγκυρη τιμή.

  • Οι λεκτικές μορφές υπάρχουν για να δένουν πιο χαλαρά από την ανάθεση, όχι για στιλ.

  • Το xor υπάρχει, δεν έχει συμβολική μορφή, δεν βραχυκυκλώνει.

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

  • perlop — Λογικοί — ο σύντροφος αναφοράς, με το πλαίσιο των γραμμών προτεραιότητας και τις σημειώσεις ειδικά για το PetaPerl.

  • perlop — Προτεραιότητα — ο πλήρης πίνακας· οι γραμμές 5, 15, 16, 22, 23, 24 είναι οι τελεστές αυτής της σελίδας.

  • perlop — Τριαδικός?: ως λογική επιλογή.