रिकॉर्ड ऐसे डेटा स्ट्रक्चर होते हैं जो जुड़ी हुई जानकारी को लेबल के साथ एक साथ रखते हैं। ये JavaScript या Java के ऑब्जेक्ट, या C या Rust के structs जैसे होते हैं, लेकिन इनमें कुछ खास फर्क हैं।
रिकॉर्ड घुंघराले ब्रैकेट से बनाए जाते हैं और उनके एलिमेंट को कॉमा से अलग किया जाता है।
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
रिकॉर्ड का टाइप भी मिलते-जुलते सिंटैक्स से परिभाषित किया जाता है, बस बराबर के चिह्न = की जगह कोलन चिह्न : लगते हैं।
firefly : { name : String, creator : String, episodes : Int }
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
इन टाइप परिभाषाओं को बार-बार लिखना झंझट भरा है, इसलिए परिभाषा साझा करने के लिए टाइप एलियस का इस्तेमाल करना एक आम तरीका है।
type alias TvSeries =
{ name : String
, creator : String
, episodes : Int
}
firefly : TvSeries
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
टाइप एलियस रिकॉर्ड के लिए एक कंस्ट्रक्टर फंक्शन भी अपने आप बना देता है। यह कभी-कभी चौंकाने वाला लगता है, क्योंकि Elm में फंक्शन का नाम छोटे अक्षर से शुरू होना चाहिए। लेकिन टाइप कंस्ट्रक्टर इस नियम का एक अपवाद हैं।
firefly : TvSeries
firefly = TvSeries "Firefly" "Joss Whedon" 14
किसी रिकॉर्ड इंस्टेंस के फील्ड की वैल्यू पढ़ने का मुख्य तरीका डॉट नोटेशन है, जैसे firefly.creator।
Elm का कंपाइलर डॉट . से शुरू होने वाले खास एक्सेसर फंक्शन भी देता है, जैसे .creator, जो ऐसे किसी भी रिकॉर्ड पर काम करता है जिसमें उस नाम का फील्ड हो।
यह उस नियम का दूसरा अपवाद है कि फंक्शन का नाम छोटे अक्षर से ही शुरू होना चाहिए। वास्तव में, उपयोगकर्ता द्वारा बनाए गए फंक्शन का नाम छोटे अक्षर से शुरू होना चाहिए, लेकिन जिन दो उदाहरणों को हमने अभी देखा, उन्हें कंपाइलर बनाता है, प्रोग्रामर नहीं।
firefly : TvSeries
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
firefly.name
--> "Firefly"
.creator firefly
--> "Joss Whedon"
रिकॉर्ड को बाइंडिंग में रिकॉर्ड पैटर्न मैचिंग के ज़रिए डीस्ट्रक्चर भी किया जा सकता है। डीस्ट्रक्चरिंग किसी भी ऐसे रिकॉर्ड के साथ काम करती है जिसमें पैटर्न में लिखे नामों वाले फील्ड हों।
episodesCount : TvSeries -> Int
episodesCount { episodes } =
episodes
complicatedCopy : TvSeries -> TvSeries
complicatedCopy show =
let
{ name, creator } = show
in
{ name = name
, creator = creator
, episodes = episodesCount show
}
रिकॉर्ड अपरिवर्तनीय होते हैं, Elm में जैसे सब कुछ, इसलिए एक बार रिकॉर्ड परिभाषित हो जाने के बाद उसके फील्ड की वैल्यू कभी नहीं बदल सकती। किसी मौजूदा रिकॉर्ड की कॉपी बनाने, लेकिन उसके एक या अधिक फील्ड बदलने के लिए एक खास सिंटैक्स है। यह सिंटैक्स मूल रिकॉर्ड और बदलने वाले फील्ड को अलग पहचानने के लिए पाइप चिह्न | का इस्तेमाल करता है, जैसे { oldRecord | field1 = newValue }।
firefly : TvSeries
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
updatedFirefly : TvSeries
updatedFirefly =
{ firefly | creator = "J Whedon", episodes = 15 }
Elm [स्ट्रक्चरल इक्वैलिटी][equality] का इस्तेमाल करता है, यानी एक ही रिकॉर्ड के दो इंस्टेंस जिनकी वैल्यू बिल्कुल समान हैं, बराबर माने जाते हैं।
firefly1 = TvSeries "Firefly" "Joss Whedon" 14
firefly2 = TvSeries "Firefly" "Joss Whedon" 14
firefly1 == firefly2
--> True
Elm स्ट्रक्चरल टाइपिंग का भी समर्थन करता है, यानी अगर किसी फंक्शन को x और y फील्ड वाला रिकॉर्ड चाहिए, तो वह ऐसे किसी भी रिकॉर्ड के साथ काम करेगा जिसमें ये फील्ड हों, जैसे द्वि-आयामी बिंदु, त्रि-आयामी बिंदु, अंतरिक्ष यान, वगैरह।
ऐसे रिकॉर्ड टाइप की परिभाषा में पाइप | होता है, जैसे { a | x : Float, y : Float }, और Elm की शब्दावली में इन्हें "एक्सटेंसिबल रिकॉर्ड" कहा जाता है।
टाइप परिभाषा में पाइप | और असली रिकॉर्ड इंस्टेंस में पाइप |, इन दोनों के फर्क का ध्यान रखिए। टाइप परिभाषा में पाइप | एक्सटेंसिबल रिकॉर्ड की परिभाषा ({ a | x : Int }) होता है, जबकि असली रिकॉर्ड इंस्टेंस में पाइप | का मतलब है कि हम उस रिकॉर्ड के कुछ फील्ड बदल रहे हैं।
point2d = { x = 1, y = 2 }
point3d = { x = 3, y = 4, z = 7 }
.x point2d --> 1
.x point3d --> 3
length : { a | x : Float, y : Float } -> Float
length vector =
sqrt (vector.x * vector.x + vector.y * vector.y)
length point2d --> 2.236068
length point3d --> 5
translateX : { a | x : Float } -> { a | x : Float }
translateX vector =
{ vector | x = vector.x + 1 }
translateX point2d --> { x = 2, y = 2 }
translateX point3d --> { x = 4, y = 4, z = 7 }
इस अभ्यास में आप खेलों के बड़े प्रशंसक हैं और आपको NBA बास्केटबॉल से अभी-अभी लगाव हुआ है। चूँकि आप NBA बास्केटबॉल में नए हैं, इसलिए आप इसके इतिहास में गहराई तक उतर रहे हैं। आप टीमों और कोचों पर नज़र रखते हैं, उनके जीत-हार के आँकड़े जोड़ते हैं और उनकी एक-दूसरे से तुलना करते हैं।
चूँकि अभी आपकी कोई पसंदीदा टीम नहीं है, इसलिए आप एक एल्गोरिदम भी बनाएँगे जो यह तय करेगा कि किसी खास टीम का समर्थन करना चाहिए या नहीं। आपके पास सात काम हैं जो आपको अपना खुद का टीम-का-समर्थन-करने-वाला एल्गोरिदम बनाने में मदद करेंगे।
निम्नलिखित दो फील्ड वाले रिकॉर्ड के लिए Coach टाइप एलियस परिभाषित कीजिए, जिनका क्रम यह रहे:
name: कोच का नाम; इसका टाइप String है।formerPlayer: बताता है कि कोच पहले खिलाड़ी रह चुका था या नहीं; इसका टाइप Bool है।निम्नलिखित दो फील्ड वाले रिकॉर्ड के लिए Stats टाइप एलियस परिभाषित कीजिए, जिनका क्रम यह रहे:
wins: जीत की संख्या; इसका टाइप Int है।losses: हार की संख्या; इसका टाइप Int है।निम्नलिखित तीन फील्ड वाले रिकॉर्ड के लिए Team टाइप एलियस परिभाषित कीजिए, जिनका क्रम यह रहे:
name: टीम का नाम; इसका टाइप String है।coach: टीम का कोच; इसका टाइप Coach है।stats: टीम के आँकड़े; इसका टाइप Stats है।आप किसी तीसरे पक्ष के कोड से जुड़ना चाहते हैं, जिसमें टीम की अवधारणा तो है, लेकिन जो आपके कोड को अलग क्रम में पैरामीटर देकर कॉल करता है। निम्नलिखित सिग्नेचर वाला createTeam फंक्शन जोड़िए: String -> Stats -> Coach -> Team.
NBA के मालिक सब्र नहीं रखते, और आपने देखा कि टीम के नतीजे खराब रहने पर अक्सर कोच बदल दिया जाता था।
replaceCoach फंक्शन बनाइए जो पैरामीटर के रूप में नया कोच और टीम लेता है और टीम को नए कोच के साथ लौटाता है:
let
coach = { name = "Larry Bird", formerPlayer = True }
stats = { wins = 58, losses = 24 }
team = { name = "Indiana Pacers", coach = coach, stats = stats }
newCoach = { name = "Isiah Thomas", formerPlayer = True }
in
replaceCoach newCoach team
--> { name = "Indiana Pacers"
-- , coach = { name = "Isiah Thomas", formerPlayer = True }
-- , stats = { wins = 58, losses = 24 } }
आगे चलकर आप एक जटिल एल्गोरिदम बनाने की सोच रहे हैं, जो तय करेगा कि किसी टीम का समर्थन करना चाहिए या नहीं। लेकिन पहली कोशिश के लिए आपने तय किया है कि जिस टीम की जीत उसकी हार से ज़्यादा हो, आप उस टीम का समर्थन करेंगे।
आप चाहते हैं कि यह फंक्शन दूसरे संदर्भों में भी काम आए, इसलिए टाइप सिग्नेचर में एक्स्टेंसिबल रिकॉर्ड इस्तेमाल कीजिए, ताकि यह ऐसा कोई भी रिकॉर्ड स्वीकार कर सके जिसमें संबंधित फील्ड मौजूद हों।
फंक्शन को जितना हो सके संक्षिप्त रखने के लिए आप पैटर्न मैचिंग इस्तेमाल करके फंक्शन के पैरामीटर से stats निकालना चाहते हैं।
rootForTeam फंक्शन बनाइए जो एक टीम लेता है और अगर आपको उस टीम का समर्थन करना चाहिए तो True लौटाता है; वरना False लौटाता है।
let
spursCoach = { name = "Gregg Popovich", formerPlayer = False }
spursStats = { wins = 56, losses = 26 }
spursTeam = { name = "San Antonio Spurs", coach = spursCoach, stats = spursStats }
in
rootForTeam spursTeam
--> True
Exercism पर साइन अप कीजिए और Elm को 28 कॉन्सेप्ट110 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।