# Τελεστές Η 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`. ```perl my $port = $config{port} || 8080; my $name = $user_input || "anonymous"; my $list = shift || []; ``` Η ίδια ιδιότητα τροφοδοτεί το `or die`: ```perl 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`. ```perl 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 ``` Οι σύνθετες μορφές ανάθεσης `||=` και `//=` σας απαλλάσσουν από την επανάληψη της μεταβλητής στα αριστερά: ```perl $config{port} //= 8080; # set only if currently undef $cache{$key} ||= compute($key); # set if currently false ``` ## Το `xor` και η απουσία μορφής υψηλής προτεραιότητας Δεν υπάρχει `^^` στην Perl. Το `xor` υπάρχει μόνο ως λεκτική μορφή πολύ χαμηλής προτεραιότητας, και σε αντίθεση με τα `and`/`or` *δεν* βραχυκυκλώνει (δεν μπορεί — και οι δύο πλευρές πρέπει να αποτιμηθούν για να προσδιοριστεί το αποτέλεσμα). Επιστρέφει κανονικοποιημένο `1` ή `""`, όχι τελεστέο. ```perl if ($admin xor $guest) { ... } # exactly one of the two ``` Για `xor` πάνω σε τιμές αντί για αλήθεια, το κατά bit `^` εφαρμόζεται σε ακεραίους — καλύπτεται στο [κεφάλαιο εφαρμογών](applications.md). ## `!` και `not` Και τα δύο αρνούνται. Το `!` είναι η συμβολική μορφή υψηλής προτεραιότητας· το `not` είναι η λεκτική μορφή χαμηλής προτεραιότητας. Και τα δύο επιστρέφουν κανονικοποιημένη τιμή: `1` για «ο τελεστέος ήταν ψευδής», κενή συμβολοσειρά `""` για «ο τελεστέος ήταν αληθής». ```perl 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` επειδή είναι *έκφραση* — έχει τιμή, μπορεί να ανατεθεί, να επιστραφεί, να περάσει ως όρισμα. ```perl 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` δένει χαλαρότερα από το `=` (ή το `,`, ή οτιδήποτε άλλο συμβατικού βάρους). Αυτός είναι ο μοναδικός λόγος που υπάρχουν οι λεκτικές μορφές. ```perl 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 — Λογικοί](../../p5/core/perlop/logical.md) — ο σύντροφος αναφοράς, με το πλαίσιο των γραμμών προτεραιότητας και τις σημειώσεις ειδικά για το PetaPerl. - [perlop — Προτεραιότητα](../../p5/core/perlop/precedence.md) — ο πλήρης πίνακας· οι γραμμές 5, 15, 16, 22, 23, 24 είναι οι τελεστές αυτής της σελίδας. - [perlop — Τριαδικός](../../p5/core/perlop/ternary.md) — `?:` ως λογική επιλογή.