Pregunta

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 usarlo, y algunos que lo usan con demasiada frecuencia.

¿Qué sientes al respecto? ¿Qué código interesante has visto usándolo?

¿Fue útil?

Solución

Úselo solo para expresiones simples :

int a = (b > 10) ? c : d;

No encadene ni anide 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, cuando utilice un operador ternario, considere formatear el código de una manera que mejore la legibilidad:

int a = (b > 10) ? some_value                 
                 : another_value;

Otros consejos

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 subexpresiones. Lo uso raramente.

Me encantan, especialmente en lenguajes de tipo seguro.

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 ordenado que la alternativa.

Encadenado con el que estoy bien - anidado, no tanto.

Tiendo a usarlos más en C simplemente porque son una declaración if que tiene valor, por lo que reduce la repetición o las variables innecesarias:

x = (y < 100) ? "dog" :
    (y < 150) ? "cat" :
    (y < 300) ? "bar" : "baz";

en lugar de

     if (y < 100) { x = "dog"; } 
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; } 
else              { x = "baz"; }

En tareas como esta, encuentro que es menos refactorizante y más claro.

Por otro lado, cuando estoy trabajando en rubí, es más probable que use if...else...end porque también es una expresión.

x =   if (y < 100) then "dog"
    elif (y < 150) then "cat"
    elif (y < 300) then "bar"
    else                "baz"
    end

(aunque, ciertamente, para algo así de simple, podría usar el operador ternario de todos modos).

El operador ternario ?: es simplemente un equivalente funcional de la construcción procesal if. Por lo tanto, siempre que no esté utilizando expresiones <=> anidadas, los argumentos a favor / en contra de la representación funcional de cualquier operación se aplican aquí. Pero las operaciones ternarias de anidamiento pueden dar como resultado un código totalmente confuso (ejercicio para el lector: intente escribir un analizador que maneje los 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 en realidad es más fácil de leer que de lo contrario. 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 el operador ternario con prudencia (eso es solo en relación con la propiedad reverseOrder ) el resultado final no es particularmente breve.

Es una cuestión de estilo, de verdad; Las reglas subconscientes que tiendo a seguir son:

  • Solo evalúa 1 expresión, entonces foo = (bar > baz) ? true : false, pero NO foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
  • Si lo estoy usando para la lógica de visualización, p. <%= (foo) ? "Yes" : "No" %>
  • Solo lo utilizo realmente para la asignación; nunca fluya la lógica (así que nunca (foo) ? FooIsTrue(foo) : FooIsALie(foo)) La lógica del flujo en ternario es en sí misma una mentira, ignore ese último punto.

Me gusta porque es conciso y elegante para operaciones de asignación simples.

Como tantas 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 analizar) que:

if (x) {
    return "Yes";
} else {
    return "No";
}

Ahora, si su expresión condicional es compleja, la operación ternaria no es una buena opción. Algo así como:

x && y && z >= 10 && s.Length == 0 || !foo

no es un buen candidato para el operador ternario.

Además, si usted es un programador en C, GCC en realidad tiene una extensión que le permite excluir la porción if-true del ternario, como esta:

/* 'y' is a char * */
const char *x = y ? : "Not set";

Que establecerá x en y suponiendo que NULL no es <=>. Cosas buenas.

En mi opinión, solo 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.

Por la medida de complejidad ciclomática , el uso de if declaraciones o el operador ternario son equivalentes Entonces, según esa medida, la respuesta es no , la complejidad sería exactamente la misma que antes.

Por otras medidas, como la legibilidad, la capacidad de mantenimiento y DRY (no repetir), cualquiera de las opciones puede ser mejor que la otra.

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 contribuido:

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, lo importante es asegurarse de que su código sea legible. Cualquier construcción puede hacerse ilegible.

Uso el operador ternario siempre que puedo, a menos que haga que el código sea extremadamente difícil de leer, pero eso suele ser solo una indicación de que mi código podría usar un poco de refactorización.

Siempre me desconcierta cómo algunas personas piensan que el operador ternario es un " oculto " característica o es algo misterioso. Es una de las primeras cosas que aprendí cuando comienzo a programar en C, y no creo que disminuya en absoluto la legibilidad. Es una parte natural del lenguaje.

