goto se desaconseja casi universalmente. ¿Vale la pena usar esta declaración?

Comentarios

  • xkcd.com/292
  • goto es lo que hace la CPU en última instancia, pero no funciona bien con lo que los humanos necesitan comprender y abstraer debido a que no hay una marca en el objetivo fin. Compare con Intercal COMEFROM.
  • @Thorbj ø rnRavnAndersen, qué más quieren decir los humanos cuando ‘ ¿estás hablando de transiciones de estado en una máquina de estado? ¿Puede ‘ ver una similitud? » Ir a un estado » dado, que ‘ s lo que significa y cualquier otra cosa no sería más que una complicación innecesaria de algo tan trivial. ¿Y qué quieres decir con » sin marca «? La etiqueta es una de esas marcas.
  • @ SK-logic, depende de qué tan lejos permitas que goto ‘ s venga. Las máquinas de estado no requieren goto para implementar.
  • @Thorbj ø rnRavnAndersen, por supuesto goto no es necesario. Es simplemente la forma más racional de implementarlos en los lenguajes imperativos, ya que es lo más cercano a la semántica misma de la transición de estado. Y su destino puede estar bastante lejos de la fuente, no ‘ entorpecerá la legibilidad. Mi ejemplo favorito de tal código es D.E. Knuth ‘ s implementación del juego de aventuras.

Respuesta

Esto se ha discutido varias veces en Stack Overflow, y Chris Gillum resumió los posibles usos de goto :

Salida limpia de una función

A menudo, en una función, puede asignar recursos y necesitar salir en varios lugares. Los programadores pueden simplificar su código colocando el código de limpieza de recursos al final de la función, todos los » puntos de salida » de la función irían a la etiqueta de limpieza. De esta manera, no tiene que escribir código de limpieza en cada » punto de salida » de la función.

Salir de bucles anidados

Si estás en un bucle anidado y necesitas salir de todos bucles, un goto puede hacer que esto sea mucho más limpio y sencillo que las sentencias break y las comprobaciones if.

Mejoras de rendimiento de bajo nivel

Esto solo es válido en código crítico de rendimiento, pero las instrucciones goto se ejecutan muy rápidamente y pueden darle un impulso al moverse a través de una función. Sin embargo, esta es una espada de doble filo, porque un compilador normalmente no puede optimizar el código que contiene gotos.

Yo diría que, como muchos otros argumentarían , que en todos estos casos, el uso de goto se usa como un medio para salir de un rincón en el que uno se codificó, y generalmente es un síntoma de código que podría refactorizarse .

Comentarios

  • El primer problema se resuelve muy claramente con bloques finally en lenguajes modernos, y el segundo se resuelve etiquetando break s. Si ‘ estás atascado con C, goto es prácticamente la única forma de resolver estos problemas con elegancia.
  • Muy buenos puntos. Me gusta cómo Java permite romper múltiples niveles de bucles
  • @Chinmay – finalmente bloquea solo aplicar a 1) lenguajes modernos que los tienen yb) puede tolerar la sobrecarga (el manejo de excepciones tiene una sobrecarga. ) Es decir, usar finally solo es válido en esas condiciones. Hay situaciones muy raras, pero válidas, en las que un goto es el camino a seguir.
  • De acuerdo, gente … ¿cuál es la diferencia entre break 3 o break myLabel y goto myLabel. Oh, esa ‘ es justamente la palabra clave. Si está usando break, continue o alguna palabra clave similar, de hecho está usando un goto (Si utiliza for, while, foreach, do/loop, utiliza un goto condicional).
  • Acerca del rendimiento de bajo nivel: el comportamiento del procesador moderno puede ser difícil de predecir (canalización, ejecución fuera de orden) por lo que probablemente en el 99% de los casos no vale la pena o incluso puede ser más lento. @MatthewWhited: Alcance. Si ingresa el alcance en un punto arbitrario, no está claro (para los humanos) cómo se deben llamar los constructores (el problema también existe en C).

Respuesta

Las construcciones de flujo de control de nivel superior tienden a corresponder a conceptos en el dominio del problema. Un if / else es una decisión basada en alguna condición. Un bucle dice que se realice alguna acción repetidamente. Incluso una declaración break dice «estábamos haciendo esto repetidamente, pero ahora tenemos que detenernos».

