Ruby Closure: Blocks, Διαδικασίες και Lambdas - Ποια είναι η διαφορά;

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

Αποκλεισμός

Τα μπλοκ μπορούν να ταυτοποιηθούν μέσω του do..end ή {..} και μπορούν να είναι τα επιχειρήματα όπως φαίνεται παρακάτω:

Κάθε μέθοδος στο Ruby μπορεί να πάρει ένα προαιρετικό μπλοκ ως μη έγκυρη παράμετρο, όπως στο παρακάτω παράδειγμα:

Τι σημαίνει αυτό στο παραπάνω παράδειγμα, αλλάζουμε τη μέθοδο χαιρετισμού και χρειαζόμαστε να χρησιμοποιήσουμε τη λέξη-κλειδί της συγκομιδής για να ξεκινήσουμε το μπλοκ. Περάσαμε μια τοπική μεταβλητή (αναφερόμενη στη συμβολοσειρά "Ashley" που πέρασε τη μέθοδο χαιρετισμού ως όρισμα) για να δημιουργήσει το μπλοκ ως ένα όρισμα που μεταβιβάστηκε στο όνομα της παραμέτρου. Μέσα στο μπλοκ, "Hello # {name}!" Εγγράφεται. Τώρα ας δούμε τι συμβαίνει αν δεν αντιταχθούμε στο μπλοκ.

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

Procs

Υπάρχουν δύο τρόποι δημιουργίας ταμειακών μηχανών όπως φαίνεται παρακάτω:

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

Πρέπει να καλέσετε το αντικείμενο proc για να ενεργοποιήσετε το μπλοκ.

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

Το παρακάτω παράδειγμα δείχνει τι συμβαίνει αν δεν πάμε σε ένα ράλι.

Όταν καλείται η μέθοδος κλήσης στο αντικείμενο Proc proc1, δεν υποστηρίζουμε. Αυτό σημαίνει ότι δεν μεταβιβάζονται επιχειρήματα στο όνομα παραμέτρου του μπλοκ. Το ArgumentError δεν προβλήθηκε επειδή τα έργα μοιράστηκαν τους ίδιους κανόνες arity με τα μπλοκ και δεν έλαβαν υπόψη τον αριθμό των επιχειρημάτων. Όπως και τα μπλοκ, αν δεν έχει οριστεί καμία παράμετρος, το μηδέν εκχωρείται στο μηδέν. Γεια σας! είναι ο λόγος που έχουμε το αποτέλεσμα.

Lambdas

Εδώ είναι δύο τρόποι για να δημιουργήσετε lambdas.

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

Ένα πράγμα που πρέπει να σημειωθεί είναι ότι δεν μπορούμε να το κάνουμε αυτό για να δημιουργήσουμε ένα λάμδα:

Αυτό συμβαίνει επειδή οι lambdas δεν είναι αντικείμενα Lambda, είναι Proc αντικείμενα. Η κύρια διαφορά ανάμεσα στα πρίσματα και τα λάμδα είναι ότι έχουν διαφορετικούς κανόνες αρρυθμίας.

Δεδομένου ότι τα λάμδα είναι το αντικείμενο του Proc, μπορούμε να καλέσουμε τη μέθοδο επανάκλησης στο λάμβδα και το μπλοκ να εκτελεστεί. Στο πρώτο παράδειγμα παραπάνω, καλούμε τη μέθοδο επανάκλησης στο lambda1 και μεταβείτε στο όνομα παραμέτρου του μπλοκ και πείτε "Hello # {name}!" Ας πάρουμε το επιχείρημα Ashley. αποτελέσματα Hello Ashley! Στο δεύτερο παράδειγμα, το lambda1 καλείται χωρίς να καλέσει το όρισμα και το ArgumentError επιστρέφεται καθώς το μπλοκ λαμβάνει μία παράμετρο. Αυτό δείχνει ότι, αντίθετα με τις διαδικασίες και τα μπλοκ, οι lambdas κάνουν το όρισμα αρίθμησης.

Ένα τελευταίο πράγμα ...

Ένα άλλο πράγμα που θέτει τα μπλοκ, τους κυλίνδρους και τα αρνιά ξεχωριστά είναι το πώς λειτουργεί το κλειδί επιστροφής.

Αποκλεισμός

Όταν χρησιμοποιώ τον ακόλουθο κώδικα:

Έλαβα αυτό το μήνυμα σφάλματος:

επιστροφή μη αναμενόμενη (LocalJumpError)

Έτσι, όταν η μέθοδος μπλοκάρει τι συμβαίνει, η εκτέλεση του προγράμματος πηγαίνει από την εφαρμογή της μεθόδου στο μπλοκ. Γενικά, τα προγράμματα επιστρέφουν το LocalJumpError όταν έχουμε μια μέθοδο εφαρμογής, αλλά δεν παίρνουμε ποτέ ένα μπλοκ. Αυτό έχει ως αποτέλεσμα την εφαρμογή του προγράμματος από την εφαρμογή της μεθόδου σε ένα μπλοκ που δεν υπάρχει, οπότε εμφανίζεται ένα σφάλμα. Δεν υπήρχε εμπόδιο στο να περάσετε το σφάλμα LocalJumpError!

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

Procs

Όταν χρησιμοποιώ τον ακόλουθο κώδικα:

Δεν κάνω τα ίδια λάθη με το παράδειγμα μπλοκ. Μόλις ονομάσουμε το Pro και η λέξη "hello" αξιολογηθεί στο μπλοκ, το πρόγραμμα σταματά να τρέχει και το "hello" επιστρέφεται από τη μέθοδο proc_example. Σημειώστε ότι η τελευταία γραμμή της "καλής" μεθόδου δεν έχει αξιολογηθεί ποτέ. Αυτό συμβαίνει επειδή οι διαδικασίες επιστρέφουν από το ίδιο το μπλοκ και σταματούν την εκτέλεση της μεθόδου.

Lambdas

Όταν χρησιμοποιώ τον ακόλουθο κώδικα:

Η εφαρμογή του προγράμματος δεν σταμάτησε νωρίτερα από το χρονοδιάγραμμα. Όταν ονομάζεται Lambda1 και καλείται το μπλοκ, η εκτέλεση του προγράμματος δεν επιστρέφει από το μπλοκ όπως στην περίπτωση του διακομιστή μεσολάβησης. Αντ 'αυτού, το πρόγραμμα συνεχίζει να τρέχει και το "αντίο" επιστρέφεται με τη μέθοδο lambda_example. Έτσι, κατά την αξιολόγηση της λέξης κλειδιού επιστροφής σε ένα μπλοκ, το lambda αγνοεί τη λέξη κλειδί επιστροφής και το πρόγραμμα συνεχίζεται.

Το κλείσιμο του Ruby μπορεί να είναι δύσκολο και αν χάσετε τίποτα στα κλειστά μπλογκ μου, μπορείτε να είστε ελεύθεροι να τα μοιραστείτε!