";仅附加“/quot;”&引用;只写“;Ruby中的hash
我正在寻找一种“仅附加”哈希,其中键只能设置一次 例如:";仅附加“/quot;”&引用;只写“;Ruby中的hash,ruby,hashmap,ruby-hash,writeonly,Ruby,Hashmap,Ruby Hash,Writeonly,我正在寻找一种“仅附加”哈希,其中键只能设置一次 例如: capitals = AppendOnlyHash.new capitals['france'] = 'paris' capitals['japan'] = 'tokyo' capitals['france'] = 'nice' # raises immutable exception 图书馆有什么建议或想法如何实现这一点 (用例是一个日志类型的对象,它将被传递给numerouis松散连接的类,并希望检测是否有使用相同密钥的对象。)首先
capitals = AppendOnlyHash.new
capitals['france'] = 'paris'
capitals['japan'] = 'tokyo'
capitals['france'] = 'nice' # raises immutable exception
图书馆有什么建议或想法如何实现这一点
(用例是一个日志类型的对象,它将被传递给numerouis松散连接的类,并希望检测是否有使用相同密钥的对象。)首先,我没有考虑任何缺点:
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)
类HashImmutable{:法国=>“巴黎”,意大利=>“罗马”}
hh[:意大利]=“布雷西亚”
#=>不可变(运行时错误)
下面是创建此类类的一个天真尝试。对于“基本”用法,它似乎很好:
您可以在每个值添加到散列中时调用.freeze
,但即使这样也不是100%防弹的,因为该值可能是另一个散列
,它也会受到相同行为的影响
总之,我认为通过我上面的基本实现,这是可能的,但我会谨慎对待由“奇怪的方式”的对象突变导致的日益复杂的边缘情况。有10种方法,直接突变哈希:
Hash.instance_methods.grep(/.+!\z/) << %i|[]= delete keep_if|
#⇒ [:select!, :filter!, :reject!, :compact!, delete, keep_if,
# :transform_keys!, :transform_values!, :merge!, :[]=]
Hash.instance\u methods.grep(/.+!\z/)我担心的是,哈希可能会以其他方式更新。除了[]
之外,还有一些方法可以改变散列。也许您可以将这些方法添加到类中,例如def transform_values!;提出"一成不变",;结束
奇怪的是,现在还没有rubygem来做这件事。
capitals = AppendOnlyHash.new
str = "paris"
capitals['france'] = str
str << " CHANGED"
Hash.instance_methods.grep(/.+!\z/) << %i|[]= delete keep_if|
#⇒ [:select!, :filter!, :reject!, :compact!, delete, keep_if,
# :transform_keys!, :transform_values!, :merge!, :[]=]
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
)