2009-12-27 10 views
33

el fin de escribir de manera más concisa, en lugar de hacer esto:¿La asignación en una cláusula condicional es de buen estilo ruby?

test_value = method_call_that_might_return_nil() 
if test_value 
    do_something_with test_value 
end 

He estado asignando en condicional:

if test_value = method_call_that_might_return_nil() 
    do_something_with test_value 
end 

¿Es esta mal estilo? La sintaxis aún-más-concisa:

do_something_with test_value if test_value = method_call_that_might_return_nil() 

no está permitido, como se ha discutido in another SO question, y permanecerá así en 1,9, de acuerdo con Matz (http://redmine.ruby-lang.org/issues/show/1141).

Dada la posible confusión de asignación y comparación, ¿esto hace que sea demasiado difícil leer el código?

+0

Creo que se debe trazar una línea entre la concisión y la comprensibilidad. Creo que en el tiempo de hoy, donde debemos conocer varios idiomas diferentes, es una buena idea usar nuevas características geniales de ciertos idiomas sin dañar el conocimiento existente de los programadores. Como programador experto, ¿por qué debería tener la necesidad de buscar en Google tal idoneidad sintáctica de un idioma a otro? Preferiría pasar más tiempo buscando en Google el problema en cuestión. Por ejemplo, cómo multihilo en ruby. –

+1

Rubocop y esta guía de estilo de rubí recomiendan evitarla: https://github.com/bbatsov/ruby-style-guide – Rimian

+0

Enlace a la parte específica de la guía de estilo: https://github.com/bbatsov/ruby-style -guide # safe-assignment-in-condition –

Respuesta

14

Esta pregunta se realizó hace bastante tiempo, y todas las respuestas están desactualizadas.

Está explícitamente BUENO estilo para usar asignaciones en condicionales. Si lo hace, ajuste la condición entre paréntesis.

# Bad 

if value = Settings.get('test_setting') 
    perform_action(value) 
end 

# Okay, but uncommon and verbose 

value = Settings.get('test_setting') 
if value 
    perform_action(value) 
end 

# Good 

if (value = Settings.get('test_setting')) 
    perform_action(value) 
end 

See the community style guide for more information

La respuesta previamente aceptada dice que el uso de la palabra clave and. Nunca use las palabras clave and o or en ruby. Eso también está en la guía de estilo, y hay muy buenas razones lógicas para no usarlos.

1

Sí, diría que es un mal estilo debido a la posible confusión entre la asignación y la comparación. Es solo una línea más para asignar y luego probar, y evita que alguien en el futuro piense que fue un error y lo parche para usar ==.

26

Una algo lenguaje generalizado es el uso de and, que sería algo como esto:

tmp = method_call_that_might_return_nil and do_something_with tmp 

Otra posibilidad sería llamar #nil? explícitamente, de esa manera la intención se convierte en un poco más claro; En particular, es muy obvio que en realidad quería decir asignar en lugar de comparar:

unless (tmp = method_call_that_might_return_nil).nil? 
    do_something_with tmp 
end 
7

código conciso no es necesariamente mejor código. La concisión es útil cuando mejora la comunicación del comportamiento previsto del código del autor a los futuros mantenedores. Creo que bastantes de nosotros procedemos de entornos en los que hemos tenido asignaciones accidentales en los bloques if (cuando queríamos una comparación de igualdad) que preferimos estilos en los que está absolutamente claro que se entiende la tarea, en lugar de comparar. El idioma .nil? ya mencionado tiene esa propiedad, y lo consideraría más limpio que tener la tarea asignada dentro de la condición if. Realmente, sin embargo, no veo el daño en tener la línea de código adicional para la tarea.

2

C programadores hacen esto mucho. No veo ningún problema con eso en Ruby, siempre y cuando esté claro lo que está sucediendo.

+3

El problema es que Ruby le da una advertencia cada vez que asigna en un condicional. Si no fuera así, sospecho que sería tan popular en ruby ​​como lo es en C. –

1

Creo que está bien. La aversión a la asignación en una condición proviene de saber que una pulsación de tecla perdida al escribir == convierte una comparación en una asignación involuntaria. Una prohibición estilística de usar asignación en una condición hace que tales accidentes se destaquen como a simple vista (y a veces al lenguaje, como en C, donde se puede hacer que muchos compiladores emitan una advertencia si encuentran una asignación en una condición). Por otro lado, las pruebas también hacen que esos accidentes se destaquen. Si su código está bien cubierto por las pruebas, puede considerar descartar dichas prohibiciones.

5

La forma de programación funcional para hacer esto es usar andand. Es una forma legible de encadenar llamadas de método para que un cero en el medio detenga la cadena. Por lo tanto, su ejemplo sería algo así como:

method_call_that_might_return_nil.andand.tap {|obj| do_something_with obj} 
## or, in the common case: ## 
method_call_that_might_return_nil.andand.do_something 
Cuestiones relacionadas