防止变量绑定到 Ruby 模式匹配中的 nil?

问题描述

在使用新的 case ... in pattern matching in Ruby 时,有没有好的方法可以防止将 nil 绑定到变量?

case method()
in ... # Some cases here
  ...
in ...
  ...
in variable # If prevIoUs clauses did not match,then capture to variable
  puts variable
else # How to prevent that variable also captures nil?
  puts "Nil" # -> This is not called if method() returns nil
end

我发现了以下两种方法,但它们看起来有点难看:

1.) 使用 if 限定符

case method()
in ... # Some cases here
  ...
in ...
  ...
in variable if variable
  puts variable
else 
  puts "Nil"
end

2.) 反向匹配顺序

case method()
in ... # Some cases here
  ...
in ...
  ...
in nil
  puts "Nil"
in variable # Catch all
  puts variable
end

有什么更好的吗?


这也能用吗?这将提供一种使用单行模式匹配表达式对 nil 进行比较和赋值的好方法

if method() => variable
  ... 
end

(这个问题的灵感来自于a question on assignments in if statements

解决方法

匹配无赋值的 NilClass

如果您决定忽略 nil,您可以通过简单地匹配 NilClass 然后不分配结果来实现。在调用 as-pattern(例如 in variable)或 else 子句之前执行此操作。例如:

# arg can be assigned `nil` but can't be unassigned; this
# ensures that any nil values were actually passed in
def pattern_match arg
  case arg
  in /^a$/ => bar
  in NilClass
  in bar
  end

  # We print a message here to differentiate between arg and
  # bar being `nil`,because otherwise the method simply
  # returns `nil` since bar is auto-vivified by the
  # interpreter when it evaluates the case statement. This is
  # a potential source of confusion when looking at the
  # results.
  bar || 'matched NilClass'
end

# pass values through a scope gate for testing each
# assignment to bar in isolation
[?a,'str',1,nil].map { pattern_match _1 }
#=> ["a","str","matched NilClass"]