Estoy de acuerdo con jmulder: no debe usarse en lugar de un if, pero tiene su lugar para la expresión de retorno o dentro de una expresión:

echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;

¡Lo primero es solo un ejemplo, se debe usar un mejor soporte de i18n en plural!

(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;

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 asignación, y creo que debería evitarse. Use una declaración if en estos casos.

Creo que el operador ternario debería usarse cuando sea necesario. Obviamente es una elección muy subjetiva, pero encuentro 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 está 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 ]

Se necesita lo suficiente como para que en Python (como ejemplo), tal lenguaje 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 vagos y devuelve el último valor calculado si es igual al estado final.

Me gustan. No sé por qué, pero me siento muy bien cuando uso la expresión ternaria.

He visto tales bestias como (en realidad era mucho peor ya que era ValidDate y también se verificaba mes y día, pero no me molestó tratar de recordar todo):

isLeapYear =
    ((yyyy % 400) == 0)
    ? 1
    : ((yyyy % 100) == 0)
        ? 0
        : ((yyyy % 4) == 0)
            ? 1
            : 0;

donde, claramente, una serie de sentencias if hubiera sido mejor (aunque esta todavía es 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 difíciles como:

printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");

Me gusta usar el operador en el código de depuración para imprimir valores de error, así que no tengo que buscarlos todo el tiempo. Por lo general, hago esto para las impresiones de depuración que no permanecerán una vez que termine 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");
}

Casi nunca uso el operador ternario porque cada vez que lo uso, siempre me hace pensar mucho más de lo que tengo que pensar cuando trato de mantenerlo.

Me gusta evitar la verbosidad, pero cuando hace que el código sea mucho más fácil de aprender, iré por la verbosidad.

Considere:

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;

Parece que comprime demasiada información en muy poco espacio, sin dejar en claro lo que está sucediendo. Cada vez que veo que se usa un operador ternario, siempre encuentro una alternativa que parecía mucho más fácil de leer ... una vez más, esa es una opinión extremadamente subjetiva, así que si usted y sus colegas consideran que el ternario es muy legible, adelante.

Bueno, la sintaxis es horrible. Encuentro funcional ifs 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).

Solo cuando:

$ var = (simple > test? simple_result_1: simple_result_2);

BESO.

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);

Como otros han señalado, son buenos para condiciones simples y cortas. Me gustan especialmente los valores predeterminados (como el uso de || y o 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;

Trato a los operadores ternarios como GOTO. Tienen su lugar, pero son algo que generalmente debes evitar para que el código sea más fácil de entender.

Recientemente vi una variación en los operadores ternarios (bueno, más o menos) que hacen que el estándar " ()? : " La variante parece ser un modelo 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, así que cosas como esas podrían no ser posibles en otros idiomas (afortunadamente).

Por simple si los casos, 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 todos mis if / else.

Insistir en que sería un gran NO-NO en mi libro.

Entonces, resumiendo, para un solo si / de lo contrario usaré el operador ternario. Para otros casos, un if / else if / else (o switch) regular

Me gusta el caso especial de Groovy del operador ternario, llamado operador de Elvis:?:

expr ?: default

Este código se evalúa como 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 / escritura.

Para tareas simples como asignar un valor diferente dependiendo de una condición, son geniales. No los usaría cuando hay expresiones más largas dependiendo de la condición aunque.

Muchas respuestas han dicho, depende . Encuentro que si la comparación ternaria no es visible en un escaneo rápido del código, entonces no debería usarse.

Como un problema secundario, también podría notar que su existencia misma es en realidad un poco anomólica debido al hecho de que en C, las pruebas de comparación son una declaración. En Icon, la construcción if (como la mayoría de Icon) es en realidad una expresión. Para que pueda 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 ternery. :-)

Recientemente hubo una discusión sobre la posibilidad de agregar el operador ?: al icono, pero varias personas señalaron correctamente que no había absolutamente ninguna necesidad debido a la forma en que <=> funciona.

Lo que significa que si pudieras hacer eso en C (o en cualquiera de los otros lenguajes que tienen el operador de ternery), entonces, de hecho, no necesitarías el operador de ternery.

Si usted y sus compañeros de trabajo comprenden 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 recuerdan que tienen precedencia correcta y, cuando tienes una pila de ellas, hace que leer el código sea una pesadilla.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top