ternary-operator - ternario - ternary operator ruby
¿Ternario o no ternario? (30)
Úselo solo para expresiones simples :
int a = (b > 10) ? c : d;
No encadene o anide a los operadores ternarios ya que es difícil de leer y confuso:
int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;
Además, al usar el operador ternario, considere formatear el código de una manera que mejore la legibilidad:
int a = (b > 10) ? some_value
: another_value;
Personalmente, soy un defensor del operador ternario: ()? :; Me doy cuenta de que tiene su lugar, pero me he encontrado con muchos programadores que están completamente en contra de su uso, y algunos que lo usan con demasiada frecuencia.
¿Cuáles son tus sentimientos al respecto? ¿Qué código interesante has visto al usarlo?
(Hack del día)
#define IF(x) x ?
#define ELSE :
Entonces puedes hacer if-then-else como expresión:
int b = IF(condition1) res1
ELSE IF(condition2) res2
ELSE IF(conditions3) res3
ELSE res4;
Al igual que muchas preguntas de opinión, la respuesta es inevitable: depende
Para algo como:
return x ? "Yes" : "No";
Creo que es mucho más conciso (y más rápido para mí analizar) que:
if (x) {
return "Yes";
} else {
return "No";
}
Ahora bien, si su expresión condicional es compleja, entonces la operación ternaria no es una buena opción. Algo como:
x && y && z >= 10 && s.Length == 0 || !foo
no es un buen candidato para el operador ternario.
Por otro lado, si usted es un programador en C, GCC en realidad tiene una extensión que le permite excluir la parte si verdadera del ternario, como esta:
/* ''y'' is a char * */
const char *x = y ? : "Not set";
Lo cual establecerá x
y
suponiendo que y
no es NULL
. Buen material.
Bueno, la sintaxis es horrible. Considero que if funcional es muy útil, y a menudo hace que el código sea más legible.
Sugeriría hacer una macro para que sea más legible, pero estoy seguro de que alguien puede llegar a un caso extremo horrible (como siempre ocurre con CPP).
Casi nunca utilizo el operador ternario porque cada vez que lo uso, siempre me hace pensar mucho más que lo que tengo que hacer más tarde cuando intento mantenerlo.
Me gusta evitar la verborrea, pero cuando hace que el código sea mucho más fácil de aprender, voy por la verborrea.
Considerar:
String name = firstName;
if (middleName != null) {
name += " " + middleName;
}
name += " " + lastName;
Ahora, eso es un poco detallado, pero me parece mucho más legible que:
String name = firstName + (middleName == null ? "" : " " + middleName)
+ " " + lastName;
o:
String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;
Simplemente parece comprimir demasiada información en muy poco espacio, sin dejar en claro qué está pasando. Cada vez que uso un operador ternario, siempre he encontrado una alternativa que parecía mucho más fácil de leer ... por otra parte, esa es una opinión extremadamente subjetiva, así que si usted y sus colegas encuentran el ternario muy legible, hágalo.
Como otros han señalado, son agradables para condiciones simples y breves. Me gustan especialmente los valores predeterminados (algo así como el || y el uso en javascript y python), por ejemplo
int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;
Otro uso común es inicializar una referencia en C ++. Como las referencias deben declararse e inicializarse en la misma declaración, no puede usar una declaración if.
SomeType& ref = pInput ? *pInput : somethingElse;
Creo que el operador ternario debería usarse cuando sea necesario. Obviamente es una elección muy subjetiva, pero creo que una expresión simple (especialmente como expresión de retorno) es mucho más clara que una prueba completa. Ejemplo en C / C ++:
return (a>0)?a:0;
Comparado con:
if(a>0) return a;
else return 0;
También tiene el caso donde la solución se encuentra entre el operador ternario y la creación de una función. Por ejemplo en Python:
l = [ i if i > 0 else 0 for i in lst ]
La alternativa es:
def cap(value):
if value > 0:
return value
return 0
l = [ cap(i) for i in lst ]
Es necesario que en Python (como ejemplo), tal modismo se pueda ver regularmente:
l = [ ((i>0 and [i]) or [0])[0] for i in lst ]
esta línea usa propiedades de los operadores lógicos en Python: son flojos y devuelve el último valor calculado si es igual al estado final.
El operador Ternary ?:
Es simplemente un equivalente funcional de la construcción de procedimiento if
. Por lo tanto, siempre que no utilice expresiones anidadas ?:
argumentos a favor / en contra de la representación funcional de cualquier operación se aplican aquí. Pero las operaciones ternarias de anidación pueden dar como resultado un código que es francamente confuso (ejercicio para el lector: intente escribir un analizador sintáctico que maneje condicionales ternarios anidados y apreciará su complejidad).
Pero hay muchas situaciones en las que el uso conservador del operador ?:
Puede dar como resultado un código que, de hecho, es más fácil de leer que de otra manera. Por ejemplo:
int compareTo(Object object) {
if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
return 1;
if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
return -1;
else
return 0;
}
Ahora compara eso con esto:
int compareTo(Object object) {
if(isLessThan(object))
return reverseOrder ? 1 : -1;
else(isGreaterThan(object))
return reverseOrder ? -1 : 1;
else
return 0;
}
Como el código es más compacto, hay menos ruido sintáctico y, al usar juiciosamente el operador ternario (esto es solo en relación con la propiedad reverseOrder ), el resultado final no es particularmente conciso.
En mi opinión, tiene sentido usar el operador ternario en los casos en que se necesita una expresión.
En otros casos, parece que el operador ternario disminuye la claridad.
Encadenado estoy bien con - anidado, no tanto.
Tiendo a usarlos más en C simplemente b / c son una declaración if que tiene valor, por lo que reduce la repetición innecesaria o las variables:
x = (y < 100) ? "dog" :
(y < 150) ? "cat" :
(y < 300) ? "bar" : "baz";
más bien que
if (y < 100) { x = "dog"; }
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; }
else { x = "baz"; }
En asignaciones como esta, me parece menos refactorizado, y más claro.
Cuando trabajo en ruby, por otro lado, es más probable que lo use if...else...end
porque es una expresión también.
x = if (y < 100) then "dog"
elif (y < 150) then "cat"
elif (y < 300) then "bar"
else "baz"
end
(aunque, ciertamente, por algo tan simple, podría usar el operador ternario de todos modos).
Es una cuestión de estilo, realmente; las reglas subconscientes que tiendo a seguir son:
- Solo evalúa 1 expresión, entonces
foo = (bar > baz) ? true : false
foo = (bar > baz) ? true : false
, pero NOfoo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
- Si lo estoy usando para la lógica de visualización, p. Ej.
<%= (foo) ? "Yes" : "No" %>
<%= (foo) ? "Yes" : "No" %>
Solo realmente utilízalo para la asignación; nunca fluya la lógica (entonces nuncaLa lógica de flujo en ternario es en sí misma una mentira, ignora ese último punto.(foo) ? FooIsTrue(foo) : FooIsALie(foo)
)
Me gusta porque es conciso y elegante para operaciones de asignación simple.
Estoy de acuerdo con jmulder: no debe usarse en lugar de un if
, pero tiene su lugar para la expresión return o dentro de una expresión:
echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;
¡El primero es solo un ejemplo, se debe usar un mejor soporte i18n del plural!
Hace que la depuración sea un poco más difícil ya que no puede colocar puntos de interrupción en cada una de las sub expresiones. Lo uso raramente.
He visto tales bestias (en realidad era mucho peor ya que era ValidData y revisaba el mes y el día también, pero no me molestaba intentar recordar todo):
isLeapYear =
((yyyy % 400) == 0)
? 1
: ((yyyy % 100) == 0)
? 0
: ((yyyy % 4) == 0)
? 1
: 0;
donde, claramente, una serie de enunciados if habría sido mejor (aunque este es aún mejor que la versión macro que vi una vez).
No me importa para cosas pequeñas como:
reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;
o incluso cosas un poco complicadas como:
printf ("Deleted %d file%s/n", n, (n == 1) ? "" : "s");
Lo uso con bastante frecuencia en lugares donde estoy obligado a trabajar en un constructor, por ejemplo, las nuevas construcciones .NET 3.5 LINQ to XML, para definir valores predeterminados cuando un parámetro opcional es nulo.
Ejemplo de ejemplo:
var e = new XElement("Something",
param == null ? new XElement("Value", "Default")
: new XElement("Value", param.ToString())
);
o (gracias asterita)
var e = new XElement("Something",
new XElement("Value",
param == null ? "Default"
: param.ToString()
)
);
No importa si usa el operador ternario o no, asegurarse de que su código sea legible es lo más importante. Cualquier construcción puede hacerse ilegible.
Los amo, especialmente en lenguajes seguros para tipos.
No veo cómo esto:
int count = (condition) ? 1 : 0;
es más difícil que esto:
int count;
if (condition)
{
count = 1;
}
else
{
count = 0;
}
editar -
Yo diría que los operadores ternarios hacen que todo sea menos complejo y más limpio que la alternativa.
Me gusta el caso especial de Groovy del operador ternario, llamado el operador de Elvis:?:
expr ?: default
Este código evalúa a expr si no es nulo, y por defecto si lo es. Técnicamente no es realmente un operador ternario, pero definitivamente está relacionado con él y ahorra mucho tiempo / tipeo.
Me gusta usar el operador en el código de depuración para imprimir los valores de error para que no tenga que buscarlos todo el tiempo. Por lo general, hago esto para las impresiones de depuración que no van a permanecer una vez que haya terminado de desarrollar.
int result = do_something();
if( result != 0 )
{
debug_printf("Error while doing something, code %x (%s)/n", result,
result == 7 ? "ERROR_YES" :
result == 8 ? "ERROR_NO" :
result == 9 ? "ERROR_FILE_NOT_FOUND" :
"Unknown");
}
Me gustan. No sé por qué, pero me siento muy bien cuando uso la expresión ternaria.
Normalmente uso en cosas como esta:
before:
if(isheader)
drawtext(x,y,WHITE,string);
else
drawtext(x,y,BLUE,string);
after:
drawtext(x,y,isheader==true?WHITE:BLUE,string);
Para casos simples, me gusta usarlo. En realidad, es mucho más fácil leer / codificar, por ejemplo, como parámetros para funciones o cosas por el estilo. También para evitar la nueva línea que me gusta mantener con todo mi if / else.
Neseting sería un gran NO-NO en mi libro.
Entonces, reanudando, para un único if / else usaré el operador ternario. Para otros casos, un if / else regular if / else (o switch)
Para tareas simples como asignar un valor diferente dependiendo de una condición, son geniales. No los usaría cuando haya expresiones más largas dependiendo de la condición.
Por la medida de la complejidad ciclomática , el uso de las declaraciones if
o el operador ternario son equivalentes. Entonces, según esa medida, la respuesta es no , la complejidad sería exactamente la misma que antes.
Con otras medidas, como la legibilidad, la facilidad de mantenimiento y DRY (No repetir), cualquiera de las opciones puede ser mejor que la otra.
Recientemente vi una variación en los operadores ternarios (bueno, más o menos) que hacen que la variante estándar "()?:" Parezca ser un dechado de claridad:
var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]
o, para dar un ejemplo más tangible:
var Name = [''Jane'', ''John''][Gender == ''m''];
Eso sí, esto es Javascript, por lo que cosas como esa podrían no ser posibles en otros idiomas (afortunadamente).
Sólo cuando:
$ var = (simple> prueba? simple_result_1: simple_result_2);
BESO.
Si está utilizando el operador ternario para una asignación condicional simple, creo que está bien. Lo he visto (ab) usado para controlar el flujo del programa sin siquiera hacer una tarea, y creo que debería evitarse. Use una declaración if en estos casos.
Si usted y sus compañeros de trabajo entienden lo que hacen y no se crean en grupos masivos, creo que hacen que el código sea menos complejo y más fácil de leer porque simplemente hay menos código.
La única vez que creo que los operadores ternarios hacen que el código sea más difícil de entender es cuando tienes más de 3 o 4 en una línea. La mayoría de las personas no recuerda que tienen una prioridad basada en la razón y cuando tienes una pila de ellas, hace que leer el código sea una pesadilla.
Tantas respuestas han dicho, depende . Encuentro que si la comparación ternaria no es visible en un escaneo rápido hacia abajo del código, entonces no debería usarse.
Como cuestión secundaria, también podría señalar que su propia existencia en realidad es un poco anómala debido al hecho de que en C, las pruebas de comparación son una afirmación. En Icon, la construcción if
(como la mayoría de Icon) es en realidad una expresión. Entonces puedes hacer cosas como:
x[if y > 5 then 5 else y] := "Y"
... que encuentro mucho más legible que un operador de comparación de terneras. :-)
Hubo una discusión reciente sobre la posibilidad de agregar el operador ?:
Icon, pero varias personas señalaron correctamente que no había absolutamente ninguna necesidad por la forma en if
funciona.
Lo que significa que si pudieras hacer eso en C (o en cualquiera de los otros idiomas que tienen el operador de terneras), entonces, de hecho, no necesitarías el operador de terneras.
Trato a los operadores ternarios mucho como GOTO. Tienen su lugar, pero son algo que normalmente se debe evitar para que el código sea más fácil de entender.
Uso el operador ternario siempre que puedo, a menos que haga que el código sea extremadamente difícil de leer, pero eso generalmente es solo una indicación de que mi código podría usar un poco de refactorización.
Siempre me sorprende cómo algunas personas piensan que el operador ternario es una característica "oculta" o algo misterioso. Es una de las primeras cosas que aprendí cuando comencé a programar en C, y no creo que disminuya la legibilidad en absoluto. Es una parte natural del lenguaje.