Erlang 21 - 1. Records

1 रिकॉर्ड




erlang

1 रिकॉर्ड

1.1 रिकॉर्ड और ट्यूपल्स

ट्यूपल्स के बजाय रिकॉर्ड का उपयोग करने का मुख्य लाभ यह है कि रिकॉर्ड में फ़ील्ड नाम से एक्सेस किए जाते हैं, जबकि ट्यूपल में फ़ील्ड्स को स्थिति के अनुसार एक्सेस किया जाता है। इन अंतरों को स्पष्ट करने के लिए, मान लीजिए कि आप एक व्यक्ति को टपल {Name, Address, Phone} का प्रतिनिधित्व करना चाहते हैं।

इस डेटा में हेरफेर करने वाले कार्यों को लिखने के लिए, निम्नलिखित को याद रखें:

  • Name फ़ील्ड टपल का पहला तत्व है।
  • Address फ़ील्ड दूसरा तत्व है।
  • Phone फ़ील्ड तीसरा तत्व है।

उदाहरण के लिए, एक वैरिएबल P से डेटा निकालने के लिए जिसमें इस तरह का टपल होता है, आप निम्नलिखित कोड लिख सकते हैं और फिर संबंधित क्षेत्रों को निकालने के लिए पैटर्न मिलान का उपयोग कर सकते हैं:

Name = element(1, P),
Address = element(2, P),
...

इस तरह के कोड को पढ़ना और समझना मुश्किल है, और यदि टुपल में तत्वों की संख्या गलत है, तो त्रुटियां होती हैं। यदि फ़ील्ड्स के डेटा प्रतिनिधित्व को फिर से आदेश, फ़ील्ड्स को जोड़ने, या हटाने के द्वारा बदल दिया जाता है, तो व्यक्ति टपल के सभी संदर्भों की जाँच की जानी चाहिए और संभवतः उन्हें संशोधित किया जाना चाहिए।

रिकॉर्ड स्थिति के बजाय नाम से फ़ील्ड के संदर्भ की अनुमति देते हैं। निम्न उदाहरण में, डेटा को संग्रहीत करने के लिए एक टपल के बजाय एक रिकॉर्ड का उपयोग किया जाता है:

-record(person, {name, phone, address}).

यह रिकॉर्ड के क्षेत्रों को नाम से संदर्भित करने में सक्षम बनाता है। उदाहरण के लिए, यदि P एक वैरिएबल है जिसका मान एक person रिकॉर्ड है, तो निम्न कोड रिकॉर्ड के नाम और पते के क्षेत्रों तक पहुंचता है:

Name = P#person.name,
Address = P#person.address,
...

आंतरिक रूप से, रिकॉर्ड किए गए टुपल्स का उपयोग करते हुए रिकॉर्ड किए जाते हैं:

{person, Name, Phone, Address}

1.2 एक रिकॉर्ड को परिभाषित करना

किसी person की यह निम्नलिखित परिभाषा इस खंड में कई उदाहरणों में उपयोग की जाती है। तीन क्षेत्रों में शामिल हैं, name , phone और address name और phone लिए डिफ़ॉल्ट मान क्रमशः "" और [] है। address लिए डिफ़ॉल्ट मान परमाणु undefined , क्योंकि इस क्षेत्र के लिए कोई डिफ़ॉल्ट मान प्रदान नहीं किया गया है:

-record(person, {name = "", phone = [], address}).

उदाहरण में रिकॉर्ड सिंटैक्स का उपयोग सक्षम करने के लिए रिकॉर्ड को शेल में परिभाषित किया जाना चाहिए:

> rd(person, {name = "", phone = [], address}).
person

ऐसा इसलिए है क्योंकि रिकॉर्ड परिभाषाएँ केवल संकलन समय पर उपलब्ध हैं, रनटाइम पर नहीं। शेल में रिकॉर्ड के विवरण के लिए, STDLIB में shell(3) मैनुअल पेज देखें।

1.3 एक रिकॉर्ड बनाना

एक नया person रिकॉर्ड निम्नानुसार बनाया गया है:

> #person{phone=[0,8,2,3,4,3,1,2], name="Robert"}.
#person{name = "Robert",phone = [0,8,2,3,4,3,1,2],address = undefined}

जैसा कि address फ़ील्ड को छोड़ दिया गया था, इसका डिफ़ॉल्ट मान उपयोग किया जाता है।

Erlang 5.1 / OTP R8B से, विशेष फ़ील्ड _ साथ रिकॉर्ड में सभी फ़ील्ड का मान सेट किया जा सकता है। _ अर्थ है "सभी क्षेत्र स्पष्ट रूप से निर्दिष्ट नहीं हैं"।

उदाहरण:

> #person{name = "Jakob", _ = '_'}.
#person{name = "Jakob",phone = '_',address = '_'}

