当第一个条件为假时,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
答案 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
。
简而言之,利用布尔表达式短路。
答案 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
当msg
为nil
时, outcome
为true
。该方法的前三行称为&#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}},无需担心song
是nil
。