Elixir 1.7 - Basic types

मूल प्रकार




elixir

मूल प्रकार

इस अध्याय में हम अमृत मूल प्रकारों के बारे में अधिक जानेंगे: पूर्णांक, फ्लोट, बुलियन, परमाणु, स्ट्रिंग्स, सूचियाँ और टुपल्स। कुछ बुनियादी प्रकार हैं:

iex> 1          # integer
iex> 0x1F       # integer
iex> 1.0        # float
iex> true       # boolean
iex> :atom      # atom / symbol
iex> "elixir"   # string
iex> [1, 2, 3]  # list
iex> {1, 2, 3}  # tuple

मूल अंकगणित

iex खोलें और निम्न अभिव्यक्तियाँ लिखें:

iex> 1 + 2
3
iex> 5 * 5
25
iex> 10 / 2
5.0

ध्यान दें कि 10/2 ने पूर्णांक 5 बजाय एक फ्लोट 5.0 लौटाया। यह अपेक्षित है। अमृत ​​में, ऑपरेटर / हमेशा एक फ्लोट लौटाता है। यदि आप पूर्णांक विभाजन करना चाहते हैं या विभाजन प्राप्त करना चाहते हैं, तो आप div को आमंत्रित कर सकते हैं और फ़ंक्शन को rem हैं:

iex> div(10, 2)
5
iex> div 10, 2
5
iex> rem 10, 3
1

ध्यान दें कि नामित कार्यों को लागू करते समय अमृत आपको कोष्ठकों को छोड़ने की अनुमति देता है। घोषणाओं और नियंत्रण-प्रवाह निर्माणों को लिखते समय यह सुविधा एक क्लीनर सिंटैक्स देती है।

अमृत ​​बाइनरी, ऑक्टल और हेक्साडेसिमल संख्याओं को दर्ज करने के शॉर्टकट शॉर्टकट्स का भी समर्थन करता है:

iex> 0b1010
10
iex> 0o777
511
iex> 0x1F
31

फ्लोट नंबरों के लिए कम से कम एक अंक के बाद एक डॉट की आवश्यकता होती है और वैज्ञानिक संकेतन के लिए e भी समर्थन करता है:

iex> 1.0
1.0
iex> 1.0e-10
1.0e-10

एलिक्जिर में फ़्लोट्स 64-बिट डबल परिशुद्धता हैं।

आप किसी दिए गए फ्लोट के निकटतम पूर्णांक को प्राप्त करने के लिए round फ़ंक्शन को आमंत्रित कर सकते हैं, या किसी फ्लोट के पूर्णांक भाग को प्राप्त करने के लिए trunc फ़ंक्शन कर सकते हैं।

iex> round(3.58)
4
iex> trunc(3.58)
3

कार्यों की पहचान

अमृत ​​में कार्यों की पहचान उनके नाम और उनके गुण दोनों से की जाती है। किसी फ़ंक्शन की समता, फ़ंक्शन द्वारा ली जाने वाली तर्कों की संख्या का वर्णन करती है। इस बिंदु पर हम पूरे प्रलेखन में फ़ंक्शन का वर्णन करने के लिए फ़ंक्शन नाम और उसकी समता दोनों का उपयोग करेंगे। round/1 उस फंक्शन की पहचान करता है जिसे round नाम दिया round और 1 तर्क लेता है, जबकि round/2 एक अलग (नोक्सेन्सेन्ट) फंक्शन की पहचान उसी नाम से करता है लेकिन 2 की एक एरिटी के साथ।

बूलियन्स

बुलिश के रूप में अमृत true और false का समर्थन करता true :

iex> true
true
iex> true == false
false

अमृत ​​एक मूल्य प्रकार की जांच करने के लिए विधेय कार्यों का एक गुच्छा प्रदान करता है। उदाहरण के लिए, is_boolean/1 फ़ंक्शन का उपयोग यह जांचने के लिए किया जा सकता है कि मूल्य एक बूलियन है या नहीं:

iex> is_boolean(true)
true
iex> is_boolean(1)
false

यदि आप एक तर्क पूर्णांक, एक फ्लोट, या तो या तो क्रमशः जांचने के लिए is_integer/1 , is_float/1 या is_number/1 का उपयोग कर सकते हैं।

