3.3. Λίστες, λίστες και πάλι λίστες

Μιλήσαμε για συναρτήσεις και μεταβλητές και θα μιλήσουμε για τις λίστες Διάταξης.

3.3.1. Ορισμός μιας Λίστας

Πριν πούμε περισσότερα για τις λίστες, είναι απαραίτητο να κατανοήσετε την διαφορά μεταξύ ατομικών τιμών και λιστών.

Συναντήσαμε τις ατομικές τιμές όταν ορίσαμε μεταβλητές στις προηγούμενες ενότητες. Ατομική τιμή είναι μια μοναδική τιμή. Για παράδειγμα, μπορούμε να δώσουμε στην μεταβλητή «x» την μοναδική τιμή 8 ως εξής:

(let* ( (x 8) ) x)

(Προσθέσαμε την έκφραση x στο τέλος ώστε να εμφανιστεί η τιμή που δώθηκε στην μεταβλητή x - υπό κανονικές συνθήκες δεν θα χρειαστεί να κάνετε κάτι τέτοιο. Παρατηρήστε ότι η εντολή let* λειτουργεί όπως και μια συνάρτηση· η τιμή της τελευταίας εντολής είναι η επιστρεφόμενη τιμή.)

Μια μεταβλητή μπορεί, επίσης, να αναφέρεται σε μια λίστα τιμών, παρά σε μια και μοναδική τιμή. Για να δώσετε στην μεταβλητή x την λίστα των τιμών 1, 3, 5 πληκτρολογούμε:

