Διαδρομές
/
Factor
Factor
/
Ασκήσεις
/
Η Ταινία του Τηλεγραφητή
Η Ταινία του Τηλεγραφητή

Η Ταινία του Τηλεγραφητή

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

Εισαγωγή

Έχεις ήδη χρησιμοποιήσει ροές στο channel-chatter και τις έχεις αποδεσμεύσει στο boatswains-bilge. Αυτή η άσκηση είναι η πρώτη δική σου προσαρμοσμένη ροή: μια κλάση που υλοποιεί το πρωτόκολλο, ώστε ο ίδιος κώδικας with-input-stream / read1 / stream-read1 που δούλευε σε ένα <string-reader> να δουλεύει και στη δική σου.

Mixins: το άλλο μισό της ιεραρχίας κλάσεων

Ξέρεις ήδη το TUPLE: child < parent … από το dragons-descendants: μια ιεραρχία με έναν μόνο γονέα, όπου τα πεδία περνούν προς τα κάτω. Η Factor έχει και έναν δεύτερο τρόπο να επεκτείνεις το γράφημα κλάσεων: τα ανοιχτά mixins. Ένα MIXIN: m δηλώνει μια κλάση χωρίς πεδία, στην οποία άλλες κλάσεις μπορούν να ενταχθούν εκ των υστέρων με INSTANCE: c m. Η συμμετοχή είναι πολλά-προς-πολλά: μια κλάση μπορεί να είναι στιγμιότυπο όσων mixins θέλει.

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

INSTANCE: my-stream input-stream    ! readable
INSTANCE: my-stream output-stream   ! writable

Μια ροή μπορεί να είναι το ένα, το άλλο ή και τα δύο. Οι γενικές μέθοδοι στο input-stream (ή στο output-stream) απευθύνονται, λοιπόν, σε οποιαδήποτε κλάση έχει ενταχθεί στο mixin: έτσι βρίσκουν τον δρόμο τους προς την κλάση σου τα read1, stream-contents, with-input-stream κ.λπ.

Τα mixins είναι ανοιχτά: μπορείς να προσθέσεις ένα νέο μέλος αφού δηλωθεί το mixin, ακόμη και σε διαφορετικό λεξιλόγιο. Αυτή είναι η διαφορά με το TUPLE: < parent, όπου η σχέση καθορίζεται όταν δηλώνεται η κλάση-παιδί.

Οι γενικές μέθοδοι του πρωτοκόλλου

Οι γενικές μέθοδοι του πρωτοκόλλου βρίσκονται στο io:

stream-read1         ( stream -- elt/f )
stream-read          ( n stream -- seq/f )
stream-read-unsafe   ( n buf stream -- count )
stream-write1        ( elt stream -- )
stream-write         ( seq stream -- )
stream-flush         ( stream -- )
stream-element-type  ( stream -- type )

Το stream-read1 επιστρέφει το επόμενο byte (ή f στο τέλος της ροής). Το stream-write1 γράφει ένα. Το stream-read-unsafe είναι η μαζική ανάγνωση χαμηλότερου επιπέδου που παρέχουν οι περισσότερες ροές εισόδου· το stream-read χτίζεται πάνω της και αναλαμβάνει τη δέσμευση μνήμης. Το stream-element-type λέει αν η ροή δουλεύει με bytes (+byte+) ή με χαρακτήρες (+character+). Όταν τυλίγεις μια άλλη ροή, η απλούστερη υλοποίηση αναθέτει απλώς στην υποκείμενη ροή.

Ο καθαρισμός προέρχεται από το destructors

Οι ροές είναι disposables: μια προσαρμοσμένη ροή επεκτείνει το disposable και υλοποιεί το dispose*. Αυτό είναι το framework από το boatswains-bilge, εφαρμοσμένο σε μια κλάση ροής:

TUPLE: my-stream < disposable underlying ;

: <my-stream> ( underlying -- s )
    my-stream new-disposable swap >>underlying ;

M: my-stream dispose* underlying>> dispose ;

Μόλις μπει αυτό στη θέση του, όλοι οι συνδυαστές with-… από το channel-chatter δουλεύουν αυτόματα στη ροή σου.

Οδηγίες

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

Η δουλειά σου είναι να φτιάξεις την ταινία ως προσαρμοσμένη ροή εισόδου Factor.

1. Όρισε την ταινία

Όρισε μια πλειάδα tape που επεκτείνει το disposable και κρατά μία υποδοχή, wire, για την υποκείμενη ροή εισόδου.

TUPLE: tape < disposable wire ;

Έπειτα γράψε τον κατασκευαστή <tape> ( wire -- tape ). Χρησιμοποίησε το new-disposable (όχι το new) ώστε το framework καταστροφέων να καταχωρίσει την ταινία, και αποθήκευσε την υποκείμενη ροή στην υποδοχή wire.

2. Ενσωμάτωσε το mixin input-stream

Δήλωσε το tape ως input-stream:

INSTANCE: tape input-stream

Αυτό κάνει τους προεπιλεγμένους συνδυαστές του πρωτοκόλλου να κατευθύνονται στην κλάση σου.

3. Διάβασε ένα σύμβολο Μορς

Υλοποίησε το M: tape stream-read1 ( tape -- elt/f ). Διάβασε bytes από το υποκείμενο καλώδιο μέχρι να συναντήσεις ένα από τα CHAR: ., CHAR: - ή CHAR: \s (κενό). Επίστρεψε αυτό το byte. Αν το καλώδιο επιστρέψει f (τέλος ροής), επίστρεψε και f. Η ταινία τελείωσε.

"x.y -ab cz" <string-reader> <tape>
[ stream-read1 ] [ stream-read1 ] [ stream-read1 ] tri
! => CHAR: . CHAR: - CHAR: \s

4. Ανάθεσε τον τύπο στοιχείου

Υλοποίησε το M: tape stream-element-type ( tape -- type ) αναθέτοντας στο καλώδιο. Η ταινία δεν αλλάζει το είδος των στοιχείων που διαβάζονται.

5. Καθάρισε

Υλοποίησε το M: tape dispose* ( tape -- ). Το framework καλεί τη μέθοδό σου ακριβώς μία φορά ανά dispose. Απλώς κάνε dispose στο υποκείμενο καλώδιο.

Με αυτά τα πέντε κομμάτια στη θέση τους, η ταινία λειτουργεί ως κανονική ροή εισόδου. Τα with-input-stream, stream-read και οι άλλες λέξεις του πρωτοκόλλου δρομολογούνται αυτόματα στις μεθόδους σου.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Factor Exercism

Έτοιμος να ξεκινήσεις την άσκηση Η Ταινία του Τηλεγραφητή;

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