Tengo este profesor, es bastante inteligente (a veces, jaja), dijo que los buenos programadores intentan usar while
bucles en lugar de for
bucles. La razón que dio para esto es porque los while
bucles se pueden probar, ya que en uno se puede explicar completamente lo que sucede en un while
bucle, mientras que no se puede hacer eso para un for
bucle. También dijo algo sobre los programadores de la NASA que solo usan while
bucles y no se les permite hacer for
bucles debido a esto.
Me cuesta mucho entender esto, para ambos bucles uno puede explicar cómo funcionan en detalle, ¿verdad? para ambos siempre sabrás lo que va a pasar?
¿Alguien puede explicarme por qué while
se pueden probar los bucles (y por eso, podría ser mejor que los for
bucles, en algunos casos al menos).
Aunque esto todavía no dice nada sobre la diferencia entre while y for loops.
for
máswhile
simplemente no tiene sentido. Puede haber uno, pero este no lo es.for (init; test; step) { body }
tiene un desugaring trivialwhile
:{init; while (test) { step; body }}
.Respuestas:
En pocas palabras : lo que su maestro probablemente quiso decir es que la semántica de
while
es más o menos la misma en la mayoría de los idiomas, mientras que la semántica defor
puede cambiar considerablemente (vea la discusión a continuación). Por lo tanto, las pruebas independientes del lenguaje abstracto son más confiables con awhile
, pero se debe tener cuidado de que una prueba con unfor
bucle no coincida con la semántica delfor
bucle en muchos idiomas.Su pregunta no es lo suficientemente precisa (aunque puede que no sea su culpa).
El punto es que, afaik, no hay un estándar oficial, compatible con ISO, o una definición de referencia
for
ywhile
bucles aceptados oficialmente . La definición depende del lenguaje de programación.Por lo tanto, no puede hacer ninguna declaración general con respecto a su equivalencia antes de haber definido exactamente lo que cada uno puede hacer. Me refiero a eso más precisamente, ya que es uno de los principales argumentos utilizados en otras respuestas (y la discusión será útil en lo que sigue).
Sobre intertranslatabilidad de
for
ywhile
buclesResumen : depende del lenguaje de programación, pero siempre es posible siempre que pueda tener un bucle infinito y una forma de salir de él.
Pero puede hacer tal declaración para un lenguaje de programación específico, y la respuesta dependerá de las características del lenguaje.
Eso también significa que no hay pruebas generales, sino solo una para cada lenguaje de programación.
Una cosa que generalmente es cierta es que un
while
bucle generalmente puede imitar unfor
bucle, porque el bucle while puede hacer la prueba de condición de salida del bucle for, realizar la inicialización de la variable de control con una asignación antes de ingresar al bucle y hacer el incremento al final del cuerpo del bucle, para quese convierte
Esto funciona más o menos para la mayoría de los idiomas, pero no es tan obvio como parece, y puede haber muchos "detalles" de los que preocuparse.
Por ejemplo, en muchos idiomas, el
for
bucle evalúa 3 argumentos (valor inicial, incremento y valor final) como argumentos estrictos , evaluados una vez antes de ingresar al bucle, mientras que otros tomarán luego como argumentos thunk para ser reevaluados en cada turno, o posiblemente como argumento perezoso para ser evaluado solo cuando sea necesario.Otro punto puede ser que la variable de incremento puede ser local al
for
bucle, o tener que ser una variable local de la función donde aparece el bucle.Dependiendo de tales problemas, la traducción de a
for
a awhile
puede variar ampliamente, aunque generalmente es posible lograrlo.Lo mismo vale para lo contrario, traduciendo a
while
en unfor
bucle.El primer problema es que un
while
bucle siempre reevaluará la condición de salida en cada vuelta. Pero algunosfor
bucles no proporcionan una condición que se reevalúa en cada turno, aparte de la comparación de la variable de control con algún valor fijo calculado en la entrada del bucle. Entonces la traducción no es posible a menos que exista algún otro medio para salirse del ciclo en algunas condiciones arbitrarias.Esto se puede lograr con varios dispositivos, generalmente comenzando con una declaración condicional que pruebe la condición, seguida de un salto implementado, según esté disponible, por una declaración de salida del ciclo, una declaración de retorno (después de encapsular el ciclo en una función), una declaración goto o un aumento de excepción.
En otras palabras, nuevamente depende mucho de los idiomas, y posiblemente de las características sutiles de los idiomas.
Esto dice, como respondió @milleniumbug , la intertranslación es fácil en el lenguaje C, porque un
for
lopp es esencialmente unwhile
bucle más algo extra para una variable de control incrementada.Pero esto no se aplica necesariamente a otros idiomas, y muy probablemente no de la misma manera.
Dicho esto, generalmente se supone que los lenguajes de programación tienen poder de Turing con solo uno de estos bucles, ya que todo lo que necesita es un bucle infinito. Entonces, siempre y cuando tenga alguna forma de bucle para siempre, y posiblemente decida detenerse, está bastante seguro de que puede imitar cualquier otra construcción ... pero no necesariamente fácil.
En cuanto a las pruebas
Resumen : No conozco ninguna razón para afirmar que las pruebas deberían ser significativamente más difíciles con una u otra (a menos que alguna característica extraña del lenguaje).
Probablemente hay un malentendido, o tu maestro tenía su mente en otra cosa.
La semántica formal se puede definir para los diversos tipos de bucles definidos en los lenguajes de programación, y luego usarse para probar propiedades.
Puede ser, nuevamente según el idioma, que la realización de pruebas formales con respecto a los programas puede ser más compleja en algunos casos. Pero eso depende del idioma.
No puedo imaginar una razón por la cual las pruebas deberían ser significativamente más difíciles con una construcción más que con la otra. El
for
ciclo puede ser más complejo ya que puede ofrecer, como en C, todo lo que se hace con unwhile
plus más. Pero si lo hicieras con unwhile
, tendrías que agregar los extras en alguna otra forma.Podría usar el argumento general formal de intertranslatabilidad, siempre y cuando exista la posibilidad de un solo bucle infinito. Sin embargo, me abstendré de hacer eso, ya que las construcciones involucradas no son nada con lo que quieras lidiar en una prueba, y claramente sería una declaración injusta, al menos en la práctica.
Sin embargo, siguiendo la discusión anterior, hemos visto que las dificultades para la intertranslatabilidad provienen de la gran variabilidad del
for
ciclo de un idioma a otro. De ahí la siguiente conclusión, que probablemente sea la respuesta correcta:Una posibilidad para comprender la afirmación de su maestro es que la semántica del
while
bucle es prácticamente la misma en todos los lenguajes de programación, mientras que la sintaxis y la semántica delfor
bucle pueden variar significativamente de un idioma a otro. Por lowhile
for
tanto, es posible hacer pruebas "abstractas" generales con bucles que tienen una semántica independiente del lenguaje en buena medida, mientras que esto no es posible para el bucle que tiene una sintaxis y una semántica que cambian demasiado de un idioma a otro. Pero esto no se aplica dentro de un lenguaje dado, cuando la semántica de ambos se define con precisión.Mi mejor sugerencia es que le preguntes a tu maestro qué quiso decir exactamente y si puede darte un ejemplo. Frases o malentendidos es un evento común.
fuente
En el lenguaje C puede reescribir cada
for
ciclo a unwhile
ciclo equivalente y viceversa.while -> for
transformación:Volver a escribir
a
for -> while
transformación:Esto es un poco más complicado, especialmente si tiene una
continue
declaración en su ciclo.Volver a escribir:
a:
pero reemplace cada
continue;
declaración congoto next_label;
declaración. Sicondition
es una instrucción nula, reemplácela contrue
.Como puede ver, en el lenguaje C ninguno de los dos es más "demostrable" (lo que sea que eso signifique) que el otro, ya que incluso si uno de los bucles lo fuera, podría reescribirlo en términos de otro bucle.
Ahora, existen otros idiomas donde esta
while <-> for
equivalencia no existe. Por ejemplo, en Pascal, puede asumir más sobre elfor
ciclo. Esto significa que no puede expresar cada concepto al escribir unfor
bucle, pero puede probar más sobre el flujo del código:Aquí,
n
se guarda al comienzo del ciclo, por lo que los cambiosn
no influyen en el recuento de iteraciones, y no se puede modificari
en el cuerpo del ciclo. Esto significa que puede probar trivialmente que este ciclo finalmente terminará (comon
es finito, y no puede modificarloi
).fuente
goto
. Si se agregan banderas, todos los demás bucles se pueden emular usando un solo "while (1) ..." alrededor de una función que se ejecuta hasta un "retorno"; si uno agrega "goto", todos los otros bucles se pueden emular usando eso.En la lógica de Floyd-Hoare , el sistema formal más común para razonar sobre la corrección de los programas de computadora, existe la regla while .
En palabras, si tiene una cláusula de protección (la expresión entre paréntesis en el
while()
), una función variante (una expresión con valores discretos que se puede mostrar que disminuye monotónicamente cada vez que se ejecuta el bucle, y siempre es positiva), y un bucle invariante (una declaración lógica que siempre es verdadera antes y después de cada vez que se ejecuta el ciclo), puede probar que el ciclo while finalizará (porque la función variante no puede seguir disminuyendo) y que eventualmente la cláusula de protección será falsa y el ciclo invariante sea cierto.La lógica de Floyd-Hoare no tiene reglas para los
for
bucles o cualquier construcción que los lenguajes reales puedan tener.Sin embargo, como explican otras respuestas, los bucles for siempre se pueden escribir en términos de bucles while. Eso significa que se puede razonar sobre ellos, solo requiere un poco más de trabajo.
Si su maestro tenía cursos en la universidad donde tenía que proporcionar pruebas de corrección de sus programas, probablemente escribía programas utilizando solo bucles while. Sé que lo hice. Y una vez que estás acostumbrado a pensar en términos de guardias y funciones variantes e invariantes de bucle, parecen muy naturales. El uso excesivo de los bucles es un hábito que ves con los graduados de CS, tuve que aprender a dejar de hacerlo en mis primeros meses como desarrollador profesional.
En algún momento, su maestro recordaba todo esto como "buenos programadores usan bucles while", mientras que lo que realmente sucede es más como "algunos graduados de CS convierten sus hábitos de prueba de corrección en hábitos prácticos de programación".
fuente
for
ciclo, que no tiene una definición fija y es más complejo, sin ser formalmente necesario.En realidad, en cierto sentido, todo lo contrario es cierto.
Un lenguaje con solo
for
bucles no es completo de Turing, solo puede calcular las funciones primitivas-recursivas, no todas las funciones computables de Turing. Dado que todos los cálculos en un lenguaje con solofor
bucles siempre terminan, el problema de detención y todos los demás problemas de decidibilidad basados en él, simplemente no surgen, por lo que es posible decidir mecánicamente muchas más propiedades estáticas de los programas que en un lenguaje conwhile
buclesOTOH, un lenguaje con solo números naturales, una sola variable y
while
-loops es Turing-complete, por lo que no es posible decidir incluso las propiedades más simples: ¿este programa devolverá un resultado?fuente
for
lenguaje único puede producir unwhile
comportamiento equivalente al disminuir la variable de bucle (suponiendo que el lenguaje lo permita) durante las iteraciones que no se supone que den como resultado una terminación. (Por ejemplofor n in 1 to 2 { if condition then n := n-1 }
)Me gustaría decir que, en realidad, no hay diferencia. Su pregunta es irrelevante. Puede ser que tu maestro haya querido usar while-loop cuando no. de iteraciones no se conoce de antemano. En muchos casos necesitamos usar un ciclo while para extraer dígitos de un no. cuando el usuario ingresa el no. que puede ser de cualquier longitud. Técnicamente hablando, la similitud entre el bucle for & while es que ambos son bucles controlados por entrada en los que la (expresión / condición de prueba) se evalúa antes de ingresar al cuerpo del bucle. Esta es la distinción entre los bucles while y do-while.
fuente
Probablemente proviene de la programación inicial de C donde, según las normas actuales, los bucles fueron ampliamente abusados y mal utilizados, especialmente la modificación condicional. A medida que los programadores comenzaron a comprender el efecto que tenían ciertos estilos de programación, el abuso y el mal uso de los condicionales de bucle cayeron en desgracia, y la declaración, aunque (posiblemente) una vez válida, ya no tiene ninguna verdad.
La declaración no tiene absolutamente ninguna verdad si observa únicamente la definición y la sintaxis del lenguaje e ignora cómo se estaba utilizando.
Sin embargo, la declaración en sí ofrece una valiosa lección a cualquiera que quiera entenderla, su historia y por qué ya no se considera verdadera. - ¿Cuál es la expresión sobre el aprendizaje, los errores y repetirlos .....
fuente
¡Tu profesor tiene razón!
La razón es la siguiente es válida C
¡No puede garantizar que las variables de condición no hayan sido manipuladas!
fuente
while
bucles funcionen mejor aquí?while
bucles, ¿puede garantizar que la variable de condición no haya sido alterada? De hecho, la manipulación de la variable de condición es la única forma de salir de unwhile
bucle. Por lo general, me abstengo de votar negativamente, pero por esta respuesta, haré una excepción.