如何避免备忘录导致Ruby中的错误? [英] How should I avoid memoization causing bugs in Ruby?

查看:87
本文介绍了如何避免备忘录导致Ruby中的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于如何避免由于易变的状态而导致记忆不足的错误,是否达成共识?

Is there a consensus on how to avoid memoization causing bugs due to mutable state?

在此示例中,缓存的结果的状态发生了变化,因此第二次调用时给出了错误的结果.

In this example, a cached result had its state mutated, and therefore gave the wrong result the second time it was called.

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]dupclone
  2. greeting可以freeze @greeting_cache[formality]的结果.当memoization_mutator向其附加字符串时,会引发异常.
  3. 检查所有使用greeting结果的代码,以确保它们均不对字符串进行任何突变.
  1. greeting could return a dup or clone of @greeting_cache[formality]
  2. greeting could freeze the result of @greeting_cache[formality]. That'd cause an exception to be raised when memoization_mutator appends strings to it.
  3. Check all code that uses the result of greeting to ensure none of it does any mutating of the string.

关于最佳方法是否达成共识?做(1)或(2)降低性能的唯一缺点是吗? (我还怀疑冻结一个引用了其他对象的对象可能无法完全起作用)

Is there a consensus on the best approach? Is the only disadvantage of doing (1) or (2) decreased performance? (I also suspect freezing an object may not work fully if it has references to other objects)

旁注:此问题不会影响记忆的主要应用:由于Fixnum是不可变的,因此计算斐波那契序列不会有可变状态的问题. :)

Side note: this problem doesn't affect the main application of memoization: as Fixnums are immutable, calculating Fibonacci sequences doesn't have problems with mutable state. :)

推荐答案

我倾向于返回克隆的对象.创建新字符串对性能的影响几乎没有.冻结会公开实现细节.

I would lean towards returning a cloned object. The performance hit of creating a new string is next to nothing. And freezing exposes implementation details.

这篇关于如何避免备忘录导致Ruby中的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