Ανώνυμες αναφορές - [...] και {...}#

Δεν θέλετε πάντα να δώσετε όνομα σε έναν εσωτερικό πίνακα ή κατακερματισμό πριν τον αναφέρετε. Η Perl παρέχει δύο κατασκευαστές που χτίζουν ένα νέο κοντέινερ και σας παραδίδουν αναφορά σε αυτό σε μία έκφραση:

  • Το [...] χτίζει έναν φρέσκο ανώνυμο πίνακα και επιστρέφει αναφορά σε αυτόν.

  • Το {...} χτίζει έναν φρέσκο ανώνυμο κατακερματισμό και επιστρέφει αναφορά σε αυτόν.

Αυτοί είναι ο κύριος τρόπος συναρμολόγησης εμφωλευμένων δομών δεδομένων.

Πίνακας: [...]#

my $aref = [1, 'foo', undef, 13];

Η δεξιά πλευρά αποτιμά τη λίστα (1, 'foo', undef, 13), κατανέμει έναν νέο πίνακα, αντιγράφει αυτά τα τέσσερα στοιχεία μέσα, και αποδίδει ένα βαθμωτό που κρατάει αναφορά σε αυτόν τον πίνακα. Αυτό είναι ακριβώς ισοδύναμο με τη μορφή δύο βημάτων με κατονομασμένο ενδιάμεσο:

my @array = (1, 'foo', undef, 13);
my $aref  = \@array;

…εκτός από το ότι καμία μεταβλητή @array δεν διαρρέει στην περιβάλλουσα εμβέλεια. Ο ανώνυμος πίνακας δεν έχει όνομα· υπάρχει μόνο η αναφορά, και ο πίνακας παραμένει ζωντανός όσο παραμένει και η αναφορά.

Οι κενές μορφές είναι χρήσιμες ως αρχικές τιμές:

my $aref = [];         # reference to a new empty array
push @{$aref}, 1, 2;   # now [1, 2]

Κατακερματισμός: {...}#

my $href = { APR => 4, AUG => 8 };

Ίδια ιδέα για τους κατακερματισμούς. Η έκφραση είναι μια λίστα ζευγών κλειδιού/τιμής (το => είναι απλώς κόμμα που αυτο-εισαγωγοποιεί την αριστερή του πλευρά), ένας νέος κατακερματισμός κατανέμεται, τα ζεύγη εισάγονται, και παίρνετε πίσω μια αναφορά:

my %hash = (APR => 4, AUG => 8);
my $href = \%hash;

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

my $href = {};
$href->{red} = 17;

{...} έναντι μπλοκ - μια γωνία του αναλυτή#

Ένα γυμνό {...} σε θέση πρότασης αναλύεται ως μπλοκ, όχι ως κατασκευαστής κατακερματισμού:

{ foo => 1 };          # block, with `foo => 1` as its expression

Στις περισσότερες θέσεις - στα δεξιά του =, μέσα σε λίστα, ως όρισμα σε συνάρτηση - η Perl εντοπίζει αυτόματα την ερμηνεία του κατασκευαστή κατακερματισμού. Αν χρειαστεί ποτέ να επιβάλετε την ερμηνεία του κατασκευαστή κατακερματισμού, βάλτε + μπροστά:

my $x = +{ foo => 1 }; # unambiguous: always a hash reference

Σπάνια θα το χρειαστείτε αυτό. Μέσα σε return +{...} από υπορουτίνα και σε μερικές άλλες θέσεις «τύπου πρότασης», είναι η λύση.

Εμφώλευση - κατασκευαστές μέσα σε κατασκευαστές#

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

my $tree = {
    name     => 'root',
    children => [
        { name => 'left',  children => [] },
        { name => 'right', children => [
            { name => 'r1', children => [] },
        ] },
    ],
};

print $tree->{children}[1]{children}[0]{name};   # r1

Κάθε [...] και {...} κατανέμει φρέσκα. Σε αντίθεση με την παγίδα «κοινού εσωτερικού πίνακα» από τους Πίνακες πινάκων, οι εμφωλευμένοι κατασκευαστές δεν μοιράζονται ποτέ αποθήκευση κατά λάθος.

Κατονομασμένα ενδιάμεσα έναντι ανώνυμων κατασκευαστών#

Και οι δύο μορφές λειτουργούν. Επιλέξτε με βάση την αναγνωσιμότητα:

  • Ανώνυμος κατασκευαστής όταν το κοντέινερ έχει έναν σκοπό και ο μοναδικός του ρόλος είναι «να είναι η τιμή αυτού του πεδίου». Εμφωλευμένα κυριολεκτικά δεδομένων, μίας χρήσης πίνακες αναζήτησης, εγγραφές πίνακα callback.

  • Κατονομασμένο ενδιάμεσο όταν χτίζετε το κοντέινερ σταδιακά, ή όταν θέλετε να χρησιμοποιήσετε τελεστές πίνακα/κατακερματισμού πάνω του απευθείας χωρίς να επαναλαμβάνετε @{...} / %{...}:

    my @row;
    for my $x (@source) {
        push @row, transform($x);
    }
    $grid[$i] = \@row;
    

Αντιγραφή έναντι κοινής χρήσης#

Οι ανώνυμοι κατασκευαστές πάντα κατανέμουν· δεν μοιράζονται ποτέ. Αλλά η ανάθεση μιας αναφοράς σε άλλο βαθμωτό δεν αντιγράφει τίποτα:

my $a = [1, 2, 3];
my $b = $a;            # $a and $b refer to the SAME array
push @{$b}, 4;
print "@{$a}";         # 1 2 3 4

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

my $copy_aref = [ @{$a} ];     # new array, same elements
my $copy_href = { %{$h} };     # new hash, same keys/values

Η νέα αναφορά είναι ανεξάρτητη από την αρχική. Οι τιμές μέσα είναι ακόμα κοινές - αν αυτές οι τιμές είναι οι ίδιες αναφορές, οι δύο δομές δείχνουν ακόμα σε κοινά υποδέντρα. Αυτό είναι ρηχή αντιγραφή. Για βαθιά αντιγραφή, καταφύγετε σε άρθρωμα όπως το Storable (dclone).

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

  • Αναφορές υπορουτινών - η τρίτη γεύση ανώνυμου πράγματος, χρησιμοποιώντας sub { ... } αντί για [...] ή {...}.

  • Ασθενείς αναφορές - απαραίτητες όταν μια εμφωλευμένη δομή δείχνει πίσω στον εαυτό της.