Η Julia ενθαρρύνει τους προγραμματιστές να βάζουν όσο περισσότερο κώδικα γίνεται μέσα σε συναρτήσεις που μπορούν να μεταγλωττιστούν με JIT, και η δημιουργία πολλών μικρών συναρτήσεων είναι, εκ σχεδιασμού, αποδοτική.
Αυτό έχει την τάση να αφήνει πολλές μικρές, απλές συναρτήσεις, οι οποίες πρέπει να συνδυαστούν για να φέρουν εις πέρας μη τετριμμένες εργασίες.
Μια προφανής προσέγγιση είναι η εμφώλευση κλήσεων συναρτήσεων. Το παρακάτω παράδειγμα είναι πολύ επιτηδευμένο, αλλά δείχνει το σημείο.
julia> first.(titlecase.(reverse.(["my", "test", "strings"])))
3-element Vector{Char}:
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
Το μειονέκτημα αυτής της προσέγγισης είναι ότι η αναγνωσιμότητα πέφτει γρήγορα όσο βαθαίνει η εμφώλευση.
Χρειαζόμαστε μια απλούστερη και πιο ευέλικτη προσέγγιση.
Αυτή είναι η τεχνική που αγαπούν οι μαθηματικοί, και η Julia αντιγράφει τη μαθηματική σύνταξη.
Οποιοσδήποτε αριθμός συναρτήσεων μπορεί να composed μαζί με τελεστές ∘ (τους πληκτρολογείς ως \circ και μετά tab).
Το αποτέλεσμα μπορεί να χρησιμοποιηθεί ως μία μόνο συνάρτηση.
julia> compfunc = first ∘ titlecase ∘ reverse
first ∘ titlecase ∘ reverse
julia> compfunc.(["my", "test", "strings"])
3-element Vector{Char}:
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
# alternative syntax, giving the same result
julia> (first ∘ titlecase ∘ reverse).(["my", "test", "strings"])
Δύο σημεία που αξίζει να προσέξεις:
Μια εναλλακτική θα μπορούσε να θεωρηθεί η προσέγγιση των προγραμματιστών και όχι των μαθηματικών.
Οι Pipelines χρησιμοποιούνται εδώ και καιρό σε σενάρια κελύφους του Unix και πιο πρόσφατα έγιναν δημοφιλείς σε mainstream γλώσσες προγραμματισμού (στη F# αποδίδεται μερικές φορές η πρωτοπορία της υιοθέτησής τους).
Η βασική ιδέα είναι να ξεκινήσεις με κάποια δεδομένα και μετά να τα διοχετεύσεις μέσω μιας σειράς συναρτήσεων για να πάρεις το αποτέλεσμα.
Ο τελεστής διοχέτευσης είναι ο |> (όπως στη F# και σε πρόσφατες εκδόσεις της R), αν και η Julia έχει και μια έκδοση για broadcasting, τον .|>.
julia> ["my", "test", "strings"] .|> reverse .|> titlecase .|> first
3-element Vector{Char}:
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
Η εκτέλεση τώρα γίνεται αυστηρά από τα αριστερά προς τα δεξιά, με την έξοδο κάθε συνάρτησης να ρέει προς την κατεύθυνση του βέλους και να γίνεται η είσοδος για την επόμενη συνάρτηση.
Δεν είναι τυχαίο ότι οι συναρτήσεις που χρησιμοποιούνται για να δείξουν τη σύνθεση και τη διοχέτευση παίρνουν όλες ένα μόνο όρισμα.
Κάποιες καθαρά συναρτησιακές γλώσσες διοχετεύουν το πρώτο όρισμα σε μια συνάρτηση αλλά επιτρέπουν να συμπεριληφθούν και άλλα.
Αντίθετα, η Julia περιμένει μόνο ονόματα συναρτήσεων (ή κάτι ισοδύναμο) σε μια διοχέτευση, χωρίς πρόσθετα ορίσματα.
Υπάρχουν σημαντικοί τεχνικοί λόγοι γι' αυτό (που σχετίζονται με το γεγονός ότι το currying δεν αποτελεί στάνταρ μέρος του σχεδιασμού της γλώσσας).
Οι πολλοί άνθρωποι που δεν καταλαβαίνουν το currying θα πρέπει απλώς να δεχτούν ότι αυτός ο περιορισμός δεν είναι μια απρόσεκτη παράλειψη και δεν είναι πιθανό να αλλάξει σε μελλοντικές εκδόσεις της Julia.
Χρειαζόμαστε συναρτήσεις με ένα μόνο όρισμα που κάνουν ό,τι χρειάζεται. Ευτυχώς, ο ορισμός νέων συναρτήσεων στη Julia είναι εύκολος.
Πιο απλά, θα μπορούσαμε να χρησιμοποιήσουμε μια anonymous function.
Για παράδειγμα, αν έχουμε μία συμβολοσειρά εισόδου και θέλουμε να τη χωρίσουμε με βάση τις κάτω παύλες:
julia> "my_test_strings" |> (s -> split(s, '_'))
3-element Vector{SubString{String}}:
"my"
"test"
"strings"
Αυτό το διάνυσμα θα μπορούσε τότε να διοχετευτεί σε άλλες συναρτήσεις, όπως και πριν.
Η περικύκλωση της ανώνυμης συνάρτησης σε παρενθέσεις είναι προαιρετική σε αυτή την περίπτωση, αλλά γενικότερα αποτελεί έναν χρήσιμο τρόπο για να μειώσεις την ασάφεια.
Παρομοίως, θα μπορούσαμε να δημιουργήσουμε μια ονομασμένη συνάρτηση, νωρίτερα στο πρόγραμμα, και να την επαναχρησιμοποιήσουμε όποτε χρειάζεται.
Σε αυτή την άσκηση, θα βοηθήσεις ερωτευμένα ζευγάρια του λυκείου να διακηρύξουν τον έρωτά τους στα μέσα κοινωνικής δικτύωσης, δημιουργώντας μια καρδιά unicode με τα αρχικά τους:
❤ J. + M. ❤
Υλοποίησε τη μέθοδο cleanupname.
Θα πρέπει να παίρνει ένα όνομα και να αφαιρεί από αυτό όλους τους χαρακτήρες -, αντικαθιστώντας τους με ένα κενό.
Θα πρέπει επίσης να αφαιρεί τα κενά από την αρχή και το τέλος του ονόματος.
julia> cleanupname("Jane-Ann")
"Jane Ann"
Υλοποίησε τη μέθοδο firstletter.
Θα πρέπει να παίρνει ένα όνομα και να επιστρέφει το πρώτο του γράμμα ως συμβολοσειρά.
Φρόντισε να ξαναχρησιμοποιήσεις τη μέθοδο cleanupname που όρισες στο προηγούμενο βήμα και να τη συνθέσεις με άλλες συναρτήσεις.
julia> firstletter("Jane")
"J"
Υλοποίησε τη μέθοδο initial.
Θα πρέπει να παίρνει ένα όνομα και να επιστρέφει το πρώτο του γράμμα, κεφαλαίο, ακολουθούμενο από μια τελεία.
Φρόντισε να ξαναχρησιμοποιήσεις τη μέθοδο firstletter που όρισες στο προηγούμενο βήμα.
initial("Robert")
"R."
Υλοποίησε τη μέθοδο couple.
Θα πρέπει να παίρνει δύο ονόματα και να επιστρέφει τα αρχικά με emoji καρδιές γύρω τους.
Φρόντισε να ξαναχρησιμοποιήσεις τη μέθοδο initial που όρισες στο προηγούμενο βήμα.
couple("Blake Miller", "Riley Lewis")
"❤ B. + R. ❤"
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Julia με 35 έννοιες128 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.