Ruby: si variable vs si variable.nil?

11

Soy nuevo en Ruby y me sorprendí cuando descubrí que todos los objetos son verdaderos, aparte de nulo y falso. Incluso 0 es cierto.

Lo bueno de esa propiedad del lenguaje es que puedes escribir:

if !variable
  # do stuff when variable is nil
end

Mis colegas, que son desarrolladores más experimentados de Ruby, insisten en que debería elegir eso en lugar de usar .nil. al igual que:

if variable.nil?
  # do stuff when variable is nil
end

Sin embargo, creo que esta última es una mejor opción por dos razones: 1. Creo que está más orientada a objetos, especialmente en un lenguaje como Ruby, donde todo es un intercambio de objetos y mensajes. 2. En mi opinión, es más legible, incluso si es menos compacto.

¿Estoy cometiendo un error de "novato" aquí?

Javier Holguera
fuente
44
¿Estás probando para nada? o un valor falso?
Estoy probando para nada. Básicamente, si la variable es nula, hago algo (o no)
Javier Holguera
3
Si está haciendo una prueba de nulo, ¿por qué quiere que la prueba de falso también ingrese a ese bloque?
De acuerdo, lo señalé como otra razón para preferir .nil? Pero insistieron en que "si la variable do x" es más idiomática que "if variable.nil? Do x" y preferible cuando se sabe que la variable no es booleana
Javier Holguera

Respuestas:

17

Escribe lo que quieres decir. Significa lo que escribes.

Hagamos una prueba diferente. .vowel?

if char == 'a'
   # do stuff
end

vs

if char.vowel?
   # do stuff
end

Ahora, es obvio que estos no hacen lo mismo. Pero si solo espera charserlo ao bfuncionará. Pero confundirá al próximo desarrollador: el segundo bloque se ingresará para las condiciones donde [eiou]también está char . Pero para a, funcionará correctamente.

Sí, es el caso nily falseson los únicos valores falsos en Ruby. Sin embargo, si está probando nilmediante pruebas nil || false, esto no es lo que quiere decir.

Significa que el próximo desarrollador (que resulta ser un loco asesino que conoce la dirección de su casa) leerá el código y se preguntará por qué falsedebería entrar allí también.

Escribe el código que transmite exactamente lo que quieres decir.

Por Lundberg
fuente
3

Considera lo siguiente:

response = responses.to_a.first

Esto devolverá el primer elemento de responses, o nil. Entonces, porque las declaraciones condicionales se tratan nilcomo falsepodemos escribir:

response = responses.to_a.first
if response
  # do something ('happy path')
else
  # do something else
end

Que es más legible que:

if response.nil?
  # do something else
else
  # do something ('happy path')
end

El if (object)patrón es muy común en el código Ruby. También conduce muy bien a la refactorización, por ejemplo:

if response = responses.to_a.first
  do_something_with(response)
else
  # response is equal to nil
end

Recuerde también que un método Ruby regresa nilpor defecto. Entonces:

def initial_response
  if @condition
    @responses.to_a.first
  else
    nil
  end
end

se puede simplificar a:

def initial_response
  if @condition
    @responses.to_a.first
  end
end

Entonces podemos refactorizar más:

if response = initial_response
  do_something_with(response)
else
  # response is equal to nil
end

Ahora puede argumentar que regresar nilno siempre es la mejor idea, ya que significa buscar en niltodas partes. Pero esa es otra tetera de pescado. Dado que la prueba de "presencia o ausencia" de objetos es un requisito tan frecuente, la veracidad de los objetos es un aspecto útil de Ruby, aunque sorprendente para los recién llegados al lenguaje.

zetetic
fuente
2

No solo se if variable.nil?lee más como el lenguaje natural, sino que también protege contra un programador que accidentalmente le asigna un falsevalor y cae en su ifdeclaración, ya que Ruby es un lenguaje poco escrito.

Greg Burghardt
fuente
1
¿Entonces el comentario inicial en la pregunta original estaba equivocado? ¿Debería haber sido "hacer cosas cuando la variable es nula o falsa"? Y dado que el código que no coincide con el comentario es un error, ¿hay un error de inmediato?
gnasher729
Correcto. Una simple prueba de veracidad podría introducir errores lógicos.
Greg Burghardt
0

Idiomáticamente, unless variablees preferible if !variable. Las ifdeclaraciones negadas a menudo se consideran un olor a código, ya que es más fácil pasar por alto la negación cuando se descrema.

La imagen más grande aquí es que hacer nilcontroles como este también es un poco un olor a código. Para una OO adecuada, intente utilizar el patrón de objeto nulo para que este tipo de verificación nunca sea necesaria. http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

Diga a los objetos qué hacer, no les pregunte qué son. Esto a veces se conoce como decir no preguntar

Matt Gibson
fuente