Prevent variable binding to nil in Ruby pattern matching?

Viewed 157

When utilizing the new case ... in pattern matching in Ruby, is there a nice way to prevent binding of nil to a variable?

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

I have found the following two ways but they kind of seem ugly:

1.) Use if qualifier

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

2.) Reverse match order

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

Is there something nicer?


How could this also be used? It would allow a nice way to do comparison and assignment against nil using the one-line pattern matching expression:

if method() => variable
  ... 
end

(This question was inspired by a question on assignments in if statements)

1 Answers

Match NilClass Without Assignment

If you've decided that nil should be ignored, you can do it by simply matching against NilClass and then not assigning the result. Do this before calling your as-pattern (e.g. in variable) or an else clause. For example:

# 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"]
Related