Οι τιμές μπορεί να είναι αριθμοί ή κάποιο άλλο είδος δεδομένων, όπως γράμματα, ή δομές δεδομένων που αποτελούνται από απλούστερα μέρη. Στους κανόνες μιας γλώσσας προγραμματισμού, οι τιμές πρώτης κατηγορίας είναι τιμές που μπορούν να δοθούν σε συναρτήσεις, να επιστραφούν από συναρτήσεις και να συνδεθούν με ένα όνομα μεταβλητής. Οι συναρτήσεις που λαμβάνουν ή επιστρέφουν άλλες συναρτήσεις ονομάζονται συναρτήσεις ανώτερης τάξης. Οι περισσότερες γλώσσες που έχουν συναρτήσεις ως τιμές πρώτης τάξης έχουν επίσης συναρτήσεις ανώτερης τάξης και κλεισίματα.
Για παράδειγμα, ρίξτε μια ματιά στην ακόλουθη συνάρτηση Scheme:
; Επιστρέψτε έναν κατάλογο με όλα τα βιβλία με τουλάχιστον ΤΡΙΣΤΙΑ αντίτυπα που έχουν πουληθεί. (define (best-selling-books threshold) (filter (lambda (book) (>= (book-sales book) threshold)) book-list))
Σε αυτό το παράδειγμα, η έκφραση lambda (lambda (book) (>= (book-sales book) threshold)) είναι μέρος της συνάρτησης best-selling-books. Όταν εκτελείται η συνάρτηση, η Scheme πρέπει να κάνει την τιμή της lambda. Αυτό το κάνει φτιάχνοντας ένα closure με τον κώδικα της λάμδα και μια αναφορά στη μεταβλητή threshold, η οποία είναι μια ελεύθερη μεταβλητή μέσα στη λάμδα. (Μια ελεύθερη μεταβλητή είναι ένα όνομα που δεν είναι δεσμευμένο σε μια τιμή).
Η συνάρτηση φίλτρου εκτελεί στη συνέχεια το κλείσιμο σε κάθε βιβλίο του καταλόγου για να επιλέξει ποια βιβλία θα επιστρέψει. Επειδή το ίδιο το closure έχει μια αναφορά στο threshold, το closure μπορεί να χρησιμοποιεί αυτή την τιμή κάθε φορά που το filter εκτελεί το closure. Η ίδια η συνάρτηση filter μπορεί να γραφτεί σε ένα εντελώς ξεχωριστό αρχείο.
Ακολουθεί το ίδιο παράδειγμα ξαναγραμμένο σε ECMAScript (JavaScript), μια άλλη δημοφιλής γλώσσα με υποστήριξη για closures:
// Επιστρέφουμε μια λίστα με όλα τα βιβλία που έχουν πουλήσει τουλάχιστον 'threshold' αντίτυπα. function bestSellingBooks(threshold) { return bookList. filter( function(book) { return book. sales >= threshold; } ); }
Η ECMAScript χρησιμοποιεί εδώ τη λέξη function αντί για lambda και τη μέθοδο Array.filter αντί για τη συνάρτηση filter, αλλά κατά τα άλλα ο κώδικας κάνει το ίδιο πράγμα με τον ίδιο τρόπο.
Μια συνάρτηση μπορεί να δημιουργήσει ένα κλείσιμο και να το επιστρέψει. Το ακόλουθο παράδειγμα είναι μια συνάρτηση που επιστρέφει μια συνάρτηση.
Στο σύστημα:
; Επιστρέφει μια συνάρτηση που προσεγγίζει την παράγωγο της f ; χρησιμοποιώντας ένα διάστημα dx, το οποίο θα πρέπει να είναι κατάλληλα μικρό. (define (derivative f dx) (lambda (x) (/ (- (f (+ x dx)) (f (f x)) dx))))
Στο ECMAScript:
// Επιστρέψτε μια συνάρτηση που προσεγγίζει την παράγωγο της f // χρησιμοποιώντας ένα διάστημα dx, το οποίο θα πρέπει να είναι κατάλληλα μικρό. function derivative(f, dx) { return function(x) { return (f(x + dx) - f(x)) / dx; }; }
Το περιβάλλον κλεισίματος διατηρεί τις δεσμευμένες μεταβλητές f και dx μετά την επιστροφή της περιβάλλουσας συνάρτησης (παράγωγος). Σε γλώσσες χωρίς κλεισίματα, αυτές οι τιμές θα χάνονταν μετά την επιστροφή της περιβάλλουσας συνάρτησης. Σε γλώσσες με κλεισίματα, μια δεσμευμένη μεταβλητή πρέπει να διατηρείται στη μνήμη για όσο διάστημα την έχει οποιοδήποτε κλείσιμο.
Ένα κλείσιμο δεν είναι απαραίτητο να σχηματίζεται χρησιμοποιώντας μια ανώνυμη συνάρτηση. Η γλώσσα προγραμματισμού Python, για παράδειγμα, έχει περιορισμένη υποστήριξη για ανώνυμες συναρτήσεις, αλλά διαθέτει κλεισίματα. Για παράδειγμα, ένας τρόπος με τον οποίο το παραπάνω παράδειγμα της ECMAScript θα μπορούσε να υλοποιηθεί στην Python είναι ο εξής:
# Επιστρέψτε μια συνάρτηση που προσεγγίζει την παράγωγο της f # χρησιμοποιώντας ένα διάστημα dx, το οποίο θα πρέπει να είναι κατάλληλα μικρό. def derivative(f, dx): def gradient(x): return (f(x + dx) - f(x)) / dx return gradient
Σε αυτό το παράδειγμα, η συνάρτηση με το όνομα gradient κάνει ένα κλείσιμο μαζί με τις μεταβλητές f και dx. Η εξωτερική περιβάλλουσα συνάρτηση με το όνομα παράγωγος επιστρέφει αυτό το κλείσιμο. Στην περίπτωση αυτή, μια ανώνυμη συνάρτηση θα μπορούσε επίσης να λειτουργήσει.
def derivative(f, dx): return lambda x: (f(x + dx) - f(x)) / dx
Η Python πρέπει συχνά να χρησιμοποιεί επώνυμες συναρτήσεις, επειδή οι εκφράσεις λάμδα μπορούν να περιέχουν μόνο άλλες εκφράσεις (κώδικα που επιστρέφει μια τιμή) και όχι δηλώσεις (κώδικα που έχει αποτελέσματα αλλά δεν έχει τιμή). Αλλά σε άλλες γλώσσες, όπως η Scheme, όλος ο κώδικας επιστρέφει μια τιμή- στη Scheme, τα πάντα είναι μια έκφραση.