नोट: किसी भी क्षण आप शेल का उपयोग करने के तरीके के बारे में जानकारी प्रिंट करने के लिए शेल में h() टाइप कर सकते हैं। h हेल्पर का उपयोग किसी भी फ़ंक्शन के लिए प्रलेखन तक पहुंचने के लिए भी किया जा सकता है। उदाहरण के लिए, टाइपिंग h is_integer/1 is_integer/1 फ़ंक्शन के लिए दस्तावेज़ मुद्रित करने जा रहा है। यह ऑपरेटरों और अन्य निर्माणों के साथ भी काम करता है ( h ==/2 आज़माएं)।

परमाणुओं

एक परमाणु एक स्थिर है जिसका नाम स्वयं का मूल्य है। कुछ अन्य भाषाओं में ये प्रतीक हैं:

iex> :hello
:hello
iex> :hello == :world
false

true और false बुलियन वास्तव में, परमाणु हैं:

iex> true == :true
true
iex> is_atom(false)
true
iex> is_boolean(:false)
true

अंत में, एलिक्जिर में एलियास नामक एक निर्माण होता है जिसे हम बाद में देखेंगे। उपनाम ऊपरी मामले में शुरू होते हैं और परमाणु भी होते हैं:

iex> is_atom(Hello)
true

स्ट्रिंग्स

एलिक्जिर में स्ट्रिंग्स को डबल कोट्स द्वारा सीमांकित किया गया है, और वे UTF-8 में एन्कोडेड हैं:

iex> "hellö"
"hellö"

नोट: यदि आप विंडोज पर चल रहे हैं, तो एक मौका है कि आपका टर्मिनल डिफ़ॉल्ट रूप से UTF-8 का उपयोग नहीं करता है। IEx में प्रवेश करने से पहले आप chcp 65001 चलाकर अपने वर्तमान सत्र के एन्कोडिंग को बदल सकते हैं।

अमृत ​​भी स्ट्रिंग प्रक्षेप का समर्थन करता है:

iex> "hellö #{:world}"
"hellö world"

स्ट्रिंग्स में लाइन ब्रेक हो सकते हैं। आप एस्केप सीक्वेंस का उपयोग करके उनका परिचय दे सकते हैं:

iex> "hello
...> world"
"hello\nworld"
iex> "hello\nworld"
"hello\nworld"

आप IO मॉड्यूल से IO.puts/1 फ़ंक्शन का उपयोग करके एक स्ट्रिंग प्रिंट कर सकते हैं:

iex> IO.puts "hello\nworld"
hello
world
:ok

ध्यान दें कि IO.puts/1 फ़ंक्शन परमाणु को वापस लौटाता है :ok मुद्रण के बाद :ok

Elixir में स्ट्रिंग्स को बायनेरिज़ द्वारा आंतरिक रूप से दर्शाया जाता है जो बाइट्स के अनुक्रम होते हैं:

iex> is_binary("hellö")
true

हम एक स्ट्रिंग में बाइट्स की संख्या भी प्राप्त कर सकते हैं:

iex> byte_size("hellö")
6

ध्यान दें कि उस स्ट्रिंग में बाइट्स की संख्या 6 है, भले ही उसमें 5 अक्षर हों। ऐसा इसलिए क्योंकि “ö” वर्ण यूटीएफ -8 में प्रतिनिधित्व करने के लिए 2 बाइट लेता है। String.length/1 फ़ंक्शन का उपयोग करके, हम वर्णों की संख्या के आधार पर स्ट्रिंग की वास्तविक लंबाई प्राप्त कर सकते हैं:

iex> String.length("hellö")
5

स्ट्रिंग मॉड्यूल में फ़ंक्शंस का एक समूह होता है जो यूनिकोड मानक में परिभाषित स्ट्रिंग्स पर काम करता है:

iex> String.upcase("hellö")
"HELLÖ"

अनाम कार्य

बेनामी कार्यों को इनलाइन बनाया जा सकता है और कीवर्ड fn और end द्वारा सीमांकित किया जाता है:

iex> add = fn a, b -> a + b end
#Function<12.71889879/2 in :erl_eval.expr/5>
iex> add.(1, 2)
3
iex> is_function(add)
true
iex> is_function(add, 2) # check if add is a function that expects exactly 2 arguments
true
iex> is_function(add, 1) # check if add is a function that expects exactly 1 argument
false

