यह एक बड़ा विषय है! इस पर एक लंबी किताब लिखी जा सकती है, और कई लोगों ने ऐसा किया है (कुछ उदाहरण देखने के लिए Amazon पर "unicode book" खोजिए)।
कंप्यूटर में अक्षरों को संभालना पहले के दशकों में बहुत आसान था, जब प्रोग्रामर मानते थे कि अंग्रेज़ी ही एकमात्र महत्वपूर्ण भाषा है। तो: 26 अक्षर, ऊपरी और निचला केस, 10 अंक, कई विराम चिह्न, साथ ही घंटी बजाने के लिए एक कोड (0x07), और यह सब 7 बिट्स में समा जाता था: ASCII अक्षर सेट।
स्वाभाविक रूप से, लोग पूछने लगे कि à, ä और Ł का क्या? फिर अन्य लोग ऄ, ஹ और ญ के बारे में पूछने लगे, और युवा लोग इमोजी 😱 चाहते थे। क्या करें?
लंबी कहानी को संक्षेप में कहें तो, कई बुद्धिमान और धैर्यवान लोगों को वर्षों तक समितियों में सेवा करनी पड़ी, Unicode अक्षर सेट और UTF-8 जैसे एन्कोडिंग के विवरण तैयार करने में, और बहुत सारे सॉफ़्टवेयर को बहुत जटिल पुनर्लेखन की आवश्यकता पड़ी। साथ ही, बहुत सारे नए बग आ गए।
सब कुछ टूटने से बचाने के लिए, Unicode/UTF-8 डिज़ाइन यह सुनिश्चित करता है कि पहले 127 कोड ASCII के समान हैं (घंटी भी)।
लगभग 2005 के बाद डिज़ाइन की गई भाषाओं को यह बड़ा लाभ है कि एक काफी स्थिर Unicode मानक पहले से मौजूद था।
Julia (पहली बार 2012 में रिलीज़) यह मान सकती थी कि सब कुछ Unicode होगा: अक्षर, स्ट्रिंग, वेरिएबल और फंक्शन के नाम, गणितीय ऑपरेटर...
manual के अनुसार, "Julia सामान्य ASCII टेक्स्ट को संभालना सरल और कुशल बनाती है, और Unicode को संभालना यथासंभव सरल और कुशल है।" ध्यान दें "यथासंभव" पर, यह कथन का महत्वपूर्ण हिस्सा है।
अक्षर लिटरल सिंगल कोट्स में लिखे जाते हैं, और डबल कोट्स में लिखी स्ट्रिंग से अलग होते हैं।
यह 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:9 के लिए जाँच करता हैisnumeric(), isdigit से अधिक व्यापक, इसलिए ¾ और विभिन्न गैर-यूरोपीय लिपियों के लिए true देता हैisxdigit(), हेक्साडेसिमल अंकisascii(), Unicode से पहले का अक्षरispunct(), विराम चिह्न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
साथ ही, रेगुलर एक्सप्रेशन (एक अन्य कॉन्सेप्ट का विषय) शक्तिशाली खोज और हेरफेर की अनुमति देते हैं।
स्ट्रिंग से Char वेक्टर के लिए, हम collect() का उपयोग कर सकते हैं।
Char वेक्टर से स्ट्रिंग के लिए, 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() कंस्ट्रक्टर एक वेक्टर पर काम करता है।
एक Char को 1-अक्षर वाली स्ट्रिंग में कास्ट करने के लिए, फंक्शन string() है, छोटे s के साथ।
julia> string('a')
"a"
अब तक इस दस्तावेज़ में सब कुछ अपेक्षाकृत सरल लगता है, तो क्या वाकई चिंता की कोई बात नहीं है? दुर्भाग्य से, यह बहुत आशावादी है!
एक जटिलता प्रति कोड पॉइंट "अधिकतम" 6 हेक्स अंकों की आवश्यकता से आती है। इसका मतलब है कि UTF-8 एन्कोड होने पर अलग-अलग अक्षरों को मेमोरी में अलग-अलग मात्रा में जगह चाहिए।
एक बाइट केवल 255 तक की (अहस्ताक्षरित) संख्याएँ संग्रहीत कर सकती है, यानी दो हेक्स अंक, इसलिए UTF-8 एक Char को संग्रहीत करने के लिए बाइटों की अलग-अलग संख्या (1 से 4) का उपयोग करता है।
इन्हें "कोड यूनिट" कहा जाता है, और 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 उन्हें एक मूल अक्षर और एक संशोधक के रूप में मानता है।