2010-06-21 13 views
11

Nie rozumiem następujący kod (x!):jeśli vs if (x == false) w Ruby

ruby-1.9.1-p378 > puts "nil is false" unless nil 
nil is false 
=> nil 
ruby-1.9.1-p378 > puts "nil isn't false" unless nil == false 
nil isn't false 
=> nil 

w większości języków (z C-bazy, co najmniej), jeśli (! cond) i jeśli (cond == false) oceni to samo. Co się tutaj dzieje, żeby tego nie robić?

(Chciałbym szczegóły dlaczego, rozumiem, że to jest jak jest.)

Odpowiedz

31

Ruby uważa, że ​​false i nil to jedyne dwie wartości "falsyfikacyjne", podczas gdy wszystko inne jest "prawdą". Jest to z definicji i nie można go modyfikować (przynajmniej w MRI). Definicja ta jest stosowana do wszystkich wbudowanych operatorów jak if, unless, while, until, cond ? if_truthy : if_falsey, ||, && ...

Pisanie foo == bar zawsze wywołać metodę == na foo z bar jako argument. Domyślnie, nil, false, true i wszystkie inne od zaraz, takie jak symbole, itp., Są równe sobie. To może być zmieniony, choć:

def nil.==(bar) 
    super || bar == false 
end 
puts "nil == false" if nil == false # => "nil == false" 

W Ruby 1.9, można również przedefiniować operatora !, więc unless foo niekoniecznie jest taka sama jak if !foo lub sprzeczne z if foo:

def true.! 
    true 
end 

puts "True?" if true # => "True?" 
puts "or not?" if !true # => "or not?" 

Nie dlatego, że ktokolwiek poleciłby robić coś takiego ...

+0

zero nie jest * faktycznie fałszywe *, to tylko * falsey *. Idealne wyjaśnienie. +1. I tak, proszę nie przesłonić == lub! lub cokolwiek, jeśli nie masz bardzo dobrego powodu. – MatrixFrog

+0

+1 za dobrą odpowiedź. To samo dotyczy PHP, który musiał wymyślić operatora '===' (tak, to jest * trzy * '='). – Mawg

+0

Dziękuję bardzo za wyjaśnienie. –

2

nil nie jest równa false porównaniu nad == ponieważ ich zawartość semantyczna jest inna (nil ma informacji, false jest wartością logiczną). Jeśli jednak spróbujesz oszacować wartość nil w kontekście boolowskim, zostanie ona uznana za fałszywą, głównie ze względu na wygodę i idiomatyczną zgodność z innymi językami.

nil == a <=> nil != a <=> false będzie dotyczyć praktycznie każdej wartości oprócz zerowej.

Można więc powiedzieć tylko, że "zero nie jest prawdziwe", a "zero to zero". Dotyczy to rubinu.

0

W niektórych językach można używać tylko bajtów w instrukcjach "if". Próba sprawdzenia, czy ciąg znaków lub liczba jest prawdą czy fałszem, jest po prostu głupi i pozbawiony znaczenia, więc język nie pozwoli ci tego zrobić.

W Ruby jednak wszystko można uważać za boolowskie, nawet jeśli tak naprawdę nie jest. W rzeczywistości wszystko w Ruby jest skuteczne, z wyjątkiem zer i fałsz (IIRC). Nie znaczy to, że zero jest w rzeczywistości RÓWNE do fałszywego, tak jak nie oznacza to, że liczba całkowita 45 jest rzeczywiście RÓWNA prawdą. Są różne, oddzielne, rzeczy. Ale jeśli zamierzasz traktować zero jak boolean (to znaczy używać go w razie lub nie), to jest tak, jakby było fałszywe.