2016-09-10 11 views
3

ruby​​は、最初の条件がfalseのときにif文を評価するのを止めますか? song = nilの場合、私はいつもundefined method `ready' for nil:NilClass>を取得します。ruby​​は、最初の条件がfalseの場合にif文を評価するのを止めますか?

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 
+2

エラーメッセージは、最初の 'elsif'に由来します。 – Stefan

+0

@Stefanあなたは正しいです、ありがとう – PoVa

+1

エラーの行番号を常に見てください;-) – Stefan

答えて

4

Rubyなどのプログラミング言語では、短絡ブール表現が使用されています。つまり、false && puts("hi")という形式の式は、式puts("hi")の右側を実行しません。これはifの条件にも同様に、何でも&&となります。

オペレーター&&の右側には、より速く安価な式/機能を左側に、より高価な式を常に入れたいので、これは特に重要です。

expensive_methodが常に実行される上記の例では、この

puts "hi" if expensive_method() && some_value 

を考えてみましょう。しかし、some_valueが間違っているとどうなりますか?これは、より効率的である:some_valueは時々偽かもしれないという可能性を活かし

puts "hi" some_value && expensive_method() 

、我々はこれらの例でexpensive_methodを評価することから自分自身を惜しま。

つまり、ブール式の短絡を利用します。最初の行で発生する例外については

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

4

song.readyが実行されたときに

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

songnilに等しくなければならないが、song.readyに到達するために、!song.nil?は真でなければならない、songではないという意味nil、矛盾。したがって、我々は最初のelsifが実行されるようにsongは、nilでなければならないと結論:等価です

elsif !song.ready 

elsif !(nil.ready) 

に例外を発生させます。

さらに一般的に、エラーメッセージには重要な情報が含まれており、慎重な検討が必要です。またあなたは、例外が発生した行を特定します。その時点でsongnilであることを示すエラーメッセージが表示されます。したがって、最初のステートメントでは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 

msgoutcometrueときnilです。メソッドの最初の3行は "ガード句"と呼ばれます。

1

他の2つの回答は、エラーが発生した理由を既に説明しています。これを修正するには、非常に簡単です。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の残りの部分に移動することができますsongnilである。

+0

最初の 'elsif'を最後に移動して、それをプレーンな' else'にすることができます。これにより、失敗アクションと成功アクションが分離されます。 – Stefan

関連する問題