अमृत ​​में "प्रथम श्रेणी के नागरिक" कार्य हैं, जिसका अर्थ है कि उन्हें पूर्णांकों और तारों के समान अन्य कार्यों के लिए तर्क के रूप में पारित किया जा सकता है। उदाहरण में, हमने फ़ंक्शन को वैरिएबल add में is_function/1 फ़ंक्शन में पास किया है जो सही ढंग से सही लौटा true । हम is_function/2 को कॉल करके फ़ंक्शन की समता की भी जांच कर सकते हैं।

ध्यान दें कि एक अनाम फ़ंक्शन को लागू करने के लिए चर और कोष्ठक के बीच एक डॉट () की आवश्यकता होती है। डॉट यह सुनिश्चित करता है कि किसी अनाम फ़ंक्शन को add और नामांकित फ़ंक्शन add/2 नाम के बीच कोई अस्पष्टता न हो। इस अर्थ में, अमृत अनाम कार्यों और नामित कार्यों के बीच एक स्पष्ट अंतर बनाता है। हम अध्याय 8 में उन अंतरों का पता लगाएंगे।

अनाम फ़ंक्शंस क्लोजर हैं और जैसे कि वे फ़ंक्शन को परिभाषित करते समय कार्यक्षेत्र में हैं चर का उपयोग कर सकते हैं। आइए एक नए अनाम फ़ंक्शन को परिभाषित करें जो हमारे द्वारा पहले परिभाषित किए गए अनाम फ़ंक्शन का उपयोग करता है:

iex> double = fn a -> add.(a, a) end
#Function<6.71889879/1 in :erl_eval.expr/5>
iex> double.(2)
4

ध्यान रखें कि किसी फंक्शन के अंदर दिया गया वैरिएबल उसके आसपास के वातावरण को प्रभावित नहीं करता है:

iex> x = 42
42
iex> (fn -> x = 0 end).()
0
iex> x
42

(लिंक किया गया) सूची

मूल्यों की सूची निर्दिष्ट करने के लिए अमृत वर्ग कोष्ठक का उपयोग करता है। मान किसी भी प्रकार के हो सकते हैं:

iex> [1, 2, true, 3]
[1, 2, true, 3]
iex> length [1, 2, 3]
3

दो सूचियों को क्रमशः ++/2 और --/2 ऑपरेटरों का उपयोग करके संक्षिप्त या घटाया जा सकता है:

iex> [1, 2, 3] ++ [4, 5, 6]
[1, 2, 3, 4, 5, 6]
iex> [1, true, 2, false, 3, true] -- [true, false]
[1, 2, 3, true]

सूची ऑपरेटर मौजूदा सूची को कभी भी संशोधित नहीं करते हैं। सूची से तत्वों को हटाने या हटाने से एक नई सूची लौट आती है। हम कहते हैं कि अमृत डेटा संरचनाएं अपरिवर्तनीय हैं । अपरिवर्तनीयता का एक लाभ यह है कि यह स्पष्ट कोड की ओर जाता है। आप स्वतंत्र रूप से डेटा को गारंटी के साथ पास कर सकते हैं कोई भी इसे बदल नहीं देगा - केवल इसे बदल देगा।

पूरे ट्यूटोरियल में, हम एक सूची के प्रमुख और पूंछ के बारे में बहुत सारी बातें करेंगे। सिर सूची का पहला तत्व है और पूंछ सूची का शेष भाग है। उन्हें फ़ंक्शन hd/1 और tl/1 साथ पुनः प्राप्त किया जा सकता है। चलो एक चर को एक सूची प्रदान करते हैं और उसके सिर और पूंछ को पुनः प्राप्त करते हैं:

iex> list = [1, 2, 3]
iex> hd(list)
1
iex> tl(list)
[2, 3]

एक खाली सूची का सिर या पूंछ प्राप्त करना एक त्रुटि फेंकता है:

iex> hd []
** (ArgumentError) argument error

कभी-कभी आप एक सूची बनाएंगे और यह एकल उद्धरणों में एक मूल्य लौटाएगा। उदाहरण के लिए:

iex> [11, 12, 13]
'\v\f\r'
iex> [104, 101, 108, 108, 111]
'hello'

