2011-01-13 11 views
8

क्या इस बात पर सर्वसम्मति है कि म्यूटोइज़ेशन से बचने के लिए कैसे विस्फोटक स्थिति के कारण बग का कारण बनता है?मुझे रुबी में बग के कारण यादों से कैसे बचना चाहिए?

इस उदाहरण में, एक कैश किए गए परिणाम के राज्य को बदल दिया गया था, और इसलिए दूसरी बार गलत परिणाम दिया गया।

class Greeter 

    def initialize 
    @greeting_cache = {} 
    end 

    def expensive_greeting_calculation(formality) 
    case formality 
     when :casual then "Hi" 
     when :formal then "Hello" 
    end 
    end 

    def greeting(formality) 
    unless @greeting_cache.has_key?(formality) 
     @greeting_cache[formality] = expensive_greeting_calculation(formality) 
    end 
    @greeting_cache[formality] 
    end 

end 

def memoization_mutator 
    greeter = Greeter.new 
    first_person = "Bob" 
    # Mildly contrived in this case, 
    # but you could encounter this in more complex scenarios 
    puts(greeter.greeting(:casual) << " " << first_person) # => Hi Bob 
    second_person = "Sue" 
    puts(greeter.greeting(:casual) << " " << second_person) # => Hi Bob Sue 
end 

memoization_mutator 

दृष्टिकोण मैं से बचने के लिए देख सकते हैं इस प्रकार हैं:

  1. greeting लौट सकते हैं एक dup या clone@greeting_cache[formality]
  2. greeting की @greeting_cache[formality] का परिणाम freeze सकता है। इससे memoization_mutator स्ट्रिंग को जोड़ते समय अपवाद उत्पन्न किया जाएगा।
  3. greeting के परिणाम का उपयोग करने वाले सभी कोड को जांचें ताकि यह सुनिश्चित किया जा सके कि इनमें से कोई भी स्ट्रिंग का कोई उत्परिवर्तन नहीं करता है।

क्या सर्वोत्तम दृष्टिकोण पर सर्वसम्मति है? क्या करने का एकमात्र नुकसान (1) या (2) प्रदर्शन में कमी आई है? (मैं भी ठंड एक वस्तु को पूरी तरह से काम नहीं कर सकता है अगर यह अन्य वस्तुओं के लिए संदर्भ है संदेह है)

साइड नोट: इस समस्या को Memoization के मुख्य आवेदन को प्रभावित नहीं करता: के रूप में Fixnum रों अपरिवर्तनीय हैं, की गणना फाइबोनैचि दृश्यों नहीं है उत्परिवर्तनीय स्थिति में समस्याएं हैं। :)

+0

शैली पर एक छोटी सी टिप्पणी - आप || = ऑपरेटर के साथ ग्रीटिंग विधि को सरल बना सकते हैं। इस तरह: डेफ ग्रीटिंग (औपचारिकता); @greeting_cache [औपचारिकता] || = महंगा_greeting_calculation (औपचारिकता); अंत – zaius

+0

@zaius: यह अधिकांश परिदृश्यों में काम करता है, लेकिन काम नहीं करेगा अगर 'शून्य 'या' झूठा 'वैध मान थे। –

+0

आह, सच है। मेरी गलती। स्वीकृति के लिए – zaius

उत्तर

4

मैं क्लोन ऑब्जेक्ट लौटने की दिशा में दुबला होगा। एक नई स्ट्रिंग बनाने का प्रदर्शन हिट कुछ भी नहीं है। और ठंड कार्यान्वयन विवरण का खुलासा करता है।

0

मैं अभी भी 'माणिक नौसिखिया' कर रहा हूँ, और यदि आप '< <' और '+' एक स्ट्रिंग के लिए विधियों के बीच अंतर के बारे में जानते थे मैं नहीं जानता।

first_person = "Bob" 
puts(greeter.greeting(:casual) + " " + first_person) # => Hi Bob 
second_person = "Sue" 
puts(greeter.greeting(:casual) + " " + second_person) # => Hi Sue 

# str << obj → str 
# str + other_str → new_str 
+0

सुझाव के लिए धन्यवाद, लेकिन मैं एक और अधिक सामान्य समाधान के बाद और अधिक हूं। –

संबंधित मुद्दे