¿Por qué usarías una tarea en una condición?

En muchos idiomas, las asignaciones son legales en las condiciones. Nunca entendí la razón detrás de esto. ¿Por qué escribirías?

if (var1 = var2) { ... } 

en lugar de:

 var1 = var2; if (var1) { ... } 

    Es más útil para bucles que declaraciones if.

     while( var = GetNext() ) { ...do something with var } 

    Que de otro modo tendría que ser escrito

     var = GetNext(); while( var ) { ...do something var = GetNext(); } 

    Es más útil si llamas a una función:

     if (n = foo()) { /* foo returned a non-zero value, do something with the return value */ } else { /* foo returned zero, do something else */ } 

    Claro, puedes poner el n = foo (); en una statement separada, entonces si (n), pero creo que lo anterior es una expresión bastante legible.

    Lo encuentro más útil en cadenas de acciones que a menudo implican la detección de errores, etc.

     if ((rc = first_check(arg1, arg2)) != 0) { report error based on rc } else if ((rc = second_check(arg2, arg3)) != 0) { report error based on new rc } else if ((rc = third_check(arg3, arg4)) != 0) { report error based on new rc } else { do what you really wanted to do } 

    La alternativa (no usar la asignación en la condición) es:

     rc = first_check(arg1, arg2); if (rc != 0) { report error based on rc } else { rc = second_check(arg2, arg3); if (rc != 0) { report error based on new rc } else { rc = third_check(arg3, arg4); if (rc != 0) { report error based on new rc } else { do what you really wanted to do } } } 

    Con la comprobación de errores prolongada, la alternativa puede ejecutarse en el RHS de la página, mientras que la versión de asignación en versión condicional no lo hace.

    Puede ser útil si está llamando a una función que devuelve datos para trabajar o una bandera para indicar un error (o que está listo).

    Algo como:

     while ((c = getchar()) != EOF) { // process the character } // end of file reached... 

    Personalmente es un idioma que no me gusta mucho, pero a veces la alternativa es más fea.

    GCC puede ayudarte a detectar (con -Wall) si involuntariamente intentas usar una tarea como un valor de verdad, en caso de que te recomiende que escribas

     if ((n = foo())) { ... } 

    Es decir, use paréntesis adicionales para indicar que esto es realmente lo que quiere.

    La expresión idiomática es más útil cuando estás escribiendo un ciclo while en lugar de una instrucción if . Para una statement if , puedes dividirla como describes. Pero sin esta construcción, tendrías que repetirte a ti mismo:

     c = getchar(); while (c != EOF) { // ... c = getchar(); } 

    o use una estructura de bucle y medio:

     while (true) { c = getchar(); if (c == EOF) break; // ... } 

    Por lo general, preferiría la forma de bucle y medio.

    En PHP, por ejemplo, es útil para recorrer los resultados de la base de datos SQL:

     while ($row = mysql_fetch_assoc($result)) { // Display row } 

    Esto se ve mucho mejor que:

     $row = mysql_fetch_assoc($result); while ($row) { // Display row $row = mysql_fetch_assoc($result); } 

    La respuesta corta es que los lenguajes de progtwigción orientados a la expresión permiten un código más sucinto. No lo fuerce a separar comandos de consultas .

    La otra ventaja viene durante el uso de gdb. En el siguiente código, el código de error no se conoce si tuviéramos un solo paso.

     while (checkstatus() != -1) { // process } 

    Más bien

     while (true) { int error = checkstatus(); if (error != -1) // process else //fail } 

    Ahora, en un solo paso, podemos saber cuál fue el código de error de retorno de checkstatus ().

     if((var = someFunction())){ //Enclosed in additional pair of brackets to show its intentional ... 

    Lo anterior se puede usar en lugar de …

     var = someFunction(); if(var){ ... 

    La razón es :

    1. Mejora del rendimiento (a veces)

    2. Código menor (siempre)

    Tome un ejemplo: existe un método someMethod() y en una condición if desea verificar si el valor de retorno del método es null . Si no, vas a usar el valor de retorno nuevamente.

     If(null != someMethod()){ String s = someMethod(); ...... //Use s } 

    Va a obstaculizar el rendimiento ya que está llamando al mismo método dos veces. En su lugar use:

     String s; If(null != (s = someMethod())) { ...... //Use s }