यह मुख्य रूप से ets:match/2 और mnesia:match_object/3 में उपयोग करने के लिए रिकॉर्ड किया जाता है, एटम '_' रिकॉर्ड फ़ील्ड सेट करने के लिए। (यह ईट में एक वाइल्डकार्ड है ets:match/2 )

1.4 एक रिकॉर्ड फ़ील्ड तक पहुँचना

निम्न उदाहरण दिखाता है कि रिकॉर्ड फ़ील्ड तक कैसे पहुँचें:

> P = #person{name = "Joe", phone = [0,8,2,3,4,3,1,2]}.
#person{name = "Joe",phone = [0,8,2,3,4,3,1,2],address = undefined}
> P#person.name.
"Joe"

1.5 एक रिकॉर्ड अपडेट करना

निम्न उदाहरण दिखाता है कि रिकॉर्ड को कैसे अपडेट किया जाए:

> P1 = #person{name="Joe", phone=[1,2,3], address="A street"}.
#person{name = "Joe",phone = [1,2,3],address = "A street"}
> P2 = P1#person{name="Robert"}.
#person{name = "Robert",phone = [1,2,3],address = "A street"}

1.6 प्रकार का परीक्षण

निम्न उदाहरण से पता चलता है कि P सफल होता है यदि P टाइप person का रिकॉर्ड है:

foo(P) when is_record(P, person) -> a_person;
foo(_) -> not_a_person.

1.7 पैटर्न मिलान

मिलान को रिकॉर्ड के साथ संयोजन में उपयोग किया जा सकता है, जैसा कि निम्नलिखित उदाहरण में दिखाया गया है:

> P3 = #person{name="Joe", phone=[0,0,7], address="A street"}.
#person{name = "Joe",phone = [0,0,7],address = "A street"}
> #person{name = Name} = P3, Name.
"Joe"

निम्नलिखित फ़ंक्शन person रिकॉर्ड की एक सूची लेता है और एक विशेष नाम वाले व्यक्ति के फोन नंबर की खोज करता है:

find_phone([#person{name=Name, phone=Phone} | _], Name) ->
    {found,  Phone};
find_phone([_| T], Name) ->
    find_phone(T, Name);
find_phone([], Name) ->
    not_found.

पैटर्न में निर्दिष्ट फ़ील्ड किसी भी क्रम में दिए जा सकते हैं।

1.8 नेस्टेड रिकॉर्ड

एक रिकॉर्ड में एक क्षेत्र का मूल्य एक रिकॉर्ड का एक उदाहरण हो सकता है। निम्न उदाहरण में दिखाए गए नेस्टेड डेटा की पुनर्प्राप्ति को स्टेपवाइज़ या एकल चरण में किया जा सकता है:

-record(name, {first = "Robert", last = "Ericsson"}).
-record(person, {name = #name{}, phone}).

demo() ->
  P = #person{name= #name{first="Robert",last="Virding"}, phone=123},
  First = (P#person.name)#name.first.

यहां, demo() "Robert" मूल्यांकन करता है।

1.9 एक लंबा उदाहरण

टिप्पणियाँ निम्नलिखित उदाहरण में अंतर्निहित हैं:

%% File: person.hrl

%%-----------------------------------------------------------
%% Data Type: person
%% where:
%%    name:  A string (default is undefined).
%%    age:   An integer (default is undefined).
%%    phone: A list of integers (default is []).
%%    dict:  A dictionary containing various information 
%%           about the person. 
%%           A {Key, Value} list (default is the empty list).
%%------------------------------------------------------------
-record(person, {name, age, phone = [], dict = []}).
-module(person).
-include("person.hrl").
-compile(export_all). % For test purposes only.

%% This creates an instance of a person.
%%   Note: The phone number is not supplied so the
%%         default value [] will be used.

make_hacker_without_phone(Name, Age) ->
   #person{name = Name, age = Age, 
           dict = [{computer_knowledge, excellent}, 
                   {drinks, coke}]}.

%% This demonstrates matching in arguments

print(#person{name = Name, age = Age,
              phone = Phone, dict = Dict}) ->
  io:format("Name: ~s, Age: ~w, Phone: ~w ~n" 
            "Dictionary: ~w.~n", [Name, Age, Phone, Dict]).

%% Demonstrates type testing, selector, updating.

birthday(P) when record(P, person) -> 
   P#person{age = P#person.age + 1}.

register_two_hackers() ->
   Hacker1 = make_hacker_without_phone("Joe", 29),
   OldHacker = birthday(Hacker1),
   % The central_register_server should have 
   % an interface function for this.
   central_register_server ! {register_person, Hacker1},
   central_register_server ! {register_person, 
             OldHacker#person{name = "Robert", 
                              phone = [0,8,3,2,4,5,3,1]}}.