Βασικά - λήψη αναφορών και χρήση τους#

Υπάρχουν μόνο δύο τρόποι για να φτιάξετε μια αναφορά σε κάτι που έχει ήδη όνομα, και μόνο δύο τρόποι για να χρησιμοποιήσετε μια αναφορά μόλις την έχετε. Αυτό το κεφάλαιο καλύπτει και τους δύο. Οι ανώνυμοι κατασκευαστές ([...], {...}) καλύπτονται στις Ανώνυμες αναφορές.

Δημιουργία αναφοράς με ανάστροφη κάθετο#

Βάλτε μια ανάστροφη κάθετο μπροστά από οποιαδήποτε μεταβλητή, και παίρνετε ένα βαθμωτό που αναφέρεται σε αυτήν:

my @array = (1, 2, 3);
my %hash  = (APR => 4, AUG => 8);
my $n     = 42;

my $aref  = \@array;   # reference to the array
my $href  = \%hash;    # reference to the hash
my $sref  = \$n;       # reference to the scalar

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

my $copy   = $aref;    # two scalars, one underlying array
my @slots;
$slots[3]  = $href;    # hash reference stored as an array element
my $pulled = $slots[3];

Και το $aref και το $copy δείχνουν στον ίδιο πίνακα. Η αλλαγή του πίνακα μέσω του ενός είναι ορατή μέσω του άλλου. Για να αντιγράψετε πραγματικά τα περιεχόμενα, δείτε τις Ανώνυμες αναφορές.

Πώς εκτυπώνεται μια αναφορά#

Μετατρέψτε μια αναφορά σε συμβολοσειρά και παίρνετε μια ετικέτα τύπου συν μια διεύθυνση:

print "$aref\n";       # ARRAY(0x55d3c1a02b40)
print "$href\n";       # HASH(0x55d3c1a02be0)

Αν δείτε ποτέ τέτοια έξοδο κατά λάθος, εκτυπώσατε την αναφορά εκεί που εννοούσατε να εκτυπώσετε τα περιεχόμενα.

Χρήση αναφοράς - η μορφή με αγκύλες#

Όπου θα μπορούσατε να γράψετε όνομα μεταβλητής, μπορείτε να βάλετε την αναφορά σε αγκύλες αντί αυτής. Ο κανόνας είναι μηχανικός:

Λειτουργία επί του @array

Ίδια λειτουργία μέσω $aref

@array

@{$aref}

scalar @array

scalar @{$aref}

$array[3]

${$aref}[3]

$array[3] = 17

${$aref}[3] = 17

for my $x (@array) { ... }

for my $x (@{$aref}) { ... }

Οι κατακερματισμοί ακολουθούν το ίδιο μοτίβο:

Λειτουργία επί του %hash

Ίδια λειτουργία μέσω $href

%hash

%{$href}

keys %hash

keys %{$href}

$hash{red}

${$href}{red}

$hash{red} = 17

${$href}{red} = 17

Και τα βαθμωτά:

my $x   = 10;
my $ref = \$x;
print ${$ref};         # 10
${$ref} = 99;
print $x;              # 99

Οι αγκύλες μπορούν συνήθως να παραλειφθούν όταν αυτό που βρίσκεται μέσα είναι μια απλή βαθμωτή μεταβλητή: το @$aref σημαίνει το ίδιο με το @{$aref}, και το $$sref σημαίνει το ίδιο με το ${$sref}. Ξεκινήστε με τη μορφή με αγκύλες μέχρι η σύντομη μορφή να παύσει να μοιάζει αμφίσημη· τόσο το $$hash{key} όσο και το ${$hash}{key} λειτουργούν, αλλά το $$table{$country}[0] παρανοείται ευκολότερα από το ${$table}{$country}[0].

Χρήση αναφοράς - η μορφή με βέλος#

Το πιο συνηθισμένο πράγμα που κάνετε με μια αναφορά είναι να ανακτήσετε ένα στοιχείο από τον πίνακα ή κατακερματισμό στον οποίο δείχνει. Η μορφή με αγκύλες λειτουργεί (${$aref}[3]) αλλά είναι δυσανάγνωστη. Η μορφή με βέλος είναι η συντομογραφία:

$aref->[3]             # same as ${$aref}[3]
$href->{red}           # same as ${$href}{red}

Το βέλος δεν είναι καλλωπιστικό. Είναι αυτό που διακρίνει δύο διαφορετικές σημασίες:

$aref->[3]             # fourth element of the array $aref points at
$aref[3]               # fourth element of the unrelated array @aref

Τα $aref και @aref είναι ξεχωριστές μεταβλητές, τόσο άσχετες όσο τα $x και @x. Το ξεχασμένο βέλος ανακτά σιωπηλά από έναν διαφορετικό πίνακα που πιθανότατα δεν υπάρχει. Η εκτέλεση υπό use strict μετατρέπει το λάθος σε σφάλμα μεταγλώττισης αντί για σιωπηλή λάθος απάντηση κατά τον χρόνο εκτέλεσης.

Ρωτώντας τι δείχνει μια αναφορά#

Η ενσωματωμένη ref επιστρέφει μια συμβολοσειρά που περιγράφει το είδος του αναφερόμενου:

ref $aref              # ARRAY
ref $href              # HASH
ref $sref              # SCALAR
ref \&printer          # CODE
ref $n                 # empty string - $n isn't a reference

Συνδυάστε με λογικό περιβάλλον για να ελέγξετε «είναι αυτό αναφορά;»:

if (ref $maybe) {
    # it's a reference of some kind
}
if (ref $maybe eq 'ARRAY') {
    # it's specifically an array reference
}

Δείτε την ref για την πλήρη λίστα συμβολοσειρών επιστροφής (συμπεριλαμβανομένων CODE, GLOB, REF, Regexp, και του ονόματος πακέτου όταν η αναφορά έχει γίνει blessed σε μια κλάση).

Δύο συνηθισμένα λάθη αρχαρίων#

  • Αντιμετώπιση μιας αναφοράς σαν να ήταν το υποκείμενο κοντέινερ. Το push $aref, 1 δεν προσθέτει στον πίνακα· είναι σφάλμα τύπου. Πρέπει να αποαναφέρετε: push @{$aref}, 1 ή (ισοδύναμα) push @$aref, 1.

  • Παράλειψη του βέλους μεταξύ μεταβλητής και του δείκτη της. Το $aref[3] δεν είναι το ίδιο με το $aref->[3]. Το πρώτο διαβάζει από τον @aref, το δεύτερο διαβάζει μέσω της αναφοράς.

Πού να πάτε στη συνέχεια#

  • Πίνακες πινάκων - η δισδιάστατη περίπτωση, και ο κανόνας του βέλους-μεταξύ-δεικτών.

  • Ανώνυμες αναφορές - [...] και {...} για κατασκευή δομών χωρίς κατονομασμένα ενδιάμεσα.