下面的代码应该根据任何==
检查的结果打印给定的三个选项之一,但是它没有。对于通过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),但是如果您愿意,您可以进一步调整代码。 您可以针对一组示例输入对其进行测试。对我来说,结果似乎是有效的,但如果您认为存在极端情况,您当然可以对其他String值进行练习。 执行样品的顺序并不重要。如果对测试数组重新排序,仍然可以得到正确的结果。只要when语句的顺序是正确的,并且使用了正确的表达式类型进行比较,就可以让case表达式做您想做的事情——只是不一定按照您最初期望的方式。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
["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 '?'."]
在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