Ruby 应用程序使用时间/案例在不应该产生 nil 时产生 nil



下面的代码应该根据任何==检查的结果打印给定的三个选项之一,但是它没有。对于通过gets.chomp提供的your_message的任何值,它产生nil。有人能告诉我我的代码有什么问题吗?

def stupid_coach(your_message)
case your_message
when your_message == your_message.include?("?")
p "Silly question, get dressed and go to work!"
when !your_message == your_message.include?("?")
p "I don't care, get dressed and go to work!"
when your_message == "I am going to work now!"
exit
end
end

大小写表达式和三个等号

case表达式并不像你想象的那样工作。它不仅仅是表达if/then条件的另一种方式。在底层,case在向case传递参数时在表达式上实现===操作符,或者如果没有传递初始参数,则允许您像使用一组if语句一样使用它。它也可以进行模式匹配,但这超出了这个问题的范围。

删除控件表达式的参数

当您为case提供参数时,例如case your_message,则每个When -语句将使用特定于类的三等号而不是您认为提供的条件,作为表达式对参数进行计算。这很容易通过去掉参数case来修复。例如:

your_message = "foo?"
case
when your_message.end_with?("?")
"bar"
end
#=> "bar"

现在,Ruby没有有效地说"foo?" === true(显然会返回false),而是简单地计算when-语句是否为真。基于您现有的代码,这可能是获得您期望的行为的最简单方法。

使用Proc, Lambda或Regexp与Threequals

或者,您可以重新构建case语句,以使用procs、lambdas甚至正则表达式来匹配三等于比较,因为它是由类实现的。例如,考虑下面的例子,它利用proc# ===来比较lambda的结果。

your_message = "foo? n"
case your_message
when ->{ _1.strip.end_with? "?" }
"baz"
end
#=> "baz"

这基本上是将参数传递给case(例如your_message)到lambda,然后您可以在该参数上调用方法来评估其真实性。这是一种更复杂的方法,但也很有用。

由于正则表达式也支持threequals方法,因此您也可以使用它们:

your_message = "foo?"
case your_message
when /?$/
"quux"
end
#=> "quux"

代码的其他问题

你还应该考虑顺序依赖之类的事情。在您的示例代码中,即使没有其他问题,"I am going to work now!"也永远不会匹配,因为前面的when-语句(如果工作的话)将在您到达特定比较之前根据问号的存在或不存在返回一个值。大小写表达式不会"跳过"。就像在其他语言中一样,所以你需要考虑语句优先级,就像你在if/elsif/else/end控制表达式中一样。

工作实例

下面的代码要简单得多,而且工作得很好。它返回有效的结果,不会返回nil。它并不假设your_message可以#respond_to?(:strip),但是如果您愿意,您可以进一步调整代码。

def stupid_coach your_message
case your_message.strip
when "I am going to work now!"
"This works when checked before matching for '?'."
when /?$/
"Silly question, get dressed and go to work!"
else
"I don't care, get dressed and go to work!"
end 
end                                                                             

您可以针对一组示例输入对其进行测试。对我来说,结果似乎是有效的,但如果您认为存在极端情况,您当然可以对其他String值进行练习。

["Foo?", "Bar.", "I am going to work now!"]
.map { stupid_coach _1 }
#=> 
["Silly question, get dressed and go to work!",
"I don't care, get dressed and go to work!",
"This can match if checked before mactching for '?'."]

执行样品的顺序并不重要。如果对测试数组重新排序,仍然可以得到正确的结果。只要when语句的顺序是正确的,并且使用了正确的表达式类型进行比较,就可以让case表达式做您想做的事情——只是不一定按照您最初期望的方式。

case表达式中,when将值与值进行比较。

在您的情况下,您正在比较your_message,这可能是一个字符串,布尔值。

考虑一个非常简单的例子:

irb(main):001:1* case "hello"
irb(main):002:1* when true
irb(main):003:1*   puts "foo"
irb(main):004:1* else
irb(main):005:1*   puts "bar"
irb(main):006:0> end
bar
=> nil          

您可以使用正则表达式或匹配字符串。

def stupid_coach(your_message)
case your_message
when "I am going to work now!"
exit
when /?/
p "Silly question, get dressed and go to work!"
else
p "I don't care, get dressed and go to work!"
end
end

虽然我不确定你是否真的想退出程序的方式,你的代码将,如果它击中exit,方法本身将返回nil

如果你想让它返回字符串而不是打印它们:

def stupid_coach(your_message)
case your_message
when "I am going to work now!"
exit
when /?/
"Silly question, get dressed and go to work!"
else
"I don't care, get dressed and go to work!"
end
end

相关内容

  • 没有找到相关文章

最新更新