जब अमृत प्रिंट करने योग्य ASCII नंबरों की एक सूची देखता है, तो अमृत एक चारलिस्ट के रूप में प्रिंट करेगा (शाब्दिक रूप से वर्णों की एक सूची)। मौजूदा Erlang कोड के साथ इंटरफेस करते समय Charlists काफी सामान्य हैं। जब भी आपको IEx में कोई मान दिखाई देता है और आप निश्चित नहीं हैं कि यह क्या है, तो आप इसके बारे में पुनः प्राप्त करने के लिए i/1 का उपयोग कर सकते हैं:

iex> i 'hello'
Term
  'hello'
Data type
  List
Description
  ...
Raw representation
  [104, 101, 108, 108, 111]
Reference modules
  List
Implemented protocols
  ...

ध्यान रखें कि एकल-उद्धृत और दोहरे-उद्धृत अभ्यावेदन अमृत के समान नहीं हैं क्योंकि वे विभिन्न प्रकारों द्वारा दर्शाए जाते हैं:

iex> 'hello' == "hello"
false

सिंगल कोट्स चार्लिस्ट हैं, डबल कोट्स स्ट्रिंग्स हैं। हम उनके बारे में अधिक बात करेंगे "बायनेरिज़, स्ट्रिंग्स एंड चार्लिस्ट्स" अध्याय में।

tuples

अमृत ​​टुपल्स को परिभाषित करने के लिए घुंघराले कोष्ठक का उपयोग करता है। सूचियों की तरह, टुपल्स किसी भी मूल्य को पकड़ सकते हैं:

iex> {:ok, "hello"}
{:ok, "hello"}
iex> tuple_size {:ok, "hello"}
2

Tuples स्मृति में संक्रामक रूप से तत्वों को संग्रहीत करते हैं। इसका मतलब है कि इंडेक्स द्वारा ट्यूपल तत्व को एक्सेस करना या ट्यूपल का आकार प्राप्त करना एक तेज़ ऑपरेशन है। सूचकांक शून्य से शुरू होते हैं:

iex> tuple = {:ok, "hello"}
{:ok, "hello"}
iex> elem(tuple, 1)
"hello"
iex> tuple_size(tuple)
2

यह भी संभव है कि किसी विशेष इंडेक्स पर एक तत्व को put_elem/3 :

iex> tuple = {:ok, "hello"}
{:ok, "hello"}
iex> put_elem(tuple, 1, "world")
{:ok, "world"}
iex> tuple
{:ok, "hello"}

ध्यान दें कि put_elem/3 ने नया टपल लौटाया। tuple चर में संग्रहीत मूल टुपल को संशोधित नहीं किया गया था। सूचियों की तरह, टुपल्स भी अपरिवर्तनीय हैं। टूपल पर प्रत्येक ऑपरेशन एक नया टपल देता है, यह दिए गए को कभी नहीं बदलता है।

सूचियाँ या टुपल्स?

सूचियों और टुपल्स के बीच अंतर क्या है?

सूचियों को लिस्टेड लिस्ट के रूप में मेमोरी में स्टोर किया जाता है, जिसका अर्थ है कि लिस्ट में प्रत्येक तत्व अपनी वैल्यू रखता है और लिस्ट के अंत तक पहुंचने तक निम्नलिखित एलिमेंट की ओर इशारा करता है। इसका मतलब है कि किसी सूची की लंबाई तक पहुंचना एक रैखिक ऑपरेशन है: इसके आकार का पता लगाने के लिए हमें पूरी सूची को पार करना होगा।

इसी तरह, सूची के प्रदर्शन का प्रदर्शन बाएं हाथ की सूची की लंबाई पर निर्भर करता है:

iex> list = [1, 2, 3]

# This is fast as we only need to traverse `[0]` to prepend to `list`
iex> [0] ++ list
[0, 1, 2, 3]

# This is slow as we need to traverse `list` to append 4
iex> list ++ [4]
[1, 2, 3, 4]

दूसरी ओर, टुपल्स को स्मृति में आकस्मिक रूप से संग्रहीत किया जाता है। इसका मतलब है कि टपल का आकार प्राप्त करना या सूचकांक द्वारा किसी तत्व तक पहुंचना तेज है। हालांकि, टुपल्स में तत्वों को अपडेट करना या जोड़ना महंगा है क्योंकि इसके लिए मेमोरी में नया टपल बनाने की आवश्यकता होती है:

