Ruby 3哈希模式匹配:如何限制rest仅包含允许的键?
Ruby 3哈希模式匹配如何限制rest仅包含指定键
Ruby 3原生模式匹配没有直接提供“约束rest仅包含允许键”的语法,但可以通过几种方式实现你的需求:
简化你当前的写法
你当前的思路是可行的,但可以简化——因为哈希匹配中的**rest永远不会是nil,没有匹配到额外键时它是空哈希,所以可以去掉rest.nil?的判断:
opts = { value: 5, limit: 10 } # 匹配成功 # opts = { value: 5 } # 匹配成功 # opts = { value: 5, foo: 10 } # 匹配失败 case opts in value:, **rest if (rest.keys - %i[limit]).empty? puts "valid" else puts "invalid" end
更高效的写法可以用集合的子集判断:
allowed_rest_keys = %i[limit].to_set case opts in value:, **rest if rest.keys.to_set.subset?(allowed_rest_keys) puts "valid" else puts "invalid" end
更贴合你理想的实现方式
你提到的类似Flowtype的in value:, limit?:写法,其实可以直接用Ruby模式匹配的可选键语法实现,而且效果更直接——显式列出所有允许的键(必填+可选),多余的键会直接导致匹配失败:
opts = { value: 5, limit: 10 } # 匹配成功 # opts = { value: 5 } # 匹配成功 # opts = { value: 5, foo: 10 } # 匹配失败 case opts in value:, limit?: puts "valid" else puts "invalid" end
如果还要限制值的类型,直接在键后面加上类型约束即可:
case opts in value: Integer, limit?: Integer puts "valid" else puts "invalid" end
这种写法无需处理rest,直接通过模式本身约束了哈希只能包含指定的键,完全符合你的需求。
需要注意的是,limit?:表示该键可选但存在时必须符合约束;如果希望键完全可以不存在(不校验存在性),也可以写成limit: Integer | nil,效果是一致的。
内容的提问来源于stack exchange,提问作者stanley90
相关产品推荐
相关产品推荐

