Επιστροφή συναρτήσεων

Είναι δυνατό να επιστρέψετε συναρτήσεις ως τιμή. Με αυτόν τον τρόπο μπορείτε να δομήσετε συναρτήσεις που κατασκευάζουν συναρτήσεις ειδικού σκοπού σύμφωνα με κάποιες παραμέτρους. Το ευαίσθητο κομμάτι είναι τι μεταβλητές βλέπει η συνάρτηση. Ο τρόπος που αυτό δουλεύει στο GEL είναι ότι όταν μια συνάρτηση επιστρέφει μια άλλη συνάρτηση, όλα τα αναγνωριστικά που αναφέρθηκαν στο σώμα της συνάρτησης που βγήκε εκτός εμβέλειας προτάσσουν ένα ιδιωτικό λεξικό της επιστρεφόμενης συνάρτησης. Έτσι η συνάρτηση θα δει όλες τις μεταβλητέςπου ήταν στην εμβέλεια όταν ορίστηκε. Για παράδειγμα, ορίζουμε μια συνάρτηση που επιστρέφει μια συνάρτηση που προσθέτει 5 στο όρισμά της.

function f() = (
  k = 5;
  `(x) = (x+k)
)

Σημειώστε ότι, η συνάρτηση προσθέτει τη k στη x. Μπορείτε να τη χρησιμοποιήσετε ως εξής.

g = f();
g(5)

Και η g(5) πρέπει να επιστρέψει 10.

Πρέπει να σημειώσετε ότι η τιμή της k που χρησιμοποιείται είναι αυτή που επιστρέφεται στην πραγματικότητα από την f. Για παράδειγμα: το

function f() = (
  k := 5;
  function r(x) = (x+k);
  k := 10;
  r
)

θα επιστρέψει μια συνάρτηση που προσθέτει 10 στο όρισμά της αντί για 5. Αυτό συμβαίνει επειδή το πρόσθετο λεξικό δημιουργείται μόνο όταν το περιεχόμενο στο οποίο η συνάρτηση ορίστηκε τελειώνει, που συμβαίνει όταν η συνάρτηση f επιστρέφεται. Αυτό είναι συνεπές με το πώς θα περιμένατε η συνάρτηση r να δουλέψει μέσα στη συνάρτηση f σύμφωνα με τους κανόνες εμβέλειας των μεταβλητών στη GEL. Μόνο αυτές οι μεταβλητές προστίθενται στο πρόσθετο λεξικό που είναι στο περιεχόμενο που μόλις τελείωσε και δεν υπάρχει πια. Οι χρησιμοποιούμενες μεταβλητές στη συνάρτηση που είναι ακόμα σε έγκυρα περιεχόμενα θα δουλέψουν ως συνήθως, χρησιμοποιώντας την τρέχουσα τιμή της μεταβλητής. Η μόνη διαφορά είναι με τις καθολικές μεταβλητές και συναρτήσεις. Όλα τα αναγνωριστικά που αναφέρθηκαν σε καθολικές μεταβλητές κατά τον ορισμό της συνάρτησης δεν προστίθενται στο ιδιωτικό λεξικό. Αυτό συμβαίνει για να αποφευχθεί πολλή περιττή εργασία κατά την επιστροφή συναρτήσεων και μπορεί σπάνια να είναι πρόβλημα. Για παράδειγμα, ας υποθέσουμε ότι διαγράφετε το "k=5" από τη συνάρτηση f και στο ανώτατο επίπεδο ορίζετε την k να είναι ας πούμε 5. Τότε όταν εκτελείτε τη f, η συνάρτηση r δεν θα βάλει την k στο ιδιωτικό λεξικό, επειδή είναι καθολική (ανωτάτου επιπέδου) τη στιγμή του ορισμού της r.

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

function f() = (
  k := 5;
  function r(x) [k] = (x+k);
  k := 10;
  r
)

θα επιστρέψει μια συνάρτηση που όταν καλείται θα προσθέσει 5 στο όρισμά του. Το τοπικό αντίγραφο της k δημιουργήθηκε όταν η συνάρτηση ορίστηκε.

Όταν θέλετε η συνάρτηση να μην έχει κανένα ιδιωτικό λεξικό, τότε βάλτε κενές αγκύλες μετά την λίστα ορισμάτων. Τότε κανένα ιδιωτικό λεξικό δεν θα δημιουργηθεί. Κάνοντας το αυξάνετε την αποτελεσματικότητα, όταν ένα προσωπικό λεξικό δεν χρειάζεται ή όταν θέλετε η συνάρτηση να αναζητήσει όλες τις μεταβλητές όπως τις βλέπει όταν καλούνται. Για παράδειγμα ας υποθέσουμε ότι θέλετε η επιστρεφόμενη συνάρτηση από την f να δει την τιμή της k από το ανώτατο επίπεδο παρά το ότι εκεί είναι μια τοπική μεταβλητή με το ίδιο όνομα κατά τη διάρκεια του ορισμού. Έτσι ο κώδικας

function f() = (
  k := 5;
  function r(x) [] = (x+k);
  r
);
k := 10;
g = f();
g(10)

θα επιστρέψει 20 και όχι 15, που θα συμβεί αν η k με μια τιμή 5 προστέθηκε στο ιδιωτικό λεξικό.