Ruby中的“仅追加” /“仅写入”哈希

时间:2019-05-01 12:10:13

标签: ruby hashmap ruby-hash writeonly

我正在寻找一种“只能追加”的哈希,其中的密钥只能设置一次。

例如:

capitals = AppendOnlyHash.new
capitals['france'] = 'paris'
capitals['japan'] = 'tokyo'
capitals['france'] = 'nice' # raises immutable exception

任何图书馆建议或想法如何实现?

(用例是一个日志记录类型的对象,它将传递给numerouis松散连接的类,并希望检测是否使用相同的键。)

3 个答案:

答案 0 :(得分:3)

有10种方法可以直接改变哈希值:

Hash.instance_methods.grep(/.+!\z/) << %i|[]= delete keep_if|
#⇒ [:select!, :filter!, :reject!, :compact!, delete, keep_if,
#   :transform_keys!, :transform_values!, :merge!, :[]=]

此外,还有可能使值本身capitals['france'] << ' and Lyon')发生变异,因此我们也应避免这种情况。

class MyHash < Hash; end

MyHash.prepend(
  Module.new do
    (Hash.instance_methods.grep(/.+!\z/) | %i|delete keep_if|).each do |method|
      define_method(method) do |*args|
        raise "Method #{method} is restricted since it is mutating"
      end
    end
    def []=(key, val)
      raise "This hash is immutable" if key?(key)
      super(key, val.freeze) # to prevent inplace mutations
    end
  end
)

需要从Hash派生,否则我们将破坏所有哈希。

我没有测试这段代码,但是它应该可以立即使用,(如果没有,这个想法应该很清楚。)

答案 1 :(得分:2)

第一个想法,我没有考虑任何缺点:

class HashImmutable < Hash
  def []=(key,val)
    if self[key].frozen?
      super(key,val)
    else
      # self[key]
      raise 'Immutable'
    end
  end
end

hh = HashImmutable.new

hh[:france] = 'Paris'
hh[:italy] = 'Roma'
hh #=> {:france=>"Paris", :italy=>"Roma"}
hh[:italy] = 'Brescia'
#=> Immutable (RuntimeError)

答案 2 :(得分:1)

这是创建此类的幼稚尝试。对于“基本”用法,它似乎工作正常:

class AppendOnlyHash < Hash
  def []=(key, value)
    raise "APPEND ONLY!!" if keys.include?(key)
    super
  end
end

但是,这肯定有一些缺陷。

首先,如果您在对象上调用破坏性方法并试图删除某些键,会发生什么?也许您可以覆盖所有这些方法-即filter!keep_ifdeletecompact!reject!select!transform_keys!transform_values!。 (我想念吗?...)

然后,如何处理Hash#merge!?我想也可以专门处理;因为使用 if 是有效的,所以没有重新定义键。

最后,如何确保“仅追加”哈希值永远不会变异?请考虑以下内容:

capitals = AppendOnlyHash.new
str = "paris"
capitals['france'] = str
str << " CHANGED"

在将每个值添加到哈希中时,您可以调用.freeze,但这并不是100%防弹的-因为该值可能又是另一个Hash,因此容易受到相同影响行为。


因此,总的来说,我认为这可以通过我上面的基本实现来实现,但是我对由“怪异的方式”中的异议突变导致的日益复杂的边缘情况保持谨慎。