在 Ruby 中,我想初始化一個新的哈希,這樣:
- 哈希被分配一組特定的初始鍵值對;
- 如果嘗試檢索未定義鍵的值,則哈希配置為引發錯誤;
- 哈希被凍結(無法進一步修改)。
有沒有一種優雅的 Ruby 風格的方式來一次完成這個設定?
我知道這可以在三個單獨的行中完成,例如:
COIN_SIDES = { heads: 'heads', tails: 'tails' }
COIN_SIDES.default_proc = -> (h, k) { raise KeyError, "Key '#{k}' not found" }
COIN_SIDES.freeze
uj5u.com熱心網友回復:
您可以通過使用 default_proc 初始化散列,然后使用 merge! 添加組件來做到這一點:
h = Hash.new{|hash, key| raise KeyError, "Key '#{key}' not found"}.merge!({ heads: 'heads', tails: 'tails' }).freeze
uj5u.com熱心網友回復:
我不確定這是否非常優雅,但是在一條(長)行中實作這一點的一種方法是使用.tap:
COIN_SIDES = { heads: 'heads', tails: 'tails' }.tap { |cs| cs.default_proc = -> (h, k) { raise KeyError, "Key '#{k}' not found" } }.tap(&:freeze)
這種方法至少避免了在上面原始問題的代碼的 3 行版本上RuboCop: Freeze mutable objects assigned to constants [Style/MutableConstant]運行RuboCop linter時生成的警告。
uj5u.com熱心網友回復:
您可以通過創建自定義類來完成大部分功能,唯一的缺點是它不是真正的哈希,因此如果需要,您需要顯式添加額外的功能,如.keys,each等:
class HashLike
def initialize(hsh)
singleton_class.attr_reader *hsh.keys
hsh.each { |k,v| instance_variable_set "@#{k}", v }
end
end
hashlike = HashLike.new(some_value: 1)
hashlike.some_value # 1
hashlike.missing_value # NoMethodError
hashlike.some_value = 2 # NoMethodError
另一種類似的方式:
class HashLike2
def initialize(hsh)
@hsh = hsh
end
def [](key)
@hsh.fetch(key)
end
end
hashlike2 = HashLike2.new(some_value: 1)
hashlike2[:some_value] # 1
hashlike2[:missing_value] # KeyError
hashlike2[:some_value] = 2 # NoMethodError
但在我看來,沒有太多理由這樣做。您可以輕松地將原來的 3 行移動到某個方法中,然后它不再是 3 行或 1 行了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/446737.html
標籤:红宝石
