Estoy buscando una forma concisa de verificar un valor para ver si es nulo o cero. Actualmente estoy haciendo algo como:
if (!val || val == 0)
# Is nil or zero
end
Pero esto parece muy torpe.
Respuestas:
¿Los objetos tienen un cero? método .
if val.nil? || val == 0
[do something]
end
O, para una sola instrucción:
[do something] if val.nil? || val == 0
or
no requiere ningún parens aquí, y se leerá de forma completamente natural para un rubyista experimentado. Las únicas personas que alguna vez son mordidas por ||
versus or
son las personas que nunca han programado Perl :)
val && val == 0
es mejor.
Si realmente te gustan los nombres de métodos con signos de interrogación al final:
if val.nil? || val.zero?
# do stuff
end
Su solución está bien, al igual que algunas de las otras soluciones.
Ruby puede hacerte buscar una manera bonita de hacer todo, si no tienes cuidado.
Desde Ruby 2.3.0 en adelante, puede combinar el operador de navegación segura ( &.
) con Numeric#nonzero?
. &.
devuelve nil
si la instancia fue nil
y nonzero?
- si el número fue 0
:
unless val&.nonzero?
# Is nil or zero
end
O sufijo:
do_something unless val&.nonzero?
unless val&.nonzero?
traduce como "si val es nulo o cero"
do_something if val&.nonzero?
(también conocido como si val
no es nil
y no es cero).
En primer lugar, creo que esa es la forma más concisa de verificar esa condición en particular.
En segundo lugar, para mí, este es un olor a código que indica una falla potencial en su diseño. Generalmente, cero y cero no deberían significar lo mismo. Si es posible, debe intentar eliminar la posibilidad de que val sea nulo antes de acceder a este código, ya sea verificándolo al principio del método o mediante algún otro mecanismo.
Es posible que tenga una razón perfectamente legítima para hacer esto, en cuyo caso creo que su código es bueno, pero al menos consideraría intentar deshacerse de la verificación nula si es posible.
¿Puede utilizar Object.nil? para probar nil específicamente (y no quedar atrapado entre falso y nil). También puede parchear un método en Object.
class Object
def nil_or_zero?
return (self.nil? or self == 0)
end
end
my_object = MyClass.new
my_object.nil_or_zero?
==> false
Esto no se recomienda ya que los cambios en Object son difíciles de rastrear para los compañeros de trabajo y pueden hacer que su código sea impredecible para otros.
nil?
siempre devolverá falso. nil?
solo devuelve verdadero en NilClass.
Object
, NilClass
y Numeric
. Object
volvería false
, NilClass
volvería true
y Numeric
volvería zero?
.
nil.to_i devuelve cero, así que a menudo hago esto:
val.to_i.zero?
Sin embargo, obtendrá una excepción si val alguna vez es un objeto que no responde_to #to_i.
"5".to_i == 5, but you're more or less right. Clever but doesn't actually work
Creo que tu código es incorrecto; lo hará en la prueba de hecho para tres valores: nil
, false
y cero. Esto se debe a que la !val
expresión es verdadera para todos los valores que son falsos, que en Ruby es nil
y false
.
Lo mejor que se me ocurre ahora mismo es
if val == nil || val == 0
# do stuff
end
Lo cual, por supuesto, no es muy inteligente, pero (muy) claro.
Mi solución también usa Refinamientos, menos los condicionales.
module Nothingness
refine Numeric do
alias_method :nothing?, :zero?
end
refine NilClass do
alias_method :nothing?, :nil?
end
end
using Nothingness
if val.nothing?
# Do something
end
Rails hace esto a través de métodos de consulta de atributos, donde además de falso y nulo, 0 y "" también se evalúan como falso.
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
Sin embargo, tiene su parte de detractores. http://www.joegrossberg.com/archives/002995.html
#attribute
, porque no puedo encontrar nada de eso.
Para ser lo más idiomático posible, sugiero esto.
if val.nil? or val == 0
# Do something
end
Porque:
Corto y claro
[0, nil].include?(val)
val.in? [0,nil]
El camino más corto y mejor debe ser
if val&.>(0)
# do something
end
Porque val&.>(0)
devuelve nil cuando val es nil ya que> básicamente también es un método, nil es igual a falso en ruby. Devuelve falso cuando val == 0
.
Me ocupo de esto definiendo un "¿es?" método, que luego puedo implementar de manera diferente en varias clases. Entonces, para Array, "es?" significa "tamaño> 0"; para Fixnum significa "self! = 0"; para String significa "self! = ''". NilClass, por supuesto, define "es?" como devolver nada.
Puede usar case
si lo desea:
case val with nil, 0
# do stuff
end
Entonces puedes usar cualquier cosa que funcione ===
, lo cual a veces es bueno. O haz algo como esto:
not_valid = nil, 0
case val1 with *not_valid
# do stuff
end
#do other stuff
case val2 with *not_valid, false #Test for values that is nil, 0 or false
# do other other stuff
end
No es exactamente una buena OOP, pero es muy flexible y funciona. Mis if
s suelen terminar comocase
todos modos, s.
Por supuesto Enum.any?
/ Enum.include?
también funciona ... si te gusta ser realmente críptico:
if [0, nil].include? val
#do stuff
end
Por supuesto, lo correcto es definir un método o función. O, si tiene que hacer lo mismo con muchos valores, use una combinación de esos buenos iteradores.
Me gusta mucho los carriles blank?
no método para ese tipo de cosas, pero va a volver true
a 0
. Entonces puedes agregar tu método:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
Y comprobará si algún valor es nulo o 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
En lugar de mono parchear una clase, puede usar mejoras a partir de Ruby 2.1. Los refinamientos son similares al parche de mono; en eso, le permiten modificar la clase, pero la modificación se limita al alcance en el que desea usarla.
Esto es excesivo si desea hacer esta verificación una vez, pero si lo repite, es una excelente alternativa a los parches de monos.
module NilOrZero
refine Object do
def nil_or_zero?
nil? or zero?
end
end
end
using NilOrZero
class Car
def initialize(speed: 100)
puts speed.nil_or_zero?
end
end
car = Car.new # false
car = Car.new(speed: nil) # true
car = Car.new(speed: 0) # true
Los refinamientos se cambiaron en el último minuto para ajustarse al alcance del archivo. Así que los ejemplos anteriores pueden haber demostrado esto, lo que no funcionará.
class Car
using NilOrZero
end
Esto es muy conciso:
if (val || 0) == 0
# Is nil, false, or zero.
end
Funciona siempre que no le importe tratar false
lo mismo que nil
. En los proyectos en los que he trabajado, esa distinción solo importa de vez en cuando. El resto del tiempo, personalmente prefiero omitir .nil?
y tener un código un poco más corto.
[ Actualización : ya no escribo este tipo de cosas. Funciona pero es demasiado críptico. He tratado de corregir mis fechorías cambiando los pocos lugares donde lo hice].
Por cierto, no lo usé .zero?
ya que esto genera una excepción si val
es, digamos, una cadena. Pero .zero?
estaría bien si sabe que ese no es el caso.
[edited]
Pensé que si val
era nulo, esta expresión se evaluaría nil == 0
(y, por lo tanto, regresaría false
). Sin embargo, parece que funciona, aunque no creo que sea muy legible.
Otra solución:
if val.to_i == 0
# do stuff
end
"5".to_i == 5
, pero tienes más o menos razón. Inteligente pero en realidad no funciona.
val ||= 0
if val == 0
# do something here
end
val
es necesario mantener el valor en ? Estás superando los datos de entrada con este método, y hay formas mejores y menos destructivas de verificar cero o cero.
false
?