Una declaración goto, por otro lado, tiende a corresponder a un concepto en el programa en ejecución, no en el dominio del problema. Dice continuar la ejecución en un punto especificado en el programa . Alguien que lea el código tiene que inferir lo que eso significa con respecto al dominio del problema.

Por supuesto, todas las construcciones de nivel superior pueden definirse en términos de gotos y ramas condicionales simples . Eso no significa que sean simplemente gotos disfrazados. Piense en ellos como gotos restringidos , y son las restricciones las que los hacen útiles. Una declaración de interrupción se implementa como un salto al final del ciclo que lo encierra, pero es mejor pensar en ella como operando en el ciclo como un todo.

En igualdad de condiciones, el código cuya estructura refleja la del dominio del problema tiende a ser más fácil de leer y mantener.

No hay casos en los que se requiere absolutamente una instrucción goto (hay un teorema a tal efecto), pero hay casos en los que puede ser la solución menos mala. Esos casos varían de lenguaje a lenguaje, dependiendo de las construcciones de nivel superior que admita el lenguaje.

En C, por ejemplo, creo que hay tres escenarios básicos en los que un goto es apropiado.

  1. Salir de un bucle anidado. Esto sería innecesario si el lenguaje tuviera una declaración de ruptura etiquetada.
  2. Salir de un tramo de código (generalmente un cuerpo de función) en caso de un error u otro evento inesperado . Esto sería innecesario si el lenguaje tuviera excepciones.
  3. Implementación de una máquina de estados finitos explícita. En este caso (y, creo, solo en este caso) un goto corresponde directamente a un concepto en el dominio del problema, pasando de un estado a otro estado especificado, donde el estado actual está representado por el bloque de código que se está ejecutando actualmente. .

Por otro lado, una máquina de estados finitos explícita también se puede implementar con una instrucción switch dentro de un bucle. Esto tiene la ventaja de que cada estado comienza en el mismo lugar del código, lo que puede ser útil para depurar, por ejemplo.

El uso principal de un goto en un lenguaje razonablemente moderno (uno que admita if / else y bucles) es para simular una construcción de flujo de control que falta en el lenguaje.

Comentarios

  • Esta es en realidad la mejor respuesta hasta ahora – bastante sorprendente, para una pregunta que tiene un año y medio. 🙂
  • +1 a » la mejor respuesta hasta ahora «. — » El uso principal de un goto en un lenguaje razonablemente moderno (uno que admita if / else y bucles) es simular un flujo de control construye que ‘ s faltan en el idioma. »
  • En la máquina de estado de instrucción switch, cada escritura en el El valor de control es realmente un goto. Los SSSM ‘ s suelen ser buenas estructuras para usar, ya que se diferencian el estado SM de la construcción de ejecución, pero no ‘ realmente eliminan » gotos «.
  • » En igualdad de condiciones, el código cuya estructura refleja la del dominio del problema tiende a ser más fácil de leer y mantener. » Yo ‘ he sabido esto completamente durante mucho tiempo, pero me faltaron las palabras para comunicarlo con tanta precisión de una manera que otros los programadores pueden y realmente entenderán. Gracias por esto.
  • El » teorema del programa estructurado » me divierte, ya que tiende a demostrar claramente la señalar que usar sentencias de programación estructuradas para emular un goto es mucho menos legible que simplemente usar un goto.

Respuesta

Seguro que depende del lenguaje de programación. La razón principal por la que goto ha sido controvertido es por sus efectos nocivos que surgen cuando el compilador le permite usarlo con demasiada libertad. Pueden surgir problemas, por ejemplo, si te permite usar goto de tal manera que ahora puedas acceder a una variable no inicializada, o peor aún, saltar a otro método y jugar con la llamada. apilar. Debería ser responsabilidad del compilador no permitir un flujo de control sin sentido.

Java ha intentado «resolver» este problema al no permitir goto por completo. Sin embargo, Java le permite usar return dentro de un bloque finally y, por lo tanto, hacer que una excepción sea inadvertida.El mismo problema sigue ahí: el compilador no está haciendo su trabajo. Eliminar goto del idioma no lo ha solucionado.

