No hay Boolean
tipo en Ruby; Ruby tiene una visión bastante simple de la verdad (o más precisamente, tiene una visión bastante simple de falsedad).
- el objeto
false
, que es la instancia singleton de FalseClass
se considera Falsy
- el objeto
nil
, que es la instancia singleton de NilClass
es Falsy
- todos los demás objetos es truthy (incluido, obviamente, el objeto
true
, que es la instancia única de TrueClass
)
[Por cierto: esto significa que una gran cantidad de objetos que se consideran Falsy en algunos otros idiomas, son en realidad Truthy en Ruby, al igual que el número entero 0
, el valor real 0.0
, la cadena vacía, la matriz vacía, el hash vacío, el carácter 'F'
]
Por lo tanto, los operadores booleanos &&
, ||
, and
y or
no devuelven valores booleanos. En su lugar, devuelven el primer objeto que determina el resultado de la expresión.
(También provocan un cortocircuito, lo que significa que solo evalúan las subexpresiones mínimas necesarias para determinar el resultado de la expresión. Por lo tanto, una formulación alternativa sería que devuelvan el resultado de la última expresión eso fue evaluado. Lo cual, a su vez, es análogo a lo que hacen los bloques, métodos, cuerpos de clase y cuerpos de módulos.)
Entonces, ¿qué significa decir para devolver el primer objeto que determina el resultado? Eso es simple, realmente: el resultado de la expresión
a && b
es Truthy si tantoa
y b
son Truthy, de lo contrario, es Falsy. Por lo tanto, si a
es Falsy, es completamente irrelevante lo b
es: el resultado será Falsy de cualquier manera. Por lo tanto, podríamos simplemente devolver a
. (Recuerde que una no tiene que ser false
, que también podría ser nil
y el programador puede querer saber cuál de los dos era.)
Si, otoh, a
es Truthy (OIA es ni nil
ni false
), a continuación, el resultado de toda la expresión es exclusivamente dependiente en b
: si b
es Truthy, todo el resultado será Truthy, de lo contrario si b
es Falsy, todo el resultado será falsy. Por lo tanto, también podríamos devolver b
, en lugar de convertirlo primero en un booleano.
||
y or
son análogos o más precisamente dual-&&
y and
.
el que has publicado este ejemplo: no
id = current_user && current_user.record.id
Aquí, el autor es aún esperando current_user
ser un valor booleano! En cambio, espera que sea User
o nil
. Pero eso está perfectamente bien, porque un User
es truthy y nil
es falsy, por lo que aún se pueden usar en una expresión booleana.
La intención básica es que el autor desea evitar que se produzca una excepción NoMethodError
, si intenta llamar al #record
en nil
.
Una forma alternativa de expresar esto sería
id = current_user.record.id unless current_user.nil?
Si desea que todos los detalles morbosos, echa un vistazo a la sección 11.1 (página 36) de los Draft ISO Ruby Specification o las especificaciones del excutable RubySpec project. (Here's the one for &&
.)
Escribí pure Ruby implementation of Ruby's Boolean operators and conditional expressions una vez por diversión. La carne de las implementaciones es estos twomixins.
Interesante.En PHP y en algunos otros lenguajes, a menudo uso booleanValue = booleanExpression1 && booleanExpression2 y, en función de la evaluación de la expresión "y", booleanValue se configurará correctamente. ¿Entonces esto no es posible con Ruby? –
PHP y otros C-me gusta cortocircuitan sus && s también. Cuando usa booleanos, los resultados son los que espera, pero cuando tiene tipos de objetos y tipos dinámicos, se encuentra en la zona específica del idioma. –
Además, si X (current_user) es falso (supongo que esto significa que current_user no está configurado - nil?), ¿Id se establecerá en falso en lugar de int (el valor de current_user.record.id)? –