¿El operador ternario es considerado perjudicial? [cerrado]

77

Por ejemplo, ¿preferirías este one-liner

int median(int a, int b, int c) {
    return (a<b) ? (b<c) ? b : (a<c) ? c : a : (a<c) ? a : (b<c) ? c : b;
}
¿

o una solución if / else con múltiples declaraciones de devolución?

¿Cuándo es apropiado ?: y cuándo no? ¿Debería enseñarse u ocultarse a los principiantes?

    
pregunta FredOverflow 18.06.2013 - 19:56

25 respuestas

229
  

¿Es malvado el operador ternario?

No, es una bendición.

  

¿Cuándo es?: ¿apropiado?

Cuando es algo tan simple, no quieres perder muchas líneas para.

  

y cuando no lo es?

Cuando la legibilidad y la claridad del código se ven afectadas y aumenta la posibilidad de error a través de una atención insuficiente, por ejemplo, con muchos operadores encadenados, como en su ejemplo.

La prueba de fuego es cuando empiezas a dudar de que tu código sea fácil de leer y mantener a largo plazo. Entonces no lo hagas.

    
respondido por el 2 revs, 2 users 96%user8685 20.08.2014 - 16:26
49

Creo que el operador ternario no anidado (es decir, una declaración en la que se usa solo una vez) está bien, pero si está anidado más de uno, es un poco difícil de leer.

    
respondido por el mipadi 21.12.2010 - 16:16
24

¿Cuándo es?: apropiado

  • Cuando hace que su código sea más conciso y legible.

y cuando no lo es?

  • Cuando hace que tu código sea ilegible.
  • Si lo está haciendo solo para complacer a una herramienta de refactorización como ReSharper y no a la persona que tiene que mantener el código

Si tiene alguna llamada de lógica o función dentro de la expresión ternaria, es horrible verla.

    
respondido por el realworldcoder 20.12.2010 - 18:12
21

Una diferencia que (creo) que nadie ha señalado es que if-else no puede devolver un valor, mientras que el operador ternario sí puede.

Desde F #, a veces me gusta usar el operador ternario para imitar la coincidencia de patrones.

match val with
| A -> 1
| B -> 3
| _ -> 0

vs

return val == A ? 1 : 
       val == B ? 3 : 
       0;
    
respondido por el Benjol 26.11.2012 - 07:15
12

Un ejemplo (IMHO) de un uso válido:

printf("Success in %d %s\n", nr_of_tries, (nr_of_tries == 1 ? "try" : "tries"));

Esto resulta en un código más legible que tener 2 declaraciones de impresión distintas. Los ejemplos anidados dependen: (¿comprensible? Sí: no)

    
respondido por el Henno Brandsma 20.12.2010 - 20:07
5

Absolutamente no es el mal. De hecho, es pureza , y if-then-else no lo es.

En lenguajes funcionales como Haskell, F #, ML, etc., las declaraciones if-then-else se consideran malas.

El motivo de esto es que cualquier "acción" como una declaración imperativa if-then-else requiere que separe una declaración de variable de su definición, e introduce state a su función.

Por ejemplo, en el siguiente código:

const var x = n % 3 == 1
    ? Parity.Even
    : Parity.Odd;

vs.

Parity x;
if (n % 3 == 1)
    x = Parity.Even;
else
    x = Parity.Odd;

La primera tiene dos ventajas además de ser más corta:

  1. x es una constante, por lo que ofrece muchas menos posibilidades de introducir errores y, potencialmente, puede optimizarse de una forma que nunca podría ser la segunda.
  2. El tipo queda claro con la expresión, por lo que el compilador puede inferir sin esfuerzo que x debe ser del tipo Parity .

Confusamente, en lenguajes funcionales, el operador ternario a menudo se llama if-then-else. En Haskell, podrías decir x = if n mod 3 == 1 then Odd else Even .

    
respondido por el Rei Miyasaka 21.12.2010 - 15:56
5

Esa expresión particular hace que me duelen los ojos; Golpeé a cualquier desarrollador en mi equipo que lo usó porque no se puede mantener.

Los operadores ternarios no son malos cuando se usan bien. Ni siquiera tienen que ser líneas simples; Un formato largo bien formateado puede ser muy claro y fácil de entender:

return
      ( 'a' == $s ) ? 1
    : ( 'b' == $s ) ? 2
    : ( 'c' == $s ) ? 3
    :                 4;

