Αυτό είναι ένα μεγάλο θέμα! Μπορείς κάλλιστα να γράψεις ένα ολόκληρο βιβλίο γι' αυτό, και αρκετοί το έχουν κάνει (ψάξε στο Amazon για "unicode book" για να δεις μερικά παραδείγματα).
Ο χειρισμός των χαρακτήρων στους υπολογιστές ήταν πολύ πιο απλός σε παλαιότερες δεκαετίες, τότε που οι προγραμματιστές θεωρούσαν ότι τα αγγλικά ήταν η μόνη σημαντική γλώσσα. Έτσι: 26 γράμματα, κεφαλαία και πεζά, 10 ψηφία, μερικά σημεία στίξης, συν ένας κωδικός (0x07) για να χτυπάει ένα κουδούνι, και όλα χωρούσαν σε 7 bits: το σύνολο χαρακτήρων ASCII.
Φυσικά, οι άνθρωποι άρχισαν να αναρωτιούνται τι γίνεται με τα à, ä και Ł, μετά άλλοι άρχισαν να ρωτούν για τα ऄ, ஹ και ญ, και οι νέοι ήθελαν emoji 😱. Τι να κάνουμε;
Για να μην τα πολυλογούμε, πολλοί έξυπνοι και υπομονετικοί άνθρωποι χρειάστηκε να συμμετάσχουν σε επιτροπές για χρόνια, επεξεργαζόμενοι τις λεπτομέρειες του συνόλου χαρακτήρων Unicode και κωδικοποιήσεων όπως το UTF-8, και πολλά προγράμματα χρειάστηκαν μια πολύ περίπλοκη επανεγγραφή. Επίσης, εισήχθησαν πολλά νέα bugs.
Για να μην καταρρεύσουν τα πάντα, ο σχεδιασμός των Unicode/UTF-8 διασφαλίζει ότι οι πρώτοι 127 κωδικοί είναι ίδιοι με του ASCII (ακόμα και το κουδούνι).
Οι γλώσσες που σχεδιάστηκαν μετά το 2005 περίπου έχουν το τεράστιο πλεονέκτημα ότι υπήρχε ήδη ένα αρκετά σταθερό πρότυπο Unicode.
Η Julia (κυκλοφόρησε για πρώτη φορά το 2012) μπόρεσε να υποθέσει ότι τα πάντα θα ήταν Unicode: χαρακτήρες, συμβολοσειρές, ονόματα μεταβλητών και συναρτήσεων, μαθηματικοί τελεστές...
Όπως λέει και το εγχειρίδιο, "Η Julia κάνει τον χειρισμό απλού κειμένου ASCII απλό και αποδοτικό, και ο χειρισμός του Unicode είναι τόσο απλός και αποδοτικός όσο γίνεται." Πρόσεξε το "όσο γίνεται", είναι σημαντικό μέρος της πρότασης.
Τα literals χαρακτήρων γράφονται με μονά εισαγωγικά και διαφέρουν από τις συμβολοσειρές, που γράφονται με διπλά εισαγωγικά.
Αυτό είναι προφανές για όσους προέρχονται από τον κόσμο της C/C++, αλλά μπορεί να μπερδέψει προγραμματιστές Python και Javascript.
julia> a = 'a' # Roman alphabet
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
julia> typeof(a)
Char
julia> jha = 'झ' # Devanagari alphabet
'झ': Unicode U+091D (category Lo: Letter, other)
julia> typeof(jha)
Char
julia> '❤' # heart emoji
'❤': Unicode U+2764 (category So: Symbol, other)
Βλέπουμε από τα παραδείγματα ότι ο τύπος είναι Char, και ότι η Julia έχει περισσότερες πληροφορίες για την κατηγορία του χαρακτήρα.
Κοιτάζοντας πιο προσεκτικά, φαίνεται ότι αυτοί οι χαρακτήρες μπορούν να αναπαρασταθούν με 4 δεκαεξαδικά ψηφία. Το πλήρες σύνολο χαρακτήρων χρειάζεται έως και 6 δεκαεξαδικά ψηφία.
Αυτοί οι αριθμοί ονομάζονται "σημεία κώδικα" και προς το παρόν κυμαίνονται από U+0000 έως U+10FFFF.
Εμφανίζονται στο REPL, αλλά μέσα στον κώδικα χρησιμοποίησε τη codepoints() για να τους πάρεις.
Η μετατροπή μεταξύ Char και Int είναι απλή:
julia> Int('a')
97
julia> Char(97)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
Ο μεταγλωττιστής επιτρέπει μερικές μορφές ακέραιης αριθμητικής σε Char:
julia> 'b' - 'a' # interval, in alphabetic order
1
julia> 'b' + 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)
julia> 'a' + 5
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)
julia> 'f' + ('A' - 'a') # same as `uppercase('f')`
'F': ASCII/Unicode U+0046 (category Lu: Letter, uppercase)
Ένα υποσύνολο από τις συναρτήσεις χειρισμού συμβολοσειρών μπορεί να λειτουργήσει και σε είσοδο Char.
uppercase() και lowercase().isuppercase() και islowercase().isletter(), καλύπτει πολλά αλφάβηταisdigit(), ελέγχει αυστηρά για 0:9isnumeric(), ευρύτερη από τη isdigit, οπότε δίνει true για το ¾ και για διάφορα μη ευρωπαϊκά συστήματα γραφήςisxdigit(), δεκαεξαδικά ψηφίαisascii(), χαρακτήρας προ-Unicodeispunct(), σημεία στίξηςisspace(), οποιοσδήποτε χαρακτήρας κενού διαστήματοςisprint(), εκτυπώσιμοι χαρακτήρες (το αντίθετο είναι η iscntrl())islowercase('A') # false
uppercase('γ') # 'Γ': Unicode U+0393 (category Lu: Letter, uppercase)
ispunct('@') # true
isdigit('A') # false
isxdigit('A') # true
Για να ελέγξεις αν ένας χαρακτήρας υπάρχει μέσα σε μια συμβολοσειρά, έχουμε το in.
Πρόσεξε ότι αυτό διαφέρει από τις υποσυμβολοσειρές:
# char search
julia> 'a' ∈ "xabcahliazlnkiw"
true
# substring search
julia> "a" ∈ "xabcahliazlnkiw"
use occursin(needle, haystack) for string containment
Επίσης, οι κανονικές εκφράσεις (θέμα άλλης Έννοιας) επιτρέπουν ισχυρή αναζήτηση και χειρισμό.
Για μετατροπή από String σε Char Vector, μπορούμε να χρησιμοποιήσουμε τη collect().
Για μετατροπή από Char Vector σε String, υπάρχει ο κατασκευαστής String().
julia> s = "abcde"
"abcde"
julia> cv = collect(s)
5-element Vector{Char}:
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)
julia> String(cv)
"abcde"
Αυτό λειτουργεί με οποιουσδήποτε χαρακτήρες, όχι μόνο με ASCII.
julia> collect("❤,😱")
3-element Vector{Char}:
'❤': Unicode U+2764 (category So: Symbol, other)
',': ASCII/Unicode U+002C (category Po: Punctuation, other)
'😱': Unicode U+1F631 (category So: Symbol, other)
Πρόσεξε ότι ο κατασκευαστής String() λειτουργεί πάνω σε ένα Vector.
Για να μετατρέψεις έναν μεμονωμένο Char σε συμβολοσειρά ενός χαρακτήρα, η συνάρτηση είναι η string(), με πεζό s.
julia> string('a')
"a"
Όλα όσα είδαμε μέχρι τώρα στο κείμενο φαίνονται σχετικά απλά, οπότε όντως δεν υπάρχει και πολύ πράγμα για να ανησυχείς;
Δυστυχώς, αυτό είναι υπερβολικά αισιόδοξο!
Μια δυσκολία προέρχεται από την ανάγκη για "έως και" 6 δεκαεξαδικά ψηφία ανά σημείο κώδικα. Αυτό σημαίνει ότι διαφορετικοί χαρακτήρες χρειάζονται διαφορετικό χώρο στη μνήμη όταν κωδικοποιούνται σε UTF-8.
Ένα byte μπορεί να αποθηκεύσει μόνο (μη προσημασμένους) αριθμούς έως το 255, δηλαδή δύο δεκαεξαδικά ψηφία, οπότε το UTF-8 χρησιμοποιεί μεταβλητό αριθμό byte (1 έως 4) για να αποθηκεύσει έναν Char.
Αυτά ονομάζονται "μονάδες κώδικα", και η συνάρτηση ncodeunits() επιστρέφει τον αριθμό που χρειάζεται για έναν δεδομένο χαρακτήρα.
julia> codepoint(jha) # jha 'झ' is defined in an earlier example
0x0000091d
julia> ncodeunits(jha)
3
julia> ncodeunits('a') # ASCII character
1
julia> ncodeunits('😱') # emoji
4
Επίσης, δεν έχουν όλα όσα μπορούν να εμφανιστούν στην οθόνη το δικό τους μοναδικό σημείο κώδικα. Κάποιοι οπτικά διακριτοί χαρακτήρες θεωρείται ότι προέρχονται από άλλους, οπότε το Unicode τους αντιμετωπίζει ως έναν γονικό χαρακτήρα συν έναν τροποποιητή.