Ruby 应用程序使用 When/Case 在不应该产生 Nil 时产生 Nil

Ruby Application using When/Case yielding Nil when it shouldn't

提问人:Panamaniac507 提问时间:3/30/2023 最后编辑:Todd A. JacobsPanamaniac507 更新时间:3/30/2023 访问量:135

问:

以下代码应根据任何检查的结果打印给定的三个选项之一,但事实并非如此。它产生通过 提供的任何your_message值。有人可以告诉我我的代码有什么问题吗?==nilgets.chomp

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
ruby 条件语句 switch-statement 比较 相等

评论

0赞 pjs 3/30/2023
所以你想检查的内容是否等于一个或值?我认为您需要回去重新阅读有关.include?案例的文档。your_messagetruefalse
0赞 Panamaniac507 3/30/2023
嗨,pjs...感谢您的反馈。除了阅读文档外,我还想与我的前辈/同龄人进行对话,以了解错误或错误......我知道 include 和 case 是如何工作的,但我不知道的是,为什么在我当前的上下文中,代码没有按预期运行。有什么想法吗?谢谢。
0赞 pjs 3/30/2023
“我知道包含和案例是如何工作的”。对不起,但这显然不是真的。因此,我建议查看文档。
2赞 Todd A. Jacobs 3/30/2023
编辑中的显式返回是不必要的。另外,以使现有答案无效的方式从根本上改变您的问题被认为是糟糕的 SO 礼仪。正确的做法通常是打开一个相关问题,如果您有单独的后续问题,该问题会链接到原始问题。
1赞 Panamaniac507 3/30/2023
嗨,托德,非常感谢您的宝贵评论......我设法让它工作。你的陈述是绝对正确的......问题是我的支票顺序......这是关键。当然,事实上,我之前将字符串与布尔值进行比较......非常感谢您的大力和耐心支持。

答:

0赞 Chris 3/30/2023 #1

在表达式中,将值与值进行比较。casewhen

在您的示例中,您正在将哪个可能是字符串与布尔值进行比较。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

虽然我不确定你是否真的想退出程序,如果你的代码命中,方法本身将返回。exitnil

如果您希望它返回字符串而不是打印它们:

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

评论

0赞 Panamaniac507 3/30/2023
谢谢你们...我按如下方式优化了我的代码,但是当使用以下测试字符串时,TEST!并且测试没有按照我的代码产生正确的结果......
3赞 Todd A. Jacobs 3/30/2023 #2

大小写表达式和 Threequals

案例表达式并不像您想象的那样工作。这不仅仅是表达 if/then 条件的另一种方式。在后台,case 在将参数传递给 case 时在表达式上实现运算符,或者允许您在不传递初始参数时像一组 if 语句一样使用它。它也进行模式匹配,但这超出了这个问题的范围。===

将参数拖放到控件表达式中

当您向 case 提供参数时,例如,每个 when 语句都将使用特定于类的 threequals 而不是您认为要给出的条件来评估为针对参数的表达式。通过将参数删除到 case 中,可以很容易地解决此问题。例如:case your_message

your_message = "foo?"

case
when your_message.end_with?("?")
  "bar"
end

#=> "bar"

现在,Ruby 不是有效地说(这显然会返回)而是简单地评估 when 语句是否真实。根据现有代码,这可能是获得预期行为的最简单方法。"foo?" === truefalse

将 Proc、Lambda 或正则表达式与 Threequals 结合使用

或者,您可以重构 case 语句以使用 procs、lambda 甚至正则表达式,这些表达式可以匹配 threequal 比较,因为它是由类实现的。例如,请考虑以下示例,该示例利用 Proc#=== 来比较 lambda 的结果。

your_message = "foo? \n"

case your_message
when ->{ _1.strip.end_with? "?" }
  "baz"
end

#=> "baz"

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

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

your_message = "foo?"

case your_message
when /\?$/
  "quux"
end

#=> "quux"

代码的其他问题

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

一个工作的例子

以下内容要简单得多,并且工作正常。它返回有效结果,并且不会返回 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 语句的顺序正确,并且使用正确的表达式类型进行比较,就可以让大小写表达式执行您想要的操作,但不一定是以您最初期望的方式。

评论

0赞 Panamaniac507 3/30/2023
嗨,托德...您的评论非常有用,非常感谢。我已经重新订购了我的 WHEN 箱子......但是,我的“当your_message.upcase & & your_message.include?("!")"未按预期工作...基本上,当测试字符串为“test!”时,它会返回表达式,这是不正确的......仅当满足两个条件时,它才应返回表达式。这是“测试!有什么想法吗?非常感谢,
1赞 Todd A. Jacobs 3/30/2023
@Panamaniac507 如果您想要详细的答案,则需要就此单独提出一个问题。简而言之,您的第一个表达式不返回布尔值。你可能想要 ,但如果没有看到完整的上下文,就很难说。Ruby 中几乎所有的东西都是一个表达式,因此理解真实性、优先级和比较表达式是必不可少的。为此,您可能希望坚持使用 if 语句,因为它们更符合您对代码的思考方式。when your_message.eql?(your_message.upcase) && your_message.end_with?("!")