Κλείσιμο (επιστήμη υπολογιστών)

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

Ο Peter J. Landin έδωσε σε αυτή την ιδέα το όνομα "κλείσιμο" το 1964. Η γλώσσα προγραμματισμού Scheme έκανε τα closures δημοφιλή μετά το 1975. Πολλές γλώσσες προγραμματισμού που δημιουργήθηκαν μετά από αυτή τη χρονική περίοδο έχουν closures.

Οι ανώνυμες συναρτήσεις (συναρτήσεις χωρίς όνομα) καλούνται μερικές φορές λανθασμένα closures. Οι περισσότερες γλώσσες που έχουν ανώνυμες συναρτήσεις έχουν επίσης κλεισίματα. Μια ανώνυμη συνάρτηση είναι επίσης ένα κλείσιμο αν έχει ένα δικό της περιβάλλον με τουλάχιστον μια δεσμευμένη μεταβλητή. Μια ανώνυμη συνάρτηση χωρίς δικό της περιβάλλον δεν είναι κλείσιμο. Ένα ονομαστικό κλείσιμο δεν είναι ανώνυμο.

Κλεισίματα και συναρτήσεις πρώτης κατηγορίας

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

Για παράδειγμα, ρίξτε μια ματιά στην ακόλουθη συνάρτηση 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, τα πάντα είναι μια έκφραση.

Χρήσεις των κλεισιμάτων

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

  • Οι σχεδιαστές βιβλιοθηκών λογισμικού μπορούν να επιτρέπουν στους χρήστες να προσαρμόζουν τη συμπεριφορά τους περνώντας κλεισίματα ως ορίσματα σε σημαντικές συναρτήσεις. Για παράδειγμα, μια συνάρτηση που ταξινομεί τιμές μπορεί να δεχτεί ένα όρισμα κλεισίματος που συγκρίνει τις προς ταξινόμηση τιμές σύμφωνα με ένα κριτήριο που ορίζει ο χρήστης.
  • Επειδή τα κλεισίματα καθυστερούν την αξιολόγηση -δηλαδή, δεν "κάνουν" τίποτα μέχρι να κληθούν- μπορούν να χρησιμοποιηθούν για τον ορισμό δομών ελέγχου. Για παράδειγμα, όλες οι τυπικές δομές ελέγχου της Smalltalk, συμπεριλαμβανομένων των διακλαδώσεων (if/then/else) και των βρόχων (while και for), ορίζονται χρησιμοποιώντας αντικείμενα των οποίων οι μέθοδοι δέχονται closures. Οι χρήστες μπορούν επίσης εύκολα να ορίσουν τις δικές τους δομές ελέγχου.
  • Μπορούν να παραχθούν πολλαπλές συναρτήσεις που κλείνουν πάνω από το ίδιο περιβάλλον, επιτρέποντάς τους να επικοινωνούν ιδιωτικά μεταβάλλοντας αυτό το περιβάλλον (σε γλώσσες που επιτρέπουν την ανάθεση).

Στο σύστημα

(define foo #f) (define bar #f) (let ((secret-message "none")) (set! foo (lambda (msg) (set! secret-message msg))) (set! bar (lambda () secret-message)))) (display (bar)) ; εκτυπώνει "none" (newline) (foo "meet me by the docks at midnight") (display (bar)) ; εκτυπώνει "meet me by the docks at midnight"
  • Τα κλεισίματα μπορούν να χρησιμοποιηθούν για την υλοποίηση συστημάτων αντικειμένων.

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

Ερωτήσεις και απαντήσεις

Ερ: Τι είναι το κλείσιμο στην επιστήμη των υπολογιστών;


A: Ένα closure είναι μια συνάρτηση που έχει ένα δικό της περιβάλλον.

Ερ: Τι περιέχει το περιβάλλον ενός κλεισίματος;


A: Το περιβάλλον ενός closure περιέχει τουλάχιστον μία δεσμευμένη μεταβλητή.

Ερ: Ποιος έδωσε στην ιδέα του closure το όνομά της;


Α: Ο Peter J. Landin έδωσε το όνομά του στην ιδέα του closure το 1964.

Ερ: Ποια γλώσσα προγραμματισμού έκανε τα closures δημοφιλή μετά το 1975;


Α: Η γλώσσα προγραμματισμού Scheme έκανε τα closures δημοφιλή μετά το 1975.

Ε: Είναι οι ανώνυμες συναρτήσεις και τα closures το ίδιο πράγμα;


Α: Οι ανώνυμες συναρτήσεις καμιά φορά κακώς αποκαλούνται closures, αλλά δεν είναι όλες οι ανώνυμες συναρτήσεις closures.

Ερ: Τι κάνει μια ανώνυμη συνάρτηση ένα κλείσιμο;


Α: Μια ανώνυμη συνάρτηση είναι closure αν έχει ένα δικό της περιβάλλον με τουλάχιστον μια δεσμευμένη μεταβλητή.

Ε: Είναι ανώνυμο ένα ονομαστικό κλείσιμο;


Α: Όχι, ένα ονομαστικό κλείσιμο δεν είναι ανώνυμο.

AlegsaOnline.com - 2020 / 2023 - License CC3