当第一个条件为假时,ruby是否会停止评估if语句?

时间:2016-09-10 15:54:28

标签: ruby

当第一个条件为假时,ruby是否会停止评估if语句?如果undefined method `ready' for nil:NilClass>,我会不断获得song = nil

    if !song.nil? && song.ready && !song.has_been_downloaded_by(event.author)
      song.send_to_user(event.author)
      nil
    elsif !song.ready
      "The song is not ready yet. Try again once it is."
    elsif song.has_been_downloaded_by(event.author)
      "Yo, check your private messages, I've already sent you the song."
    else
      'Song with such index does not exist.'
    end

3 个答案:

答案 0 :(得分:7)

Ruby,以及大多数其他编程语言都使用短路布尔表达式。意味着false && puts("hi")形式的任何表达式都不会运行表达式puts("hi")的右侧。这适用于if条件,任何&&的条件都是真的。

这一点非常重要,因为您总是希望在左侧放置更快或更便宜的表达式/函数,在&&运算符的右侧放置更昂贵的表达式。

考虑一下

puts "hi" if expensive_method() && some_value

在上面的示例中,expensive_method将始终运行。但是如果some_value有时是假的呢?这会更有效:

puts "hi" if some_value && expensive_method()

利用some_value有时可能错误的可能性,我们不必在这些情况下评估expensive_method

简而言之,利用布尔表达式短路。

https://en.wikipedia.org/wiki/Short-circuit_evaluation

答案 1 :(得分:4)

对于第一行中发生的异常:

if !song.nil? && song.ready && !song.has_been_downloaded_by(event.author)

执行song.ready时,song必须等于nil,但要达到song.ready!song.nil?必须为真,这意味着song是不是nil,这是一个矛盾。因此,我们得出结论:song必须为nil,因此执行第一个elsif

elsif !song.ready

相当于

elsif !(nil.ready)

提出异常。

更一般地说,错误消息包含有价值的信息,值得仔细研究。您的人也会识别发生异常的行。该错误消息告诉您song此时为nil。因此,它必须在第一个语句中为nil,因此第一个语句将评估nil

考虑将您的子句放在方法中并按如下方式重写。

def process_song(song)
  return nil, "song is nil" if song.nil?
  return false, "The song is not ready yet. Try again once it is." unless song.ready
  return false, "Yo, check your private messages, I've already sent you the song." \
    if song.has_been_downloaded_by(event.author)
  song.send_to_user(event.author)
  true
end

如下调用。

outcome, msg = process_song(song)

然后,或许类似于以下内容。

case outcome
when true
  ...
when false
  puts msg
  ...
when nil
  <raise exception with message that song is nil>
else
  <raise exception with message>
end
msgnil时,

outcometrue。该方法的前三行称为&#34;保护条款&#34;。

答案 2 :(得分:1)

另外两个答案已经提到了你收到错误的原因。要解决这个问题,这很简单,您只需要更改if语句的顺序即可。像这样:

if song.nil? 
  'Song with such index does not exist.'
elsif song.ready && !song.has_been_downloaded_by(event.author)
  song.send_to_user(event.author)
  nil
elsif !song.ready
  "The song is not ready yet. Try again once it is."
elsif song.has_been_downloaded_by(event.author)
  "Yo, check your private messages, I've already sent you the song."
end

现在,您正在检查第一个语句中是否song == nil,如果是true,则会收到消息Song with such index does not exist.现在,您可以转到其余的elsif {1}},无需担心songnil