Brak typu Boolean
w języku Rubin; Ruby ma dość prosty pogląd na prawdę (a dokładniej, ma dość prosty widok na kłamstwo).
- przedmiotem
false
, która jest pojedyncza wystąpienie FalseClass
jest uważany falsy
- obiektu
nil
, która jest pojedyncza wystąpienie NilClass
jest falsy
- każdy obiekt jest truey (w tym, oczywiście, obiekt
true
, który jest instancją singleton TrueClass
)
[BTW: oznacza to, że wiele obiektów, które są uważane za falsy w innych językach, są rzeczywiście truthy w Ruby, jak całkowita 0
, realnej wartości 0.0
, pustym ciągiem, The pusta tablica, pusty hash, postać 'F'
]
Więc operatorów logicznych &&
, ||
, and
i or
nie zwracają wartości logiczne. Zamiast tego zwracają pierwszy obiekt, który określa wynik wyrażenia.
(Są również przyczyną zwarcia, co oznacza, że oceniają tylko minimalne podwyrażenia, które są potrzebne do ustalenia wyniku wyrażenia. Tak więc alternatywnym sformułowaniem byłoby zwrócenie wyniku ostatniego wyrażenia który został oceniony, co z kolei jest analogiczne do tego, co robią bloki, metody, ciała klas i ciała modułów.)
Co to jest znaczy, aby zwrócić pierwszy obiekt, który określa wynik? To naprawdę proste: wynik wyrażenia
a && b
jest truthy jeśli zarównoa
i b
są truthy, w przeciwnym razie jest falsy. Tak więc, jeśli a
jest falsy, to całkowicie znaczenia co b
jest: wynik będzie falsy w obu kierunkach. Więc równie dobrze możemy po prostu zwrócić a
. (Pamiętaj, że nie musi być false
, może to również być nil
a programista może chcieć wiedzieć, który z nich było.)
Jeżeli OTOH, a
jest truthy (IOW jest ani nil
ani false
), to wynik całego wyrażenia jest wyłącznie zależne b
: jeśli b
jest truthy, cały wynik będzie truthy, w przeciwnym razie, jeśli b
jest falsy, cały wynik będzie falsy. Tak więc równie dobrze możemy zwrócić samą siebie, zamiast najpierw przekonwertować ją na wartość logiczną.
||
i or
są analogiczne lub bardziej precyzyjnie podwójny do &&
i and
.
Ty pisał ten przykład: nawet nie
id = current_user && current_user.record.id
Tutaj autor spodziewacurrent_user
być wartość logiczna! Zamiast tego spodziewa się, że będzie to albo User
lub nil
. Ale to jest całkiem w porządku, ponieważ jest pewna, że nadal mogą być używane w wyrażeniu Boolean.
Podstawową intencją jest to, że autor chce zapobiec zgłoszeniu wyjątku NoMethodError
, jeśli próbuje wywołać #record
na nil
.
Alternatywnym sposobem wyrażania byłoby
id = current_user.record.id unless current_user.nil?
Jeśli chcesz wszystkie drastyczne szczegóły, sprawdź rozdział 11.1 (strona 36) Draft ISO Ruby Specification lub plikiem wykonywalnym specyfikacji RubySpec project. (Here's the one for &&
.)
Raz napisałem pure Ruby implementation of Ruby's Boolean operators and conditional expressions dla zabawy. Mięso z wykonań jest następujące: twomixins.
Interesujące.W PHP i kilku innych językach często używałem wartości booleanValue = booleanExpression1 && booleanExpression2, a na podstawie oceny wyrażenia "i" wartość booleanValue zostanie odpowiednio ustawiona. Więc nie jest to możliwe z Ruby? –
PHP i inne C-lubi zwarcie ich && s też. Gdy używasz wartości logicznych, wyniki są takie, jakich oczekujesz, ale gdy masz typy obiektów i typy dynamiczne, jesteś w strefie specyficznej dla języka. –
Ponadto, jeśli X (current_user) jest fałszywe (zakładam, że oznacza to, że current_user nie jest ustawione - zero?), To id będzie ustawione na wartość false zamiast na int (wartość current_user.record.id)? –