2011-01-13 3 views
8

변경 가능한 상태로 인한 메모 생성을 피하는 방법에 대한 합의가 있습니까?Ruby에서 버그를 일으키는 메모 생성을 어떻게 피하는 것이 좋습니까?

이 예에서 캐시 된 결과에는 상태가 변경되어 두 번째 호출시 잘못된 결과가 나타납니다. 내가 피하기 위해 볼 수

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@greeting_cache[formality]
  2. greetingdup 또는 clone@greeting_cache[formality]의 결과를 freeze 수 반환 할 수 있습니다. 그럴 경우 memoization_mutator이 문자열을 추가 할 때 예외가 발생합니다.
  3. greeting의 결과를 사용하는 모든 코드를 검사하여 문자열이 변경되지 않도록하십시오.

최상의 접근 방식에 대한 합의가 이루어 졌습니까? (1) 또는 (2)의 성능을 저하시키는 유일한 단점은 무엇입니까? (다른 개체에 대한 참조가 있으면 개체가 완전히 작동하지 않을 수도 있습니다.)

참고 :이 문제는 메모 작성의 주 응용 프로그램에는 영향을 미치지 않습니다. Fixnum은 불변이므로 피보나치 시퀀스는 계산되지 않습니다. 가변적 인 상태에 문제가있다. :)

+0

스타일에 대한 간단한 설명 - || = 연산자로 인사말 방법을 단순화 할 수 있습니다. 이렇게 : def greeting (formality); @greeting_cache [형식] || = 비싼 _greeting_ 계산 (형식); end – zaius

+0

@ zaius : 대부분의 시나리오에서 작동하지만'nil' 또는'false'가 유효한 값이면 작동하지 않습니다. –

+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

제안 해 주셔서 감사합니다. 그러나 저는 좀 더 일반적인 해결책을 찾았습니다. –

관련 문제