Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी में ग्राम्य शून्य हैंडलिंग

पिछले छह महीनों से मैं जंग में एक एनईएस एमुलेटर काम कर रहा हूं। जैसा कि आप उम्मीद कर सकते हैं, मैंने जंग के बारे में और एनईएस आंतरिक के बारे में और भी बहुत कुछ सीखा है। लेकिन अनुभव ने मेरे रूबी को देखने के तरीके को भी बदल दिया है।

विशेष रूप से, इसने मुझे उन तरीकों के बारे में थोड़ा अधिक पागल बना दिया है जो 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 . को रोक सकता है जो हमेशा उत्पादन में फिसल जाता है। यह दिखने में थोड़ा बोझिल है, और बहुत रुबिश नहीं है, लेकिन मुझे लगता है कि कुछ परिशोधन के साथ एक अधिक सुखद वाक्य-विन्यास सामने आएगा।


  1. रूबी में बिटवाइज़ हैक्स

    संभावना है कि आपको आमतौर पर अपने दिन के काम में थोड़ा सा गणित करने की आवश्यकता नहीं होती है। रूबी के बिटवाइज़ AND और OR ऑपरेटर्स ( &और | ) का उपयोग संभवतः दुर्घटनावश उद्देश्य से अधिक किया जाता है। किसने गलती से टाइप नहीं किया और कब उनका मतलब &&था? लेकिन अगर आप सी या असेंबलर, या मेरे मामले में टर्बो

  1. रूबी में लैम्ब्डा का उपयोग करना

    ब्लॉक रूबी का इतना महत्वपूर्ण हिस्सा हैं, उनके बिना भाषा की कल्पना करना मुश्किल है। लेकिन लैम्ब्डा? लैम्ब्डा को कौन प्यार करता है? आप एक का उपयोग किए बिना वर्षों तक जा सकते हैं। वे लगभग पुराने जमाने के अवशेष की तरह लगते हैं। ...लेकिन यह बिल्कुल सच नहीं है। एक बार जब आप उनकी थोड़ी जांच कर लेते हैं त

  1. रूबी में 9 नई सुविधाएँ 2.6

    रूबी का एक नया संस्करण नई सुविधाओं और प्रदर्शन में सुधार के साथ आ रहा है। क्या आप परिवर्तनों के साथ बने रहना चाहेंगे? आइए एक नज़र डालते हैं! अंतहीन रेंज रूबी 2.5 और पुराने संस्करण पहले से ही अंतहीन श्रेणी के एक रूप का समर्थन करते हैं (Float::INFINITY के साथ) ), लेकिन रूबी 2.6 इसे अगले स्तर पर ले