Διαδρομές
/
Swift
Swift
/
Ασκήσεις
/
Double-Null0111: Τα closures είναι για πάντα
Double-Null0111: Τα closures είναι για πάντα

Double-Null0111: Τα closures είναι για πάντα

Άσκηση εκμάθησης

Εισαγωγή

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

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

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

{ (a: Double, b: Double) -> Double in
  return (a + b) / 2.0
}

Αυτό ορίζει μια κλειστή έκφραση τύπου (Double, Double) -> Double, και μπορεί να εκτελεστεί με παρόμοιο τρόπο όπως μια συνάρτηση αυτού του τύπου, εφαρμόζοντάς την σε παραμέτρους του κατάλληλου τύπου:

{ (a: Double, b: Double) -> Double in
  return (a + b) / 2.0
}(10.0, 15.0)
// returns 12.5

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

let mean = { (a: Double, b: Double) -> Double in
  (a + b) / 2.0
}

mean(13.0, 100.0)
// returns 56.5

Όπως φαίνεται παραπάνω, οι κλειστές, όπως οι κανονικές συναρτήσεις, μπορούν να παραλείψουν τη λέξη-κλειδί return εάν το σώμα της κλειστής είναι μία μόνο έκφραση.

Τις περισσότερες φορές, οι κλειστές χρησιμοποιούνται με συναρτήσεις υψηλότερης τάξης, είτε περνώντας τις ως παραμέτρους είτε επιστρέφοντάς τις ως αποτελέσματα:

[11, 75, 3, 99, 53].contains(where: { (x: Int) -> Bool in x > 100 })
// returns false

["apple", "ball", "carrot"].sorted(by: { (s1: String, s2: String) -> Bool in s1.count < s2.count })
// returns ["ball", "apple", "carrot"]

func makeAdder(base: Int) -> (Int) -> Int {
  { (x: Int) -> Int in base + x }
}

Οδηγίες

Γεια σου και πάλι, Πράκτορα Double-Null0111.

Οι δυνάμεις της UMBRA ξαναχτυπούν, και εξαρτάται από εσένα να ματαιώσεις το τελευταίο τους σχέδιο. Η υπηρεσία πληροφοριών μας μάς ενημερώνει ότι αυτά τα Minions σχεδιάζουν να πυροδοτήσουν μια βομβίδα βρώμας στον χορό του Κυβερνήτη.

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

Η δουλειά σου είναι να γράψεις τον κώδικα που θα σου επιτρέψει να απενεργοποιήσεις τη βομβίδα βρώμας στον χορό πριν εκραγεί.

1. Γράψε ένα closure που αντιστρέφει δύο καλώδια

Κάθε βομβίδα βρώμας έχει τρία καλώδια με διαφορετικά χρώματα. Γράψε ένα closure που παίρνει μια πλειάδα (String, String, String) και επιστρέφει την πλειάδα με αντεστραμμένη τη σειρά των δύο πρώτων στοιχείων. Ανάθεσε αυτό το closure στο όνομα flip.

Είναι σημαντικό να σημειώσεις ότι ο τύπος πρέπει να είναι ο ChangeClosure (ή κάποιος sendable τύπος), ο ορισμός του τύπου δίνεται στο αρχείο stub. Διαφορετικά, ο κώδικας δεν θα μεταγλωττιστεί.

flip(("red", "yellow", "blue"))
// Returns ("yellow", "red", "blue")

2. Γράψε ένα closure που περιστρέφει τα καλώδια

Γράψε ένα closure που παίρνει μια πλειάδα (String, String, String) και επιστρέφει την πλειάδα με τη σειρά των καλωδίων περιστραμμένη προς τα αριστερά. Ανάθεσε αυτό το closure στο όνομα rotate.

Είναι σημαντικό να σημειώσεις ότι ο τύπος πρέπει να είναι ο ChangeClosure (ή κάποιος sendable τύπος), ο ορισμός του τύπου δίνεται στο αρχείο stub.

rotate(("red", "yellow", "blue"))
// Returns ("yellow", "blue", "red")

3. Υλοποίησε μια γεννήτρια ανακατέματος καλωδίων

Για να βρεις τη σειρά με την οποία πρέπει να κόψεις τα καλώδια της βομβίδας βρώμας, θα χρειαστεί να υλοποιήσεις μια συνάρτηση που παράγει τη σωστή συνάρτηση ανακατέματος με βάση τον αριθμό ID της βομβίδας βρώμας.

Υλοποίησε τη συνάρτηση:

makeShuffle(
  flipper: @escaping ((String, String, String)) -> (String, String, String),
  rotator: @escaping ((String, String, String)) -> (String, String, String)
) -> ([UInt8], (String, String, String)) -> (String, String, String)

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

Για κάθε bit του αριθμού ID, ξεκινώντας από το δεξιότερο bit, θα εφαρμόζεις το closure flipper στην πλειάδα των καλωδίων αν το bit είναι 0, και θα εφαρμόζεις το closure rotator αν είναι 1, δίνοντας τη νέα κατάσταση των καλωδίων. Αφού εφαρμοστούν τα κατάλληλα closures και για τα οκτώ bits του ID, η τελική κατάσταση των καλωδίων είναι η σειρά με την οποία πρέπει να κοπούν.

let shuffler = makeShuffle(flipper: flip, rotator: rotate)
// Returns ([UInt8], (String, String, String)) -> (String, String, String)
shuffler([1, 0, 0, 1, 1, 0, 1, 1], ("red", "yellow", "blue"))
// Returns ("red", "blue", "yellow")
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Swift Exercism

Έτοιμος να ξεκινήσεις την άσκηση Double-Null0111: Τα closures είναι για πάντα;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Swift με 35 έννοιες116 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.