J'ai beaucoup traité avec Lua ces derniers mois et j'aime beaucoup la plupart des fonctionnalités, mais il me manque encore quelque chose parmi celles-ci:
- Pourquoi n'y a-t-il pas
continue
? - Quelles solutions de contournement existe-t-il?
J'ai beaucoup traité avec Lua ces derniers mois et j'aime beaucoup la plupart des fonctionnalités, mais il me manque encore quelque chose parmi celles-ci:
continue
? La façon dont la langue gère le domaine lexical crée des problèmes avec notamment les deux goto
et continue
. Par exemple,
local a=0
repeat
if f() then
a=1 --change outer a
end
local a=f() -- inner a
until a==0 -- test inner a
La déclaration d' local a
à l'intérieur du corps de la boucle des masques à l'extérieur variable nommée a
, et la portée de ce local s'étend sur l'état de l' until
déclaration si la condition est tests les plus intimes a
.
Si continue
existait, il devrait être limité du point de vue sémantique pour être valide uniquement après que toutes les variables utilisées dans l'état de venir dans l'étendue. C'est une condition difficile à document à l'utilisateur et l'appliquer dans le compilateur. Différentes propositions autour de cette question ont été abordés, y compris la réponse la plus simple de interdisez continue
avec l' repeat ... until
style de boucle. Jusqu'à présent, aucun n'a suffisamment convaincante de cas d'utilisation pour obtenir inclus dans la langue.
Le travail autour de est généralement pour inverser la condition qui entraîne un continue
à être exécutée, et de recueillir le reste du corps de la boucle en vertu de cette condition. Ainsi, la boucle suivante
-- not valid Lua 5.1 (or 5.2)
for k,v in pairs(t) do
if isstring(k) then continue end
-- do something to t[k] when k is not a string
end
peut être écrite
-- valid Lua 5.1 (or 5.2)
for k,v in pairs(t) do
if not isstring(k) then
-- do something to t[k] when k is not a string
end
end
C'est assez clair, et généralement pas un fardeau, sauf si vous avez une série de complexe de rebuts qui contrôle le fonctionnement en boucle.
Vous pouvez envelopper le corps de la boucle dans repeat until true
supplémentaire, puis utiliser do break end
inside pour obtenir l'effet de continuer. Bien sûr, vous aurez besoin de mettre en place des drapeaux supplémentaires si vous avez l' intention aussi vraiment break
de la boucle ainsi.
Cela fera une boucle 5 fois, en imprimant 1, 2 et 3 à chaque fois.
for idx = 1, 5 do
repeat
print(1)
print(2)
print(3)
do break end -- goes to next iteration of for
print(4)
print(5)
until true
end
Cette construction traduit même en un seul opcode JMP
dans le bytecode Lua!
$ luac -l continue.lua
main <continue.lua:0,0> (22 instructions, 88 bytes at 0x23c9530)
0+ params, 6 slots, 0 upvalues, 4 locals, 6 constants, 0 functions
1 [1] LOADK 0 -1 ; 1
2 [1] LOADK 1 -2 ; 3
3 [1] LOADK 2 -1 ; 1
4 [1] FORPREP 0 16 ; to 21
5 [3] GETGLOBAL 4 -3 ; print
6 [3] LOADK 5 -1 ; 1
7 [3] CALL 4 2 1
8 [4] GETGLOBAL 4 -3 ; print
9 [4] LOADK 5 -4 ; 2
10 [4] CALL 4 2 1
11 [5] GETGLOBAL 4 -3 ; print
12 [5] LOADK 5 -2 ; 3
13 [5] CALL 4 2 1
14 [6] JMP 6 ; to 21 -- Here it is! If you remove do break end from code, result will only differ by this single line.
15 [7] GETGLOBAL 4 -3 ; print
16 [7] LOADK 5 -5 ; 4
17 [7] CALL 4 2 1
18 [8] GETGLOBAL 4 -3 ; print
19 [8] LOADK 5 -6 ; 5
20 [8] CALL 4 2 1
21 [1] FORLOOP 0 -17 ; to 5
22 [10] RETURN 0 1
Directement à partir du concepteur de Lua lui-même:
Notre principale préoccupation avec "continuer" est qu'il y a plusieurs autres structures de contrôle qui (à notre avis) sont plus ou moins aussi important que "continuer" et peut même se substituer à elle. (E. g., rompre avec étiquettes [comme en Java] ou même un plus générique goto.) "continuer", ne semble pas plus spécial que les autres le contrôle de la structure des mécanismes, sauf qu'il est présent dans plus de langues. (Perl a en fait deux "continuer", "suivant" et "redo". Les deux sont utiles.)
La première partie de réponse dans la FAQ comme immolé souligné.
Comme pour une solution de contournement, vous pouvez envelopper le corps de la boucle dans une fonction, et return
au début de celle, par exemple
-- Print the odd numbers from 1 to 99
for a = 1, 99 do
(function()
if a % 2 == 0 then
return
end
print(a)
end)()
end
Ou si vous voulez les deux break
et continue
fonctionnalités, que la fonction d'effectuer le test, par ex.
local a = 1
while (function()
if a > 99 then
return false; -- break
end
if a % 2 == 0 then
return true; -- continue
end
print(a)
return true; -- continue
end)() do
a = a + 1
end
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.