what the template strategy patterns pattern observer are ruby design-patterns idioms null

the - Mejor frase de ruby para "cero o cero"



the strategy design pattern (19)

Corto y claro

[0, nil].include?(val)

Estoy buscando una forma concisa para 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.


Creo que tu código es incorrecto; de hecho, probará tres valores: nil , false y cero. Esto se debe a que la expresión !val es verdadera para todos los valores que son falsos, lo que en Ruby es nil y false .

Lo mejor que se me ocurre en este momento es

if val == nil || val == 0 # do stuff end

Lo cual por supuesto no es muy inteligente, pero (muy) claro.


Desde Ruby 2.3.0 en adelante, puede combinar el operador de navegación segura ( &. ) Con Numeric#nonzero? . &. devuelve nil si la instancia era nil y nonzero? - si el número era 0 :

unless val&.nonzero? # Is nil or zero end

O postfix:

do_something unless val&.nonzero?


En lugar de parchear mono en una clase, puedes usar refinamientos comenzando en Ruby 2.1. Los refinamientos son similares a los parches de mono; en eso, le permiten modificar la clase, pero la modificación se limita al ámbito en el que desea usarla.

Esto es excesivo si quiere hacer este control una vez, pero si se repite a sí mismo es una gran alternativa al parche 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 modificaron en el último minuto para ubicarlos en el archivo. Así que los ejemplos anteriores pueden haber demostrado esto, lo cual no funcionará.

class Car using NilOrZero end


En primer lugar, creo que es la forma más concisa en la que puede verificar esa condición en particular.

En segundo lugar, para mí este es un olor de código que indica un defecto potencial en su diseño. En general, cero y cero no deberían significar lo mismo. Si es posible, debe intentar eliminar la posibilidad de que val sea nulo antes de presionar este código, ya sea verificándolo al comienzo del método o mediante algún otro mecanismo.

Puede que tenga una razón perfectamente legítima para hacerlo, en cuyo caso creo que su código es bueno, pero al menos consideraría tratar de deshacerse de la comprobación nula si es posible.


Esto es muy conciso

if (val || 0) == 0 # Is nil, false, or zero. end

Funciona siempre y cuando no te importe tratar lo false la misma manera que nil . En los proyectos en los que he trabajado, esa distinción solo importa de vez en cuando. El resto del tiempo yo personalmente prefiero saltear .nil? y tiene un código ligeramente más corto.

[ Actualización : ya no escribo este tipo de cosas. Funciona, pero es demasiado críptico. Intenté corregir mis errores cambiando los pocos lugares donde lo hice.]

Por cierto, no .zero? ya que esto genera una excepción si val es, por ejemplo, una cadena. Pero. .zero? estaría bien si sabes que no es el caso.


Esto se evalúa como verdadero para cero y cero: nil.to_s.to_d == 0


La forma más corta y mejor debería ser

if val&.>(0) # do something end

Para val&.>(0) devuelve nil cuando val es nil ya que> básicamente es también un método, nil igual a false en ruby. Devuelve falso cuando val == 0 .


Los objetos tienen un nil? método .

if val.nil? || val == 0 [do something] end

O, para una sola instrucción:

[do something] if val.nil? || val == 0


Me ocupo de esto al definir 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?" simplemente devolviendo nil.


Otra solución:

if val.to_i == 0 # do stuff end


Para ser lo más idiomático posible, sugeriría esto.

if val.nil? or val == 0 # Do something end

Porque:

  • Utiliza el nil? método.
  • Utiliza el operador "or", que es preferible a ||.
  • No usa paréntesis, que no son necesarios en este caso. Los paréntesis solo deben usarse cuando sirven para algún propósito, como anular la precedencia de ciertos operadores.

Puede usar case si lo desea:

case val with nil, 0 # do stuff end

Entonces puedes usar cualquier cosa que funcione con === , lo que 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 un buen OOP, pero es muy flexible y funciona. Mi if usualmente termina como case todos modos.

Por supuesto Enum.any? / Enum.include? también funciona ... si te gusta ser críptico:

if [0, nil].include? val #do stuff end

Lo correcto es, por supuesto, definir un método o función. O bien, si tiene que hacer lo mismo con muchos valores, use una combinación de esos simpáticos iteradores.


Puedes usar Object.nil? para probar nulo específicamente (y no quedar atrapado entre falso y nulo). También puedes aplicar un parche a un método en Objeto.

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 Objeto son difíciles de rastrear para los compañeros de trabajo y pueden hacer que su código sea impredecible para otros.


Rails lo hace a través de métodos de consulta de atributos, donde además de falso y nulo, 0 y "" también evalúan a 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


Realmente me gusta Rails en blank? método para ese tipo de cosas, pero no regresará true para 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


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 forma bonita de hacer todo, si no tienes cuidado.


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 a # a_i.


val ||= 0 if val == 0 # do something here end