He estado lidiando mucho con Lua en los últimos meses, y realmente me gustan la mayoría de las características, pero todavía me falta algo entre ellas:
- ¿Por qué no hay
continue
? - ¿Qué soluciones hay para ello?
loops
lua
language-design
Dant
fuente
fuente
goto
declaración que puede usarse para implementar continuar. Ver las respuestas a continuación.Respuestas:
En Lua 5.2, la mejor solución es usar goto:
Esto es compatible con LuaJIT desde la versión 2.0.1
fuente
continue
día real . Elgoto
reemplazo no se ve muy bien y necesita más líneas. Además, ¿no crearía problemas si tuviera más de un ciclo haciendo esto en una función, ambas con::continue::
? Inventar un nombre por ciclo no suena como algo digno de hacer.La forma en que el lenguaje gestiona el alcance léxico crea problemas al incluir ambos
goto
ycontinue
. Por ejemplo,La declaración de
local a
dentro del cuerpo del bucle enmascara la variable externa nombradaa
, y el alcance de ese local se extiende a través de la condición de launtil
declaración, por lo que la condición está probando lo más internoa
.Si
continue
existiera, tendría que restringirse semánticamente para que solo sea válido después de que todas las variables utilizadas en la condición hayan entrado en el alcance. Esta es una condición difícil de documentar al usuario y aplicar en el compilador. Se han discutido varias propuestas sobre este tema, incluida la respuesta simple de no permitircontinue
con elrepeat ... until
estilo de bucle. Hasta el momento, ninguno ha tenido un caso de uso suficientemente convincente para incluirlos en el idioma.La solución general es invertir la condición que haría
continue
que se ejecute a, y recolectar el resto del cuerpo del bucle bajo esa condición. Entonces, el siguiente ciclopodría ser escrito
Es lo suficientemente claro, y generalmente no es una carga a menos que tenga una serie de sacrificios elaborados que controlan la operación del bucle.
fuente
until...
.goto
en Lua 5.2. Naturalmente,goto
tiene el mismo problema. Finalmente, decidieron que, independientemente de los costos de tiempo de ejecución y / o generación de código que protegieran, valía la pena tener los beneficios de tener una flexibilidadgoto
que se pueda utilizar para emular tantocontinue
a nivel múltiple como a nivel múltiplebreak
. Tendría que buscar en los archivos de la lista Lua los hilos relevantes para obtener los detalles. Como lo presentarongoto
, obviamente no era insuperable.local
es una directiva solo del compilador, no importa qué instrucciones de tiempo de ejecución se encuentrenlocal
y el uso variable, no necesita cambiar nada en el compilador para mantener el mismo comportamiento de alcance. Sí, esto podría no ser tan obvio y necesitará documentación adicional, pero, para reiterar nuevamente, requiere CERO cambios en el compilador.repeat do break end until true
ejemplo en mi respuesta ya genera exactamente el mismo código de bytes que el compilador continuaría, la única diferencia es que concontinue
usted no necesitaría una sintaxis extra fea para usarlo.do{int i=0;}while (i == 0);
falla, o en C ++:do int i=0;while (i==0);
también falla ("no se declaró en este ámbito"). Demasiado tarde para cambiar eso ahora en Lua, desafortunadamente.Puede envolver el cuerpo del bucle en adicional
repeat until true
y luego usarlodo break end
dentro para continuar. Naturalmente, necesitará configurar banderas adicionales si también tiene la intención debreak
salir del ciclo.Esto se repetirá 5 veces, imprimiendo 1, 2 y 3 cada vez.
¡Esta construcción incluso se traduce en un código
JMP
de operación literal en Lua bytecode!fuente
luac
resultados en SO! Tenga unDirectamente del diseñador del propio Lua :
fuente
continue
en Lua, lo siento".La primera parte se responde en las preguntas frecuentes como se señaló como asesinado .
En cuanto a una solución alternativa, puede envolver el cuerpo del bucle en una función y
return
desde el principio, p. Ej.O si desea ambas
break
ycontinue
funcionalidad, haga que la función local realice la prueba, p. Ej.fuente
collectgarbage("count")
incluso después de sus simples 100 intentos y luego hablaremos. Tal optimización "prematura" evitó que un proyecto de alta carga se reiniciara cada minuto la semana pasada.Nunca he usado Lua antes, pero lo busqué en Google y se me ocurrió esto:
http://www.luafaq.org/
Verifique la pregunta 1.26 .
fuente
Podemos lograrlo de la siguiente manera, saltará números pares
O / P:
fuente
Nos encontramos con este escenario muchas veces y simplemente usamos una bandera para simular continuar. Tratamos de evitar el uso de declaraciones goto también.
Ejemplo: el código tiene la intención de imprimir las declaraciones de i = 1 a i = 10 excepto i = 3. Además, también imprime "loop start", loop end "," if start "y" if end "para simular otras instrucciones anidadas que existen en su código.
se logra encerrando todas las declaraciones restantes hasta el alcance final del bucle con un indicador de prueba.
No digo que este sea el mejor enfoque, pero nos funciona perfectamente.
fuente
Lua es un lenguaje de script ligero que quiere ser lo más pequeño posible. Por ejemplo, muchas operaciones unarias como el incremento previo / posterior no están disponibles
En lugar de continuar, puedes usar goto like
fuente
De nuevo con la inversión, simplemente puede usar el siguiente código:
fuente
¿Por qué no hay continuación?
Porque es innecesario¹. Hay muy pocas situaciones en las que un desarrollador lo necesite.
A) Cuando tiene un bucle muy simple, diga una línea de 1 o 2 líneas, entonces puede cambiar la condición del bucle y todavía es bastante legible.
B) Cuando está escribiendo un código de procedimiento simple (también conocido como cómo escribimos código en el siglo pasado), también debería estar aplicando una programación estructurada (también conocido como cómo escribimos un código mejor en el siglo pasado)
C) Si está escribiendo código orientado a objetos, su cuerpo de bucle debe consistir en no más de una o dos llamadas de método a menos que pueda expresarse en una o dos líneas (en cuyo caso, consulte A)
D) Si está escribiendo código funcional, simplemente devuelva una llamada simple para la próxima iteración.
El único caso en el que desea utilizar una
continue
palabra clave es si desea codificar Lua como si fuera python, que simplemente no lo es.¿Qué soluciones hay para ello?
A menos que se aplique A), en cuyo caso no hay necesidad de ninguna solución alternativa, debe estar haciendo una programación estructurada, orientada a objetos o funcional. Esos son los paradigmas para los que Lua fue creado, por lo que estarías luchando contra el idioma si te esfuerzas por evitar sus patrones.
Alguna aclaración:
¹ Lua es un lenguaje muy minimalista. Intenta tener la menor cantidad de características posibles, y una
continue
declaración no es una característica esencial en ese sentido.Creo que esta filosofía del minimalismo es bien captada por Roberto Ierusalimschy en esta entrevista de 2019 :
² Parece que hay una gran cantidad de programadores que vienen a Lua desde otros idiomas porque cualquier programa para el que están tratando de escribir los usa, y muchos de ellos quieren no parecen querer escribir nada más que su idioma de elección, lo que lleva a muchas preguntas como "¿Por qué Lua no tiene la función X?"
Matz describió una situación similar con Ruby en una entrevista reciente :
³ Hay algunas maneras de hackear esto; algunos usuarios han sugerido usar
goto
, lo cual es una aproximación lo suficientemente buena en la mayoría de los casos, pero se pone muy feo muy rápidamente y se rompe completamente con bucles anidados. El uso degoto
s también lo pone en peligro de recibir una copia de SICP cada vez que muestra su código a otra persona.fuente
continue
podría ser una característica conveniente, pero eso no lo hace necesario . Mucha gente usa Lua bien sin él, por lo que realmente no hay razón para que sea otra cosa que una característica ordenada que no es esencial para ningún lenguaje de programación.