Crystal:检测字典插入是否覆盖键,但不进行两次散列

Crystal: detect if a dictionary insert overwrites a key, but without hashing twice

Crystal 中将键插入 Hash 的规范方法是什么,但如果映射之前确实存在,则会抛出错误。原则上,代码如下:

map = Hash(String, Int32).new
if map.has_key?("foo")
  raise "Mapping already exists"
else
  map["foo"] = 42
end

我想知道是否可以不用哈希两次?我想出了这个主意,但恕我直言,很难阅读:

map = Hash(String, Int32).new
if map.put("foo", 42) {}
  raise "Mapping already exists"
end

(如果映射存在,Map#put returns 旧值。否则,调用块的结果,即 nil 并计算为 false .)

有推荐的模式吗?

在性能方面,您已经找到了最佳解决方案。我可能会使用内联块调用这一事实来稍微重写它:

def update(hash, key, value)
  hash.put(key, value) { return }
  raise "Duplicate entry"
end

但是这里有一个重要的陷阱:在错误情况下哈希仍然会更新:

hash = {"foo" => "bar"}
update(hash, "baz", "quux")
pp hash # => {"foo" => "bar", "baz" => "quux"}
update(hash, "foo", "hello") rescue puts "Failed updating foo" # => Failed updating foo
pp hash # => {"foo" => "hello", "baz" => "quux"}

https://carc.in/#/r/bn1o

在不侵入内部 API 的情况下,我认为没有办法避免这种情况。实际上,哈希查找并不是很昂贵,毕竟它是一种针对通过键查找值而优化的数据结构。特别是因为您似乎可以在 API 中加注,这相对来说是一个更昂贵的操作。所以就我个人而言,我会选择你的第一个例子。