【问题标题】:Prevent variable binding to nil in Ruby pattern matching?防止在 Ruby 模式匹配中将变量绑定到 nil?
【发布时间】:2021-03-08 05:00:18
【问题描述】:

在使用新的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 添加显式模式匹配是否有效?
  • NilClassnil 可以在这里互换使用,但我想要类似in variable: !NilClass
  • 读者:在case 声明中看到in 而不是when,我感到很困惑。我很快发现这个 模式匹配 是在 v2.7 中引入的,而文档显然首先出现在 v3.0.0 中。如果这对您也很陌生,您可能会发现 this article 提供了有用的介绍。
  • IMO 你的第二个选项看起来不错

标签: ruby pattern-matching


【解决方案1】:

匹配没有赋值的 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", 1, "matched NilClass"]

【讨论】:

  • 既然NilClass只有一个(ton)实例,为什么不直接使用nil呢?
  • @ChristopherOezbek 因为case 使用大小写相等运算符,而不是标准相等,我发现NilClass === argnil == nil 更清楚地表达了我的意图。请注意,您还可以对 String、Integer 等进行模式匹配,因此显式使用 NilClass 是一个有用的示例。您的语义意图可能会有所不同,但在这种特殊情况下,最终结果将是相同的。
猜你喜欢
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
  • 1970-01-01
  • 2018-09-23
  • 2021-07-24
  • 2015-04-25
  • 2013-08-15
  • 1970-01-01
相关资源
最近更新 更多