Me gusta más que el equivalente si / then / else chain:

if ( 'a' == $s ) {
    $retval = 1;
}
elsif ( 'b' == $s ) {
    $retval = 2;
}
elsif ( 'c' == $s ) {
    $retval = 3;
}
else {
    $retval = 4;
}

return $retval;

Los reformatearé en:

if    ( 'a' == $s ) { $retval = 1; }
elsif ( 'b' == $s ) { $retval = 2; }
elsif ( 'c' == $s ) { $retval = 3; }
else                { $retval = 4; }

return $retval;

si las condiciones y asignaciones permiten una alineación fácil. Sin embargo, prefiero la versión ternaria porque es más corta y no tiene tanto ruido en las condiciones y asignaciones.

    
respondido por el the Tin Man 22.12.2010 - 07:51
3

ReSharper en VS.NET a veces sugiere reemplazar if...else con el operador ?: .

Parece que ReSharper sugiere solo si las condiciones / bloques están por debajo de un cierto nivel de complejidad, de lo contrario se mantiene con if...else .

    
respondido por el Uwe Keim 20.12.2010 - 21:58
2

Esto se puede reformatear para que se vea tan bien como la combinación if / else:

int median(int a, int b, int c)
{
    return
        (a<b)
        ?
            (b<c)
            ? b
            :
                (a<c)
                ? c
                : a
        :
            (a<c)
            ? a
            :
                (b<c)
                ? c
                : b;
}

Pero el problema es que no estoy realmente seguro de tener el derecho de sangrado para representar lo que realmente ocurrirá. :-)

    
respondido por el Zan Lynx 20.12.2010 - 23:07
2

Lejos de ser malo, el operador ternario es una bendición.

  • Es más útil cuando desea tomar una decisión en una expresión anidada . El ejemplo clásico es una llamada de función:

    printf("I see %d evil construct%s in this program\n", n, n == 1 ? "" : "s");
    
  • En su ejemplo particular, el ternario es casi gratuito, ya que es la expresión de nivel superior bajo un return . Puede elevar el condicional al nivel de instrucción sin duplicar nada que no sea la palabra clave return .

N.B. Nada hará que ese algoritmo particular para la mediana sea fácil de leer.

    
respondido por el Norman Ramsey 21.12.2010 - 03:55
2
  1. Dejando de lado los argumentos "malos", según mi experiencia, he encontrado una alta correlación entre el uso que hace el programador del operador ternario y la posibilidad de que su base de código sea difícil de leer, seguir y mantener (si no absoluto indocumentado). Si un programador está más preocupado por guardar algunas líneas de 1 o 2 caracteres que alguien que pueda entender su código, entonces cualquier pequeña confusión que comprenda una declaración ternaria suele ser la punta del iceberg.

  2. Los operadores ternarios atraen números mágicos como s ** t atrae moscas.

Si estuviera buscando una biblioteca de código abierto para resolver un problema en particular, y vi un código como los operadores ternarios del póster original en un candidato para dicha biblioteca, las campanas de advertencia comenzaban a sonar en mi cabeza y yo comenzaría considerando mudarse a algún otro proyecto para pedir prestado.

    
respondido por el user8865 21.12.2010 - 18:12
2

Aquí hay un ejemplo de cuando es malo:

oldValue = newValue >= 0 ? newValue : oldValue;

Es confuso y un desperdicio. El compilador podría optimizar la segunda expresión (oldValue = oldValue), pero ¿por qué el codificador hizo esto en primer lugar?

Otro doozy:

thingie = otherThingie != null ? otherThingie : null;

Algunas personas simplemente no están destinadas a ser programadores ...

Greg dice que el equivalente si la declaración es 'ruidosa'. Lo es si lo escribes ruidosamente. Pero eso mismo si se puede escribir como:

if ('a' == $s) return 1;
if ('b' == $s) return 2;
if ('c' == $s) return 3;
return 4;

Que no es más ruidoso que el ternario. Me pregunto si los atajos ternarios; ¿Todas las expresiones son evaluadas?

    
respondido por el hapybrian 26.01.2011 - 00:21
2

¿El mal? Mira, son diferentes.

if es una declaración. (test ? a : b) es una expresión. No son lo mismo.

