पिछले छह महीनों से मैं जंग में एक एनईएस एमुलेटर काम कर रहा हूं। जैसा कि आप उम्मीद कर सकते हैं, मैंने जंग के बारे में और एनईएस आंतरिक के बारे में और भी बहुत कुछ सीखा है। लेकिन अनुभव ने मेरे रूबी को देखने के तरीके को भी बदल दिया है।
विशेष रूप से, इसने मुझे उन तरीकों के बारे में थोड़ा अधिक पागल बना दिया है जो nil
return लौटाते हैं ।
यदि आप किसी चीज के लिए खड़े नहीं हैं, तो आप किसी भी चीज के लिए गिर जाएंगे
nil
क्या करता है रूबी में मतलब? लगभग कुछ भी। जब कोई विधि शून्य हो जाती है, तो इसका अर्थ यह हो सकता है:
- विधि का कोई वापसी मूल्य नहीं है
- आमतौर पर वापसी मूल्य होता है लेकिन इस बार नहीं
- यह डेटाबेस से एक मान लौटाता है, जो कि NULL है
- कुछ अनपेक्षित हुआ
यह कोड को पढ़ने में कठिन बनाता है और सबसे आम . का मुख्य कारण है रूबी में रूबी अपवाद:NoMethodError
. एक अपवाद निगरानी सेवा के अंश-स्वामी के रूप में, NoMethodError
मेरे बच्चे को स्कूल भेज रहा है।
निम्नलिखित कोड को देखें। यह nil
returns लौटाता है ज्यादातर समय क्योंकि if
स्टेटमेंट का मूल्यांकन nil
. होता है जब सशर्त मेल नहीं खाता है और कोई else
नहीं है ।
def color_name(rgb)
if rgb == 0x000000
"black"
end
end
color_name("#FFFFFF").titleize
=> NoMethodError: undefined method `titleize' for nil:NilClass
यदि आप एक अनुभवी रूबी डेवलपर हैं, तो आप जानते हैं कि यह खरगोश का छेद बहुत गहरा है। कभी-कभी शून्य के ये अलग-अलग अर्थ अजीब तरीकों से ओवरलैप होते हैं, जिससे यह जानना असंभव हो जाता है कि - उदाहरण के लिए - डेटाबेस में एक मान NULL
है या नहीं , या डेटाबेस में कोई मूल्य नहीं है।
एक बेहतर तरीका
Rust में nil
. जैसी कोई चीज़ नहीं होती है . इसके बजाय, जब हम यह बताना चाहते हैं कि कोई फ़ंक्शन कभी-कभी एक मान देता है और कभी-कभी "कुछ नहीं" देता है तो हम एक Option
का उपयोग करते हैं ।
Option
एक प्रकार है जिसमें या तो कुछ विशिष्ट मान होते हैं, या कोई मान नहीं होता है। यहां बताया गया है कि वे कोड में कैसे दिखते हैं:
Option::Some(42); // Wraps the number 42 in an option
Option::None; // Indicates "no result"
यह पहले से ही हमारे तदर्थ nil
से बेहतर दिख रहा है उपयोग, लेकिन यह और भी बेहतर हो जाता है। रस्ट कंपाइलर आपको None
. पर विचार करने के लिए बाध्य करता है मामला। आप गलती से इसे अनदेखा नहीं कर सकते।
match my_option {
Some(x) => do_something_with_x(x),
// If you remove the `None` match below, this code
// won't compile.
None => do_the_default_thing()
}
तो हम अपने रंग नामकरण उदाहरण को जंग में इस तरह लिख सकते हैं:
fn color_name(rgb: u32) -> Option<String> {
if rgb == 0x000000 {
Some("black".to_owned())
} else {
None
}
}
अब हम दोनों Some
. को संभालने के लिए बाध्य हैं और None
शर्तें:
let name = color_name(0xFFFFFF);
let name = match color_name(0xFFFFFF) {
Some(value) => value,
None => "unknown".to_owned(),
}
निश्चित रूप से यह थोड़ा वर्बोज़ और अजीब लग रहा है, लेकिन जब कोई फ़ंक्शन उपयोगी मान वापस नहीं करता है तो मामले को अनदेखा करना असंभव हो जाता है। इसका मतलब है कि कोड को समझना और बनाए रखना आसान है।
रूबी में विकल्प लागू करना
रूबी में कठोरता की कमी है, यह लचीलेपन के लिए बनाता है। मैंने सोचा कि Option
. जैसी किसी चीज़ को लागू करने का प्रयास करना दिलचस्प होगा रूबी में।
हम रूबी में संकलन-समय त्रुटियां नहीं बना सकते, क्योंकि यह एक व्याख्या की गई भाषा है। लेकिन हम गलत कोड को हमेशा बना सकते हैं जब आप किनारे के मामले को हिट करते हैं तो केवल अपवाद उठाने के बजाय अपवाद उठाएं।
सबसे पहले, दो वर्ग बनाते हैं। Some
केवल-पढ़ने के लिए मान रखता है। None
खाली है। वे जितने सरल लगते हैं, उतने ही सरल हैं।
class Some
attr_reader :value
def initialize(value)
@value = value
end
end
class None
end
इसके बाद, हम अपना Option
तैयार करेंगे क्लास जिसमें या तो Some
हो या None
और हमें उन्हें केवल तभी एक्सेस करने देता है जब हम दोनों के लिए हैंडलर प्रदान करते हैं।
class Option
def initialize(value)
@value = value
end
def self.some(value)
self.new(Some.new(value))
end
def self.none()
self.new(None.new)
end
def match(some_lambda, none_lambda)
if @value.is_a?(Some)
some_lambda.call(@value.value)
elsif @value.is_a?(None)
none_lambda.call()
else
raise "Option value must be either Some or None"
end
end
end
अंत में, हम नए Option
. का उपयोग करने के लिए अपने रंग उदाहरण को फिर से लिख सकते हैं कक्षा:
def color_name(rgb)
if rgb == 0x000000
Option.some("black")
else
Option.none()
end
end
puts color_name(0x000000).match(
-> value { value },
-> { "no match" })
# Prints "black"
निष्कर्ष
मैंने अभी तक इस तकनीक को एक वास्तविक परियोजना में आजमाया नहीं है। मुझे लगता है कि यह निश्चित रूप से बहुत सारे NoMethodErrors
. को रोक सकता है जो हमेशा उत्पादन में फिसल जाता है। यह दिखने में थोड़ा बोझिल है, और बहुत रुबिश नहीं है, लेकिन मुझे लगता है कि कुछ परिशोधन के साथ एक अधिक सुखद वाक्य-विन्यास सामने आएगा।