提问人:Alexey Romanov 提问时间:3/26/2023 更新时间:3/27/2023 访问量:185
在 Ruby 3 中模式匹配哈希时的默认值
Default values when pattern matching a hash in Ruby 3
问:
在 Ruby 3 中,
hash => {a:}
工作方式类似于 JS
{ a } = hash
除了如果不是键,它会抛出异常,而不是分配 .好的,我们可以做:a
hash
a = nil
hash => {a:} rescue nil
除非如果存在某些键而缺少其他键,则会产生不希望的结果:
{a: 1, b: 2} => {b:, c:} rescue nil
puts "b: #{b}, c: #{c}"
显示 和 都是 而不是 期望的 .有没有一种简单的方法可以得到这个结果?或者更一般地说,使用非默认值模拟 JS 哈希解构?b
c
nil
b = 2, c = nil
nil
答:
0赞
Alexey Romanov
3/26/2023
#1
在写这个问题时,我想到了这个解决方法:
{a: some_default, **hash} => {a:}
或第二种情况
{b: nil, c: nil, **hash} => {b:, c:}
我不喜欢它,因为它复制了密钥并做了一些工作来创建左侧哈希,所以希望有人有更好的选择。
1赞
Alex
3/27/2023
#2
您可以通过创建一个响应以下对象来解决缺少键错误:deconstruct_keys
hash = {a: 1}
H(hash) => x:,y:,a:
x # => nil
y # => nil
a # => 1
H(hash, "default") => x:,y:,a:
x # => "default"
y # => "default"
a # => 1
H(hash, x: :z) => x:,y:,a:
x # => :z
y # => nil
a # => 1
H(hash, "default", x: :z) => x:,y:,a:
x # => :z
y # => "default"
a # => 1
deconstruct_keys
当使用哈希模式时调用,这些键作为参数传递:=> x:,y:,a:
# DelegateClass to make H be like a hash, but pattern match differently.
# (it works just fine without DelegateClass)
#
# H.new({a: 1}) # => {:a=>1}
#
class H < DelegateClass(Hash)
def initialize(hash, default = nil, **defaults)
# since hash needs to be duped anyway
@hash = defaults.merge hash # defaults for specific key
@default = default # default for any missing keys
super(@hash) # get delegation going
end
def deconstruct_keys keys
missing = keys - @hash.keys # find what's missing
missing.each { |k| @hash[k] = @default } # add it to hash with default value
@hash # return for pattern matching
end
end
# H() method, like a Hash() method.
def H(...)
H.new(...)
end
评论