Las expresiones existen para expresar valores. Existen declaraciones para realizar acciones. Las expresiones pueden aparecer dentro de las declaraciones, pero no al revés. Por lo tanto, puede usar expresiones ternarias dentro de otras expresiones, como para términos en una suma, o para argumentos de un método, y así sucesivamente. No tiene que tener que hacerlo , pero puede hacerlo si quiere . No hay nada de malo en eso. Algunas personas podrían decir que eso es malo, pero esa es su opinión.

Un valor de una expresión ternaria es que te hace manejar tanto los casos verdaderos como los falsos. Las declaraciones de if no lo hacen.

Si le preocupa la legibilidad, puede formatearlos de manera legible.

De alguna manera, el "mal" se metió en el vocabulario de programación. Me encantaría saber quién lo dejó caer primero. (En realidad, tengo un sospechoso, él está en el MIT). Preferiría que tuviéramos razones objetivas para los juicios de valor en este campo, no solo los gustos y los insultos de las personas.

    
respondido por el Mike Dunlavey 26.01.2011 - 02:17
1

Tiene un lugar. He trabajado en muchas empresas donde los niveles de habilidad de los desarrolladores van desde terribles hasta asistentes. Dado que el código debe mantenerse y no estaré allí para siempre, trato de escribir cosas para que parezca que pertenece a ellas (sin mirar los comentarios con mis iniciales, es extremadamente raro que puedas mire el código en el que he trabajado para ver dónde hice cambios), y que alguien con menos habilidad que yo pueda mantenerlo.

Si bien el operador ternario se ve nitziffic y es genial, mi experiencia es que la línea de código será casi imposible de mantener. En mi empleador actual, tenemos productos que se han estado enviando durante casi 20 años. No usaría ese ejemplo en ninguna parte.

    
respondido por el Tangurena 20.12.2010 - 17:54
1

No creo que el operador ternario sea malvado.

Aquí hay un gotcha que me dejó perplejo, sin embargo. Fui programador en C para muchos (10+) y, a fines de la década de 1990, pasé a la programación de aplicaciones basadas en web. Como programador web, pronto me encontré con PHP, que también tiene un operador ternario. Tuve un error en un programa PHP que finalmente rastreé hasta una línea de código con un operador ternario anidado. Resulta que el operador ternario de PHP asociado de izquierda a derecha, pero el operador ternario de C (al que estaba acostumbrado) se asocia de derecha a izquierda.

    
respondido por el leed25d 20.12.2010 - 18:47
1

Todo lo que hace que tu código sea más feo es malo.

Si usa ternario para hacer su código más limpio, entonces asegúrese de usarlo. A veces en like php es genial hacer sustituciones en línea, por ejemplo.

"Hello ".($Male?"Mr":"Ms")." $Name

Eso ahorra algunas líneas, y es bastante claro, pero su ejemplo necesita al menos un mejor formato para ser claro, y ternario no es realmente bueno para líneas múltiples, entonces puede usarlo también si / else.

    
respondido por el user11134 21.12.2010 - 03:38
1

¿Puedo decirlo? No consigo encontrar esta aplicación particular de la operación ternaria evil :

  1. la operación que realiza es bastante trivial, y una vez que la revisaste, una vez es casi imposible que salgan algunos errores;
  2. lo que hace está claramente establecido en el nombre de la función;
  3. tomar > 1 línea por algo tan obvio y que claramente no se mejoraría en el futuro (a menos que un algoritmo de mediana mágica haya vivido sin ser detectado hasta ahora).

Por favor, ten piedad, mi reputación ya es bastante lamentable.

    
respondido por el cbrandolino 21.12.2010 - 16:04
1

Mayor victoria: Mostrar que hay un único objetivo de acción.

if ( $is_whatever )
    $foo = 'A';
else
    $foo = 'B';

Hay dos rutas de código que puede seguir, y el lector debe leer detenidamente para ver qué dos variables se están configurando. En este caso, es solo una variable, pero el lector tiene más que leer para darse cuenta de eso. Después de todo, podría haber sido esto:

if ( $is_whatever )
    $foo = 'A';
else
    $bar = 'B';

Con el operador ternario, está claro que solo se está configurando una variable.

$foo = $is_whatever ? 'A' : 'B';

