2017-07-19 30 views
5

Mam złą wartość w bardzo prosty kawałek (tak myślałem) o kodzie:Nieoczekiwany przypadek zachowanie w Ruby

org = 4 
case org 
when org <= 1 
    val = 'L' 
when 2..3 
    val = 'M' 
when org >= 4 
    val = 'H' 
end 

puts val 
=> nil 

Proszę, nie gniewaj się, spodziewam się, że brakowało mi coś bardzo oczywistego, ale naprawdę nie mogę tego rozgryźć. Dzięki.

Odpowiedz

7

To jest klasyczny błąd Ruby. case ma dwie metody wywoływania: jedną, w której przekazujesz coś do gałęzi na podstawie i jedną, w której nie.

Jeśli zrobić określić wyraz w oświadczeniu case następnie wszystkie pozostałe warunki są oceniane i porównywane z ===. W tym przypadku wartość org <= 1 jest niższa niż false, a org === false oczywiście nie jest prawdą. To samo dotyczy wszystkich innych przypadków, są one albo prawdziwe, albo fałszywe. Oznacza to, że żaden z nich nie pasuje.

Jeśli nie określisz wyrażenia, wówczas case zachowuje się jak fantazyjne if.

Przełącznik case org na case i działa. Można również przełączyć na zakresy:

val = 
    case org 
    when 0..1 
    'L' 
    when 2..3 
    'M' 
    else 
    'H' 
    end 

Sposób oryginalny kod wykonywany jest tak, jakby były:

org = 4 
if (org <= 1) === org 
    val = 'L' 
elsif (2..3) === org 
    val = 'M' 
elsif (org >= 4) === org 
    val = 'H' 
end 

co nie jest to, co chcesz.

+0

Dziękuję człowieku, działa !!!!! jeśli będziesz taki miły - włóż mój nos do dokumentacji, która wyjaśni mi to. –

+1

@ S.ork Od [the docs] (http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-case): "Pierwszy klauzulę when, aby dopasować warunek (lub ocena do Boolowskiej prawdy, jeśli warunek jest zerowy) "wygrywa", a jej sekcja kodu jest wykonywana " –

+0

@AndrewPiliser to nie pomaga, w moim przypadku tylko trzecia klauzula jest oceniana na true, ale nigdy nie jest wykonywana. –

2

Jako alternatywę można napisać:

letters = %w(L L M M H) 
val = letters[org.clamp(0,4)] 

Wykorzystuje Comparable#clamp, która pochodzi z Ruby 2.4.

Ruby 2.3 i starszych, można użyć:

val = letters[[0, org, 4].sort[1]] 

ten sposób, to jest w porządku, jeśli org jest mniejsza lub większa niż 04.