आइए रूबी में पैटर्न मिलान के बारे में एक संक्षिप्त चर्चा के साथ शुरू करें, यह क्या करता है, और यह कैसे कोड पठनीयता को बेहतर बनाने में मदद कर सकता है।
यदि आप कुछ साल पहले मेरे जैसे कुछ हैं, तो आप इसे रेगेक्स में पैटर्न मिलान के साथ भ्रमित कर सकते हैं। यहां तक कि बिना किसी अन्य संदर्भ के 'पैटर्न मिलान' की एक त्वरित Google खोज भी आपको उस परिभाषा के काफी करीब सामग्री लाती है।
औपचारिक रूप से, पैटर्न मिलान किसी भी डेटा की जांच करने की प्रक्रिया है (चाहे वह वर्णों का एक क्रम हो, टोकन की एक श्रृंखला, एक टपल, या कुछ और) अन्य डेटा के विरुद्ध।
प्रोग्रामिंग के संदर्भ में, भाषा की क्षमताओं के आधार पर, इसका मतलब निम्न में से कोई भी हो सकता है:
- अपेक्षित डेटा प्रकार से मिलान करना
- अपेक्षित हैश संरचना (जैसे विशिष्ट कुंजियों की उपस्थिति) के विरुद्ध मिलान करना
- अपेक्षित सरणी लंबाई के विरुद्ध मिलान
- मिलानों (या उनमें से एक भाग) को कुछ चरों पर असाइन करना
पैटर्न मिलान में मेरा पहला प्रयास अमृत के माध्यम से हुआ था। पैटर्न मिलान के लिए अमृत के पास प्रथम श्रेणी का समर्थन है, इतना अधिक कि =
ऑपरेटर, वास्तव में, मिलान
. है साधारण असाइनमेंट के बजाय ऑपरेटर।
इसका मतलब है कि अमृत में, निम्नलिखित वास्तव में मान्य कोड है:
iex> x =1iex> 1 =x
इसे ध्यान में रखते हुए, आइए रूबी 2.7+ के लिए नए पैटर्न मिलान समर्थन को देखें और आज से शुरू करके हम अपने कोड को और अधिक पठनीय बनाने के लिए इसका उपयोग कैसे कर सकते हैं।
रूबी पैटर्न केस
से मेल खाता है /में
रूबी एक विशेष केस
. के साथ मिलान पैटर्न का समर्थन करती है /में
अभिव्यक्ति। वाक्य रचना है:
केस <अभिव्यक्ति> # ...में # ...else # ...end
इसे केस
. के साथ भ्रमित नहीं होना चाहिए /कब
अभिव्यक्ति। कब
और में
शाखाओं को एक केस
में नहीं मिलाया जा सकता ।
यदि आप कोई अन्य
प्रदान नहीं करते हैं अभिव्यक्ति, कोई भी असफल मिलान एक NoMatchingPatternError
उत्पन्न करेगा ।
रूबी में पैटर्न मिलान सरणी
पैटर्न मिलान का उपयोग डेटा प्रकारों, लंबाई या मानों के विरुद्ध पूर्व-आवश्यक संरचनाओं के लिए सरणियों से मिलान करने के लिए किया जा सकता है।
उदाहरण के लिए, निम्नलिखित सभी मैच हैं (ध्यान दें कि केवल पहला इन
मामले
. के रूप में मूल्यांकन किया जाएगा पहला मैच देखना बंद कर देता है):
case [1, 2, "Three"]in [Integer, Integer, String] "matches"in [1, 2, "Three"] "matches" in [Integer, *] "matches" # क्योंकि * एक स्प्रेड ऑपरेटर है जो [a, *] "मिलान" # में किसी भी चीज़ से मेल खाता है और वेरिएबल a का मान अब 1end
है
जब आप किसी मेथड कॉल से कई सिग्नल उत्पन्न करना चाहते हैं तो इस प्रकार का पैटर्न मिलान क्लॉज बहुत उपयोगी होता है।
इलीक्सिर की दुनिया में, इसका उपयोग अक्सर ऑपरेशन करते समय किया जाता है जिसमें :ok
. दोनों हो सकते हैं परिणाम और एक :त्रुटि
परिणाम, उदाहरण के लिए, डेटाबेस में डाला गया।
यहां बताया गया है कि हम इसे बेहतर पठनीयता के लिए कैसे उपयोग कर सकते हैं:
def create case save(model_params) in [:ok, model] render :json => model in [:error,errors] render :json => error endend # आपके कोड में कहीं, उदा। एक वैश्विक सहायक या आपके मॉडल बेस क्लास के अंदर (एक अलग नाम के साथ)। def save(attrs) model =Model.new(attrs) model.save ? [:ठीक है, मॉडल] :[:त्रुटि, मॉडल.त्रुटियां]अंत
रूबी में वस्तुओं का मिलान करने वाला पैटर्न
आप एक विशिष्ट संरचना को लागू करने के लिए रूबी में वस्तुओं का मिलान भी कर सकते हैं:
केस {a:1, b:2}in {a:Integer} "matches" # डिफ़ॉल्ट रूप से, सभी ऑब्जेक्ट मैच आंशिक {a:Integer, **} "matches" # होते हैं और एक जैसे होते हैं {a:Integer}in {a:a} "matches" # और वेरिएबल a का मान अब 1in {a:Integer => a} "matches" # है और वेरिएबल a का मान अब 1in {a:1 है। b:b} "मिलान" # और वेरिएबल b का मान अब 2in {a:Integer, **nil} "मेल नहीं खाता" # यह तभी मेल खाएगा जब ऑब्जेक्ट में a हो और कोई अन्य keyend न हो
किसी भी पैरा के खिलाफ मिलान के लिए मजबूत नियम लागू करते समय यह बहुत अच्छा काम करता है।
उदाहरण के लिए, यदि आप एक फैंसी अभिवादन लिख रहे हैं, तो इसकी निम्नलिखित (दृढ़ राय वाली) संरचना हो सकती है:
में {अभिवादन:अभिवादन, नाम:नाम} {नाम:नाम} में "#{ग्रीटिंग}, #{नाम}" डालता है (अभिवादन:"हैलो", नाम:नाम) {अभिवादन:अभिवादन} में अभिवादन (अभिवादन:अभिवादन) , नाम:"बेनामी") अन्य अभिवादन (अभिवादन:"हैलो", नाम:"बेनामी") अंत में अभिवादन # हैलो, बेनामीग्रीट (नाम:"जॉन") # हैलो, जॉनग्रीट (प्रथम_नाम:"जॉन", अंतिम_नाम:"डो ") # हैलो, जॉन डोग्रीट (अभिवादन:"बोनजोर", प्रथम_नाम:"जॉन", अंतिम_नाम:"डो") # बोनजोर, जॉन डोग्रीट (अभिवादन:"बोनजोर") # बोनजोर, बेनामीरूबी में वैरिएबल बाइंडिंग और पिनिंग
जैसा कि हमने ऊपर के कुछ उदाहरणों में देखा है, पैटर्न मिलान वास्तव में पैटर्न के हिस्से को मनमाने चरों को निर्दिष्ट करने में उपयोगी है। इसे वेरिएबल बाइंडिंग कहा जाता है, और ऐसे कई तरीके हैं जिनसे हम एक वेरिएबल से जुड़ सकते हैं:
- मजबूत प्रकार के मिलान के साथ, उदा.
इन [पूर्णांक => a]
यामें {a:Integer => a}
- प्रकार विनिर्देश के बिना, उदा.
इन [a, 1, 2]
यामें {a:a}
। - चर नाम के बिना, जो डिफ़ॉल्ट रूप से कुंजी नाम का उपयोग करता है, उदा.
में {a:}
a
. नामक एक वेरिएबल को परिभाषित करेगा कुंजीa
. पर मान के साथ । - बाँध आराम, उदा.
इन [पूर्णांक, *बाकी]
यामें {a:Integer, **rest}
।
तब, जब हम उप-पैटर्न के रूप में मौजूदा चर का उपयोग करना चाहते हैं, तो हम कैसे मेल खा सकते हैं? यह तब होता है जब हम चर पिनिंग . का उपयोग कर सकते हैं ^
. के साथ (पिन) ऑपरेटर:
a =1केस {a:1, b:2}में {a:^a} "मैच"अंत
आप इसका उपयोग तब भी कर सकते हैं जब एक चर को एक पैटर्न में ही परिभाषित किया जाता है, जिससे आप इस तरह के शक्तिशाली पैटर्न लिख सकते हैं:
केस ऑर्डर में {बिलिंग_एड्रेस:{सिटी:}, शिपिंग_एड्रेस:{सिटी:^सिटी}} "बिलिंग और शिपिंग दोनों एक ही शहर में हैं" और बढ़ाएं "बिलिंग और शिपिंग दोनों एक ही शहर में होने चाहिए "अंत
वैरिएबल बाइंडिंग के साथ उल्लेख करने के लिए एक महत्वपूर्ण विचित्रता यह है कि भले ही पैटर्न पूरी तरह से मेल नहीं खाता हो, फिर भी वेरिएबल बाध्य रहेगा। यह कभी-कभी उपयोगी हो सकता है।
लेकिन, ज्यादातर मामलों में, यह सूक्ष्म बग का कारण भी हो सकता है - इसलिए सुनिश्चित करें कि आप छायांकित चर मानों पर भरोसा नहीं करते हैं जो एक मैच के अंदर उपयोग किए गए हैं। उदाहरण के लिए, निम्नलिखित में, आप शहर से अपेक्षा करेंगे "एम्स्टर्डम" हो, लेकिन इसके बजाय यह "बर्लिन" होगा:
शहर ="एम्स्टर्डम"आदेश ={बिलिंग_पता:{शहर:"बर्लिन"}, शिपिंग_पता:{शहर:"ज़्यूरिख"}}मामला आदेश {बिलिंग_पता:{शहर:}, शिपिंग_पता:{शहर:^ शहर}} डालता है "बिलिंग और शिपिंग दोनों एक ही शहर के लिए हैं" और कहते हैं "बिलिंग और शिपिंग दोनों एक ही शहर में होने चाहिए" एंडपुट्स शहर # एम्स्टर्डम के बजाय बर्लिन
रूबी की कस्टम क्लास से मेल खाना
रूबी में कस्टम क्लास पैटर्न मिलान को जागरूक करने के लिए आप कुछ विशेष तरीकों को लागू कर सकते हैं।
उदाहरण के लिए, किसी उपयोगकर्ता को उसके first_name
. से मिलान करने के लिए पैटर्न और last_name
, हम परिभाषित कर सकते हैं deconstruct_keys
कक्षा में:
वर्ग उपयोगकर्ता def deconstruct_keys(keys) {first_name:first_name, last_name:last_name} एंडेंड केस यूजरिन {first_name:"John"} "Hey, John" end
डालता है।
कुंजी
deconstruct_keys
. के लिए तर्क इसमें वे कुंजियाँ होती हैं जिनका पैटर्न में अनुरोध किया गया है। यह रिसीवर के लिए केवल आवश्यक कुंजियाँ प्रदान करने का एक तरीका है यदि उन सभी की गणना करना महंगा है।
उसी तरह जैसे deconstruct_keys
, हम deconstruct
. का कार्यान्वयन प्रदान कर सकते हैं वस्तुओं को एक सरणी के रूप में पैटर्न मिलान करने की अनुमति देने के लिए। उदाहरण के लिए, मान लें कि हमारे पास स्थान
है वह वर्ग जिसमें अक्षांश और देशांतर हो। deconstruct_keys
using का उपयोग करने के अलावा अक्षांश और देशांतर कुंजियाँ प्रदान करने के लिए, हम [अक्षांश, देशांतर]
के रूप में एक सरणी दिखा सकते हैं साथ ही:
क्लास लोकेशन डिकॉन्स्ट्रक्ट [अक्षांश, देशांतर] एंडएंड केस लोकेशन में [फ्लोट => अक्षांश, फ्लोट => देशांतर] "#{अक्षांश}, #{देशांतर}"अंत
डालता है
जटिल पैटर्न के लिए गार्ड का उपयोग करना
यदि हमारे पास जटिल पैटर्न हैं जिन्हें नियमित पैटर्न मिलान ऑपरेटरों के साथ प्रदर्शित नहीं किया जा सकता है, तो हम if
. का भी उपयोग कर सकते हैं (या जब तक
) मैच के लिए एक गार्ड प्रदान करने के लिए बयान:
केस [1, 2] में [a, b] अगर b ==a * 2 "मैच" और "नो मैच" खत्म होता है
पैटर्न मिलान =>
. के साथ /में
केस
के बिना
यदि आप रूबी 3+ पर हैं, तो आपके पास जादू से मेल खाने वाले और भी अधिक पैटर्न तक पहुंच है। रूबी 3 से शुरू होकर, पैटर्न मिलान बिना किसी केस स्टेटमेंट के सिंगल लाइन में किया जा सकता है:
[1, 2, "तीन"] => [पूर्णांक => एक, दो, स्ट्रिंग => तीन] एक डालता है # 1पुट दो # 2पुट तीन # तीन # ऊपर के समान [1, 2, " तीन"] में [पूर्णांक => एक, दो, स्ट्रिंग => तीन]
यह देखते हुए कि उपरोक्त सिंटैक्स में else
नहीं है क्लॉज, यह सबसे उपयोगी तब होता है जब डेटा संरचना पहले से जानी जाती है।
एक उदाहरण के रूप में, यह पैटर्न एक आधार नियंत्रक के अंदर अच्छी तरह फिट हो सकता है जो केवल व्यवस्थापक उपयोगकर्ताओं को अनुमति देता है:
क्लास एडमिनकंट्रोलर <ऑथेंटिकेटेड कंट्रोलर से पहले_एक्शन:वेरिफाई_एडमिन प्राइवेट डीईएफ़ वेरिफाई_एडमिन करंट।
रूबी में पैटर्न मिलान:इस स्पेस को देखें
सबसे पहले, पैटर्न मिलान को समझने में थोड़ा अजीब लग सकता है। कुछ के लिए, यह महिमामंडित वस्तु/सरणी विघटन जैसा लग सकता है।
लेकिन अगर अमृत की लोकप्रियता कोई संकेत है, तो पैटर्न मिलान आपके शस्त्रागार में एक महान उपकरण है। एलिक्सिर पर इसका उपयोग करने का पहला अनुभव होने के बाद, मैं पुष्टि कर सकता हूं कि एक बार जब आप इसकी आदत डाल लेते हैं तो जीना मुश्किल होता है।पी>
यदि आप रूबी 2.7 पर हैं, तो पैटर्न मिलान (केस
. के साथ) /में
) अभी भी प्रायोगिक है। रूबी 3 के साथ, केस
/में
नए पेश किए गए सिंगल-लाइन पैटर्न मिलान एक्सप्रेशन प्रयोगात्मक हैं, जबकि स्थिर में स्थानांतरित हो गया है। चेतावनियों को Warning[:experimental] =false
के साथ बंद किया जा सकता है कोड में या -W:no-प्रयोगात्मक
. में कमांड-लाइन कुंजी।
हालांकि रूबी में पैटर्न मिलान अभी भी अपने प्रारंभिक चरण में है, मुझे आशा है कि आपको यह परिचय उपयोगी लगा होगा और आप भी उतने ही उत्साहित होंगे जितना कि मैं आने वाले भविष्य के विकास को लेकर!
पी.एस. यदि आप रूबी मैजिक पोस्ट को प्रेस से बाहर होते ही पढ़ना चाहते हैं, तो हमारे रूबी मैजिक न्यूज़लेटर की सदस्यता लें और कभी भी एक भी पोस्ट मिस न करें!