En el nivel más bajo, es el principio DRY (Don't Repeat Yourself) en su forma más básica. Si puede especificar $foo solo una vez, hágalo.

    
respondido por el Andy Lester 26.11.2012 - 16:46
0

Si ... entonces ... o si no, tiende a enfatizar la condición y, por lo tanto, no enfatiza las operaciones que se realizan condicionalmente.

el operador ternario es lo opuesto, tiende a ocultar la condición y, por lo tanto, es útil cuando la operación que se realiza es más importante que la condición en sí.

En algunos idiomas, existe el problema técnico menor de que no son intercambiables debido a que uno es una declaración y una expresión, por ejemplo. Condicionalmente inicializando consts en C ++

    
respondido por el jk. 20.12.2010 - 17:58
0
  

¿Cuándo es apropiado y cuándo no?

Creo que cuando se desarrolla para un grupo homogéneo de personas, no hay ningún problema, pero cuando se tiene que tratar con personas que manejan diferentes niveles, este tipo de oneliners solo introduce un nivel adicional de complexyti en el código. Por lo tanto, mi política al respecto es: código claro y no explique en lugar de código corto y explique 123123 veces.

  

¿Debería enseñarse u ocultarse a   principiantes?

No se me debería enseñar a los principiantes, prefiero que se den cuenta cuando surja la necesidad, por lo que se usará solo cuando sea necesario y no siempre que necesites un "si".

    
respondido por el guiman 20.12.2010 - 23:25
0

En mi opinión, el operador en sí no es malo, pero la sintaxis utilizada para ello en C (y C ++) es excesivamente tersa. OMI, Algol 60 lo hizo mejor, así que algo como esto:

A = x == y ? B : C;

se vería más como esto (pero se adhiere a la sintaxis tipo C en general):

A = if (x==y) B else C;

Incluso con eso, el anidamiento excesivamente profundo puede llevar a problemas de legibilidad, pero al menos A) cualquiera que haya terminado de programar puede resolverlo de manera simple, y B) las personas que entienden que pueden manejar el anidamiento considerablemente más profundo con bastante facilidad . OTOH, también observaría que en LISP (por ejemplo) un cond es muy parecido a una declaración ternaria, no un conjunto de declaraciones, sino una sola expresión que produce un valor (por otra parte, la mayor parte de LISP es como que ...)

    
respondido por el Jerry Coffin 25.01.2011 - 21:12
0

Una tienda que regularmente escribe métodos de 600-1200 líneas no debería decirme que un ternario es "difícil de entender". Cualquier tienda que regularmente permita cinco condiciones para evaluar una rama de código no debería decirme que las condiciones concretamente resumidas en un ternario son "difíciles de leer".

    
respondido por el Axeman 11.03.2011 - 17:13
0

¿Cuándo es?: apropiado y cuándo no?

  • Si no obtiene un aumento de rendimiento, no lo use; Afecta la legibilidad de tu código.
  • Úsalo una vez y no lo anides.
  • Es más difícil de depurar.

¿Debería enseñarse u ocultarse a los principiantes?

No importa, pero no debe ocultarse intencionalmente ya que no es demasiado complejo para que lo aprendan los "principiantes".

    
respondido por el Amir Rezaei 23.09.2015 - 22:11
-2

En tu ejemplo:

def median(a, b, c):
    if a < b < c: return b
    if a < c < b: return c
    if b < a < c: return a
    if b < c < a: return c
    if c < a < b: return a
    if c < b < a: return b

es muy simple de leer y obvio. La variable entre el < < es el valor de retorno.

Actualizar

lo mismo, pero menos líneas de código. Todavía es simple, creo.

def median(a, b, c):
    if b<a<c or c<a<b: return a
    if a<b<c or c<b<a: return b
    if a<c<b or b<c<a: return c
    
respondido por el Christopher Mahan 26.01.2011 - 01:50
-2

También es necesario para const

const int nLegs  = isChicken ? 2: 4 ;
    
respondido por el Martin Beckett 11.03.2011 - 17:40

Lea otras preguntas en las etiquetas

Comentarios Recientes

Los operadores Bash y Ternary pueden ser dañinos, aunque solo hay tres operadores ternarios principales: match, isspace y local a un bloque. Sin embargo, creo que lo único divertido que pueden hacer las personas vinculantes dinámicas es la cláusula de rendimiento de JavaScript, aunque muchos programadores prefieren definir condicionales cortas como asignaciones. [desenfocado] Los programadores modernos eligen {variable: var} como el goto del cual su código abortará, dejándolos libres para terminar en cualquier... Lee mas