यह एक बड़ा विषय है! इस पर एक लंबी किताब लिखी जा सकती है, और कई लोगों ने ऐसा किया भी है (कुछ उदाहरण देखने के लिए Amazon पर "unicode book" खोजिए)।
पहले के दशकों में कंप्यूटर में अक्षरों को संभालना कहीं ज़्यादा आसान था, जब प्रोग्रामर मानते थे कि अंग्रेज़ी ही एकमात्र महत्वपूर्ण भाषा है। तो यह था: 26 अक्षर, बड़े और छोटे रूपों में, 10 अंक, कुछ विराम चिह्न, और घंटी बजाने के लिए एक कोड (0x07)। यह सब 7 बिट में समा गया, और यही ASCII अक्षर समूह है।
स्वाभाविक रूप से, लोग पूछने लगे कि à, ä और Ł का क्या होगा, फिर दूसरे लोग ऄ, ஹ और ญ के बारे में पूछने लगे, और युवाओं को इमोजी 😱 चाहिए थे। अब क्या किया जाए?
लंबी कहानी को छोटा करने के लिए, बहुत से बुद्धिमान और धैर्यवान लोगों को वर्षों तक समितियों में काम करना पड़ा, जिसमें उन्होंने Unicode अक्षर समूह और UTF-8 जैसी एन्कोडिंग की बारीकियाँ तय कीं, और बहुत से सॉफ्टवेयर को बहुत जटिल तरीके से दोबारा लिखने की ज़रूरत पड़ी। साथ ही, बहुत सारे नए बग भी जुड़ गए।
सब कुछ टूटने से बचाने के लिए, Unicode/UTF-8 का डिज़ाइन यह सुनिश्चित करता है कि पहले 127 कोड ASCII के बिल्कुल समान हों (घंटी वाला कोड भी)।
लगभग 2005 के बाद बनी भाषाओं के पास यह बड़ा फायदा था कि तब तक एक काफी स्थिर Unicode मानक मौजूद था।
Julia (पहली बार 2012 में जारी) यह मान सकती थी कि सब कुछ Unicode ही होगा: अक्षर, स्ट्रिंग, वेरिएबल और फंक्शन के नाम, गणितीय ऑपरेटर...
मैनुअल के शब्दों में: "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
स्ट्रिंग से 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 उन्हें एक मूल अक्षर और एक मॉडिफायर के रूप में मानता है।
यह समस्या स्ट्रिंग पर असर डालती है, जहाँ यह इंडेक्स करने में कठिनाई पैदा करती है।
इस अभ्यास में आप कुछ उपयोगी रूटीन का एक छोटा सेट बनाएँगे, जो एक डेवलपर को इंडेंटिफायर के नाम साफ़ करने में मदद करेंगी।
इन 6 टास्क में आप धीरे-धीरे दो फंक्शन बनाएँगे: transform, जो एक-एक अक्षर बदलता है, और clean, जो पूरी स्ट्रिंग बदलता है।
एक मान्य इंडेंटिफायर में शून्य या उससे अधिक अक्षर, अंडरस्कोर, हाइफ़न, प्रश्नचिह्न और इमोजी हो सकते हैं।
अगर clean फंक्शन को खाली स्ट्रिंग दी जाए, तो खाली स्ट्रिंग ही लौटनी चाहिए।
transform फंक्शन बनाइए, जो हर हाइफ़न को अंडरस्कोर से बदल दे।
julia> transform('-')
"_"
सभी व्हाइटस्पेस अक्षर हटा दीजिए। इसमें शुरू और अंत का व्हाइटस्पेस भी शामिल है।
julia> transform(' ')
""
transform फंक्शन में बदलाव कीजिए ताकि वह केमलकेस को केबैब-केस में बदल दे।
julia> transform('D')
"-d"
transform फंक्शन में बदलाव कीजिए ताकि वह जो भी अक्षर संख्यात्मक हों, उन्हें छोड़ दे।
julia> transform('7')
""
transform फंक्शन में बदलाव कीजिए ताकि वह 'α' से 'ω' के बीच के सभी ग्रीक अक्षरों को बदल दे।
julia> transform('β')
"?"
clean फंक्शन बनाइए, जो ये सभी काम पूरी स्ट्रिंग पर लागू करे।
जो अक्षर इन नियमों से बाहर हैं, वे जैसे हैं वैसे ही रहने चाहिए।
julia> clean(" a2b Cd-ω😀 ")
"ab-cd_?😀"
Exercism पर साइन अप कीजिए और Julia को 35 कॉन्सेप्ट128 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।