iex> tuple = {:a, :b, :c, :d}
iex> put_elem(tuple, 2, :e)
{:a, :b, :e, :d}

ध्यान दें कि यह केवल टपल पर ही लागू होता है, इसकी सामग्री पर नहीं। उदाहरण के लिए, जब आप एक ट्यूपल को अपडेट करते हैं, तो पुरानी और नई ट्यूपल के बीच सभी प्रविष्टियां साझा की जाती हैं, केवल उस प्रविष्टि को छोड़कर जो बदल गई है। दूसरे शब्दों में, अमृत में ट्यूपल्स और सूचियां अपनी सामग्री साझा करने में सक्षम हैं। यह स्मृति आवंटन की मात्रा को कम करता है जिसे भाषा को प्रदर्शन करने की आवश्यकता होती है और यह केवल भाषा के अपरिवर्तनीय शब्दार्थ के लिए संभव है।

वे प्रदर्शन विशेषताएँ उन डेटा संरचनाओं के उपयोग को निर्धारित करती हैं। ट्यूपल्स के लिए एक बहुत ही सामान्य उपयोग मामला है उन्हें एक फ़ंक्शन से अतिरिक्त जानकारी वापस करने के लिए उपयोग करना है। उदाहरण के लिए, File.read/1 एक फ़ंक्शन है जिसका उपयोग फ़ाइल सामग्री को पढ़ने के लिए किया जा सकता है। यह एक वापसी देता है:

iex> File.read("path/to/existing/file")
{:ok, "... contents ..."}
iex> File.read("path/to/unknown/file")
{:error, :enoent}

यदि File.read/1 दिया गया पथ मौजूद है, तो यह परमाणु के साथ एक ट्यूपल लौटाता है :ok पहले तत्व के रूप में :ok और दूसरा के रूप में फ़ाइल सामग्री। अन्यथा, यह एक टपल लौटाता है :error और त्रुटि विवरण।

ज्यादातर समय, अमृत आपको सही काम करने के लिए मार्गदर्शन करने वाला है। उदाहरण के लिए, एक ट्यूल आइटम तक पहुंचने के लिए एक elem/2 फ़ंक्शन है लेकिन सूचियों के लिए कोई बिल्ट-इन समकक्ष नहीं है:

iex> tuple = {:ok, "hello"}
{:ok, "hello"}
iex> elem(tuple, 1)
"hello"

डेटा संरचना में तत्वों की गिनती करते समय, अमृत भी एक सरल नियम का पालन करता है: यदि कार्य निरंतर समय में होता है, तो फ़ंक्शन का नाम size यदि मान पूर्व-परिकलित है) या length यदि ऑपरेशन रैखिक है (यानी लंबाई की गणना कर रहा है) इनपुट बढ़ने के साथ धीमी हो जाती है)। एक महामारी के रूप में, "लंबाई" और "रैखिक" दोनों "एल" से शुरू होते हैं।

उदाहरण के लिए, हमने अब तक 4 गणना कार्यों का उपयोग किया है: byte_size/1 (एक स्ट्रिंग में बाइट्स की संख्या के लिए), tuple_size/1 (tuple आकार के लिए), length/1 (सूची की लंबाई के लिए) और String.length/1 एक स्ट्रिंग में अंगूर की संख्या के लिए)। हम एक सस्ते ऑपरेशन में बाइट की संख्या प्राप्त करने के लिए byte_size का उपयोग करते हैं। दूसरी ओर, यूनिकोड वर्णों की संख्या को पुनः प्राप्त करते String.length , String.length का उपयोग करता है, और यह महंगा हो सकता है क्योंकि यह पूरे स्ट्रिंग के ट्रैवर्सल पर निर्भर करता है।

अमृत ​​भी डेटा प्रकार (आमतौर पर प्रक्रिया संचार में उपयोग किया जाता है) के रूप में Port , Reference और PID प्रदान करता है, और हम प्रक्रियाओं के बारे में बात करते समय उन पर एक त्वरित नज़र डालेंगे। अभी के लिए, आइए कुछ बुनियादी ऑपरेटरों पर एक नज़र डालें जो हमारे बुनियादी प्रकारों के साथ चलते हैं।