(let* ( (x '(1 3 5))) x)

Εισάγετε και τις δυο εντολές στην Κονσόλα Script-Fu και παρατηρήστε πώς ανταποκρίνεται. Όταν πληκτρολογείτε την πρώτη εντολή, σαν αποτέλεσμα δίνει:

8

Όμως, όταν εισάγετε την άλλη εντολή, δίνει σαν αποτέλεσμα:

(1 3 5)

Όταν δίνει αποτέλεσμα την τιμή 8 σας λέει ότι το x περιέχει την ατομική τιμή 8. Όταν, όμως, απαντά με την λίστα (1 3 5) σας λέει ότι η x δεν περιέχει μια μοναδική τιμή, αλλά μια λίστα τιμών. Προσέξτε ότι δεν υπάρχουν κόμματα στην δήλωση ή απόδοση της λίστα, ούτε και στο εμφανιζόμενο αποτέλεσμα.

Η σύνταξη ορισμού μιας λίστας είναι:

'(a b c)

όπου a, b, και c είναι κυριολεκτικά. Η απόστροφος (') χρησιμοποιείται για να δείξει ότι, ό,τι ακολουθεί εντός των παρενθέσεων αποτελεί κατάλογο κυριολεκτικών τιμών και όχι κάποια συνάρτηση ή έκφραση.

Μια κενή λίστα ορίζεται ως εξής:

'()

ή, απλούστερα:

()

Οι λίστες μπορούν να περιέχουν ατομικές τιμές ή άλλες λίστες:

(let*
   (
        (x
           '("GIMP" (1 2 3) ("is" ("great" () ) ) )
        )
    )
    x
)
      

Παρατηρήστε ότι μετά την πρώτη απόστροφο, δεν χρειάζεστε πλέον να βάζετε απόστροφο όταν ορίζετε εσωτερικές λίστες. Αντιγράψτε την εντολή μέσα στην Κονσόλα Script-Fu και δείτε τι επιστρέφει.

Θα παρατηρήσετε ότι το αποτέλεσμα της επιστροφής δεν είναι μια μοναδική, ατομική τιμή, αλλά η λίστα κυριολεκτικών τιμών ("The GIMP"), η λίστα (1 2 3), κ.λ.π.

3.3.2. Ως τι να αντιλαμβάνεστε τις λίστες

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

3.3.3. Δημιουργία Λίστας μέσω Συνένωσης (Η Συνάρτηση Cons)

Μια από τις πιο κοινές συναρτήσεις που θα συναντήσετε είναι η συνάρτηση cons. Παίρνει μια τιμή και την θέτει στο δεύτερο όρισμά της, μια λίστα. Στην προηγούμενη ενότητα είπαμε ότι πρέπει να σκέφτεστε την λίστα σαν να αποτελείται από ένα στοιχείο (την κεφαλή) και το υπόλοιπο της λίστας (την ουρά). Έτσι ακριβώς λειτουργεί η cons — προσθέτει ένα στοιχείο στην κεφαλή της λίστας. Με τον τρόπο αυτόν μπορείτε να δημιουργήσετε μια λίστα, ως εξής:

(cons 1 '(2 3 4) )

Το αποτέλεσμα είναι η λίστα (1 2 3 4).

Μπορείτε επίσης να δημιουργήσετε μια λίστα με ένα στοιχείο:

(cons 1 () )

Όπως θα περίμενε κανείς, στην θέση κυριολεκτικών σταθερών μπορείτε να χρησιμοποιήσετε μεταβλητές τις οποίες δηλώσατε νωρίτερα.

3.3.4. Καθορισμός μιας Λίστας με την χρήση της Συνάρτησης list

Για να ορίσετε μια λίστα από κυριολεκτικές σταθερές ή προηγούμενες μεταβλητές, χρησιμοποιήστε την συνάρτηση list:

(list 5 4 3 a b c)

Αυτό θα συνθέσει και θα επιστρέψει μια λίστα που περιέχει τις τιμές που κρατούνται από τις μεταβλητές a, b και c. Π.χ.:

        (let*  (
                  (a 1)
                  (b 2)
                  (c 3)
               )

               (list 5 4 3 a b c)
        )
      

Αυτός ο κώδικας δημιουργεί τη λίστα (5 4 3 1 2 3).

3.3.5. Προσπέλαση τιμών στη λίστα A

Για να προσπελάσετε τις τιμές σε μια λίστα, χρησιμοποιείστε τις συναρτήσεις car και cdr, που επιστρέφουν το πρώτο στοιχείο της λίστας και τα υπόλοιπα της λίστας αντίστοιχα. Αυτές οι συναρτήσεις σπάνε τη λίστα κάτω σε κατασκευή κεφαλή : ουρά που ανέφερα πριν λίγο.

3.3.6. Η συνάρτηση car

Η car επιστρέφει το πρώτο στοιχείο του καταλόγου (την κορυφή του καταλόγου). Αυτός ο κατάλογος πρέπει να μην είναι μηδενικός (μη κενός). Έτσι, το παρακάτω επιστρέφει το πρώτο στοιχείο του καταλόγου:

(car '("first" 2 "third"))

που είναι:

"first"

3.3.7. Η συνάρτηση cdr

Η cdr επιστρέφει το υπόλοιπο του καταλόγου μετά το πρώτο στοιχείο (την ουρά του καταλόγου). Εάν υπάρχει μόνο ένα στοιχείο στον κατάλογο, τότε επιστρέφει έναν κενό κατάλογο.

(cdr '("first" 2 "third"))

επιστρέφει:

(2 "third")

ενώ το υπόλοιπο:

(cdr '("one and only"))

επιστρέφει:

()

3.3.8. Προσπελάζει άλλα στοιχεία στη λίστα

Εντάξει, πήραμε το πρώτο στοιχείο στη λίστα, καθώς και τα υπόλοιπα της λίστας, αλλά πώς θα προσπελάσουμε το δεύτερο, το τρίτο και τα άλλα στοιχεία μιας λίστας; Υπάρχουν πολλές "βολικές" συναρτήσεις γι' αυτό, π.χ., η κεφαλή της κεφαλής της ουράς της λίστας (caadr), η ουρά της ουράς της λίστας (cddr), κλ.

Η βασική σύμβαση ονοματολογίας είναι εύκολη: Τα a και τα d αντιπροσωπεύουν τις κεφαλές και τις ουρές της λίστας, έτσι

(car (cdr (car x) ) )

θα μπορούσε να γραφεί ως:

(cadar x)

Για να εξασκηθείτε με συναρτήσεις προσπέλασης λίστας, δοκιμάστε γράφοντας το παρακάτω (εκτός από το όλα σε μια γραμμή, εάν χρησιμοποιείτε κονσόλα)· χρησιμοποιείστε διαφορετικές παραλλαγές των car και cdr για να προσπελάσετε τα διαφορετικά στοιχεία της λίστας:

        (let* (
                 (x  '( (1 2 (3 4 5) 6)  7  8  (9 10) )
                 )
              )
              ; place your car/cdr code here
        )
      

Προσπαθήστε να προσπελάσετε τον αριθμό 3 στη λίστα χρησιμοποιώντας δύο κλήσεις συναρτήσεων. Εάν το καταφέρετε, είστε στο δρόμο για να γίνεται ένας ειδικός στο Script-Fu!

[Σημείωση] Σημείωση

Στο Scheme, το αγγλικό (;) σημαίνει την έναρξη ενός σχολίου. Αυτό και οτιδήποτε ακολουθεί στην ίδια γραμμή, αγνοούνται από τον διερμηνέα σεναρίων, έτσι μπορείτε να το χρησιμοποιήσετε για να προσθέσετε σχόλια, για να ανανεώσετε τη μνήμη σας, όταν κοιτάτε το σενάριο αργότερα.