En C #, goto es tan seguro como break, continue, try/catch/finally y return. No le permite usar variables no inicializadas, no le permite saltar de un bloque final, etc. El compilador se quejará. Esto se debe a que resuelve el problema real , que es como dije sin sentido el flujo de control. goto no cancela mágicamente el análisis de asignación definida y otras comprobaciones razonables del compilador.

Comentarios

  • ¿Su punto es que C # ‘ s goto no es malo? Si es así, ese es el caso de todos los lenguajes modernos de uso rutinario con una construcción goto, no solo C # …

Respuesta

Sí. Cuando sus bucles están anidados a varios niveles de profundidad, goto es la única forma de salir elegantemente de un bucle interno. La otra opción es establecer una bandera y salir de cada ciclo si esa bandera satisface una condición. Esto es realmente feo y bastante propenso a errores. En estos casos, goto es simplemente mejor.

Por supuesto, la declaración break de Java hace lo mismo cosa, pero sin permitirle saltar a un punto arbitrario en el código, lo que resuelve el problema perfectamente sin permitir las cosas que hacen que goto sea malo.

Comentarios

  • goto nunca es una respuesta elegante. Cuando sus bucles están anidados a varios niveles de profundidad, su problema es que no pudo diseñar su código para evitar los bucles de múltiples líneas. Las llamadas a procedimientos NO son el enemigo. (Lea los artículos » Lambda: The Ultimate … «). Usando un goto para romper bucles niveles de profundidad es poner una curita en una fractura múltiple abierta: puede ser simple pero no es ‘ t la respuesta correcta.
  • Y, por supuesto, hay ¿Nunca es el caso extraño cuando se requieren bucles profundamente anidados? Ser un buen programador no es No solo se trata de seguir las reglas, sino también de saber cuándo romperlas.
  • @ JohnR.Strohm Nunca digas nunca. Si utiliza términos como » nunca » en programación, ‘ claramente no se ha tratado con casos de esquina, optimización, restricciones de recursos, etc. En bucles profundamente anidados, goto es, de hecho, la forma más limpia y elegante de salir de los bucles. No ‘ no importa cuánto ‘ hayas refactorizado tu código.
  • @ JohnR.Strohm: Segundo más perdido característica para cambiar de VB.NET a C #: el bucle Do. ¿Por qué? Porque puedo cambiar el bucle que necesita una ruptura profunda en un bucle Do y escribir Exit Do y allí ‘ s no GoTo. Los bucles anidados ocurren todo el tiempo. Romper las pilas ocurre en algunas ocasiones.
  • @ JohnR.Strohm La única razón por la que dices » goto nunca es una respuesta elegante » se debe a que decidió que goto nunca es una respuesta elegante y, por lo tanto, cualquier solución que use goto no puede ser una respuesta elegante.

Respuesta

La mayor parte del desánimo proviene de una especie de «religión» que se ha creado en torno a Dios Djikstra que fue convincente a principios de los años 60 sobre el poder indiscriminado de :

  • saltar a cualquier lugar en cualquier bloque de código
    • función no ejecutada desde el principio
    • bucles no ejecutados desde el principio
    • inicialización de variable omitida
  • saltar lejos de cualquier bloque de código sin ninguna posible limpieza.

Esto no tiene nada más que ver con goto declaración de los lenguajes modernos, cuya existencia se debe simplemente a apoyar la cr creación de estructuras de código que no sean las proporcionadas por el lenguaje.

En particular, el primer punto principal anterior ya está permitido y el segundo se limpia (si goto de un bloque, la pila se desenrolla correctamente y se llaman todos los destructores adecuados)

Puede consultar esta respuesta para tener una idea de cómo incluso el código no el uso de goto puede ser ilegible. El problema no es ir a sí mismo, sino su mal uso.

Puedo escribir un programa completo sin usar if, solo for. Por supuesto, no será bien legible, tendrá un aspecto torpe e innecesariamente complicado.

Pero el problema no es for. Soy yo.

Cosas como break, continue, throw, bool needed=true; while(needed) {...}, etc. están notando más que mascarada goto para escapar de las cimitarras de los fanáticos de Djikstrarian, que – 50 años después de la invención de los idiomas modernos, todavía quieren sus prisioneros. Olvidaron de qué estaba hablando Djikstra, solo recuerdan el título de su nota (GOTO consideró dañino, y ni siquiera era su único título: fue cambiado por el editor) y culpan y golpean, golpean y culpan a cada construcción que tenga esos 4 letra colocada en secuencia.

Es 2011: es hora de entender que goto tiene que lidiar con el GOTO declaración sobre la que Djikstra era convincente.

Comentarios

  • » Cosas como romper, continuar , lanzar, bool necesario = verdadero; mientras que (necesario) {…}, etc. están notando más que enmascaramiento goto » No ‘ no estoy de acuerdo con eso. Preferiría » cosas como romper, etc. están restringidas goto «, o algo así. El principal problema de goto es que suele ser demasiado potente. En la medida en que el goto actual sea menos poderoso que Dijkstra ‘ s, su respuesta está bien para mí.
  • @MuhammadAlkarouri: Estoy totalmente de acuerdo. Acabas de encontrar una redacción mejor para expresar exactamente mi concepto. Mi punto es que esas restricciones a veces pueden no ser aplicables y el tipo de restricción que necesita no está en el idioma. Entonces, algo más » poderoso «, menos especializado, es lo que le permite solucionarlo. Por ejemplo, Java break n no está disponible en C ++, por lo que goto escape, incluso si escape no es necesario que esté fuera del bucle n-ple.

Responder

El extraño goto here o allí, siempre que sea local a una función, rara vez perjudica significativamente la legibilidad. A menudo la beneficia al llamar la atención sobre el hecho de que hay algo inusual en este código que requiere el uso de una estructura de control algo poco común. .

Si los gotos (locales) están dañando significativamente la legibilidad, entonces normalmente es una señal de que la función que contiene el goto se ha vuelto demasiado compleja.

El último goto que puse en un parte del código C era construir un par de bucles entrelazados. No encaja en la definición normal de uso «aceptable» de goto, pero la función terminó siendo significativamente más pequeña y clara como resultado. Para evitar el goto habría requerido una violación particularmente desordenada de DRY.

Comentarios

  • La respuesta a esto se expresa de manera más concisa en el antiguo » Lay ‘ s Patatas fritas » eslogan: » Apuesto a que no puedes ‘ comer solo una «. En su ejemplo, tiene dos » entrelazados » (lo que sea que eso signifique, y yo ‘ Apuesto a que no es ‘ t bonitos) bucles, y el goto te dio una salida barata. ¿Qué pasa con el tipo de mantenimiento, que tiene que modificar ese código después de que te atropelló un autobús? ¿El goto le hará la vida más fácil o más difícil? ¿Es necesario repensar esos dos bucles?

Responder

Creo que todo este problema ha sido un caso de ladridos el árbol equivocado.

GOTO como tal no me parece problemático, sino más bien es un síntoma de un pecado real: código espagueti.

Si el GOTO causa cruce importante de líneas de control de flujo, entonces es malo, punto. Si no cruza ninguna línea de control de flujo, es inofensivo. En la zona gris intermedia tenemos cosas como rescates de bucles, todavía hay algunos lenguajes que no han agregado construcciones que cubran todos los casos grises legítimos.

El único caso en el que me he encontrado realmente usándolo en muchos años es el caso del ciclo donde el punto de decisión está en el medio del ciclo. Te queda un código duplicado, una bandera o un GOTO. Encuentro que la solución GOTO es la mejor de las tres. No hay ningún cruce de líneas de control de flujo aquí, es inofensivo.

Comentarios

  • El caso al que alude a veces se denomina «bucle y medio» o «N más un medio bucle» y es un caso de uso famoso para goto s que saltan a un bucle (si el lenguaje lo permite; dado que el otro caso, saltarse del bucle en el medio, suele ser trivial sin goto ).
  • (Lamentablemente, la mayoría de los idiomas prohíben saltar a un bucle).
  • @KonradRudolph: si implementa el » bucle » con GOTO no hay otra estructura de bucle a la que saltar.
  • Creo que goto grita EL FLUJO DE CONTROL AQUÍ NO ‘ SE ADAPTA A LA PROGRAMACIÓN ESTRUCTURADA NORMAL PATRONES . Debido a que los flujos de control que se ajustan a los patrones de programación estructurados son más fáciles de razonar que los que no ‘ t, uno debe intentar usar tales patrones cuando sea posible; si el código se ajusta a tales patrones, uno no debe ‘ gritar que no ‘ t. Por otro lado, en los casos en los que el código realmente no ‘ no se ajusta a esos patrones, gritar al respecto puede ser mejor que pretender que el código encaja cuando en realidad no ‘ t.
  • @supercat Bueno, imagina que te escribiste un horario y luego el viento se lo quita de las manos. De acuerdo con su lógica, no debe ‘ t recuperarlo, porque perseguir su horario no estaba ‘ t en su horario.

Respuesta

Sí, el goto se puede utilizar para beneficiar la experiencia del desarrollador: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

Sin embargo, al igual que con cualquier herramienta poderosa (punteros, herencia múltiple, etc.), uno debe ser disciplinado usándolo. El ejemplo proporcionado en el enlace usa PHP, que restringe el uso de la construcción goto a la misma función / método y deshabilita la capacidad de saltar a un nuevo bloque de control (por ejemplo, bucle, instrucción de cambio, etc.)

Respuesta

Depende del idioma. Todavía se usa mucho en la programación de Cobol, por ejemplo. También he trabajado en un dispositivo Barionet 50, cuyo lenguaje de programación de firmware es un dialecto BASIC temprano que, por supuesto, requiere que uses Goto.

Respuesta

goto puede ser útil al migrar código de ensamblador heredado a C. En primera instancia, una instrucción- La conversión por instrucción a C, utilizando goto como reemplazo de la instrucción «s branch del ensamblador, puede permitir una migración muy rápida.

Comentarios

  • Correcto, pero uno de los argumentos en contra de goto s es que frustran las optimizaciones del compilador.
  • @Sapphire_Brick: muchas optimizaciones del compilador están diseñadas en torno a ciertos patrones de ejecución. Si la tarea a realizar no ‘ no se ajusta a los patrones de ejecución admitidos, » frustrar » las optimizaciones pueden no ser algo malo.

Respuesta

Yo diría que no. Siempre deben reemplazarse con una herramienta más específica para el problema que se está utilizando para resolver el goto (a menos que no esté disponible en su idioma). Por ejemplo, las declaraciones de ruptura y las excepciones resuelven problemas previamente resueltos de goto de escape de bucle y manejo de errores.

Comentarios

  • Yo ‘ diría que cuando los idiomas tienen ambos estas características, goto generalmente no se encuentra en esos idiomas.
  • Pero es porque no ‘ ¿No los necesita o porque personas piensan que no ‘ no los necesitan?
  • Sus opiniones son intolerantes. Hay muchos casos en los que goto es lo más parecido a la semántica del dominio del problema, cualquier otra cosa sería un truco sucio.
  • @ SK-logic: No ‘ No creo que la palabra » intolerante » significa lo que usted cree que significa.
  • @Keith,

devoto intolerante a sus propias opiniones y prejuicios » – eso ‘ es lo que yo Observe constantemente aquí, con este lote con los ojos vendados que golpean goto. » ¿Deberían siempre reemplazarse » son fanáticos ‘ s palabras, al menos. Nada parecido a una opinión adecuada y sólida, sino simplemente un fanatismo puro. Este » siempre » no deja espacio para ninguna opinión alternativa, ¿ves?

Respuesta

Yo diría que no. Si encuentra la necesidad de usar GOTO, apuesto a que hay una necesidad de rediseñar el código.

Comentarios

  • Tal vez, pero usted haven ‘ t proporcionó algún razonamiento
  • Dijkstra proporcionó el razonamiento, en detalle, hace décadas.
  • Just Dogma. Sin resonancias. Nota: Djikstra NO ES MÁS UNA RESONACIÓN VÁLIDA: se refería a la declaración BASIC o FORTRAN GOTO de los primeros ‘ 60. No tienen nada que ver con los realmente anémicos (comparados con el poder de esos) gots-s de hoy.
  • @EmilioGaravaglia Bueno, la parte de su razonamiento que todavía se aplica hoy en día es que es ‘ muy fácil escribir código espagueti usando muchos gotos. Sin embargo, según esa lógica, no deberíamos ‘ t usar punteros porque usar tantos punteros como number of gotos needed to create problems crearía un caos similar.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *