J’ai beaucoup travaillé avec Lua ces derniers mois et j’aime vraiment la plupart des fonctionnalités, mais il me manque encore quelque chose parmi celles-ci:
continue
? La façon dont le langage gère la scope lexicale crée des problèmes d’inclusion à la fois du goto
et du 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 de local a
à l’intérieur du corps de la boucle masque la variable externe nommée a
et la scope de ce local s’étend à travers la condition de l’instruction till de sorte que la condition teste le plus profond a
.
Si continue
existait, il devrait être restreint sémantiquement pour être seulement valide après que toutes les variables utilisées dans la condition soient entrées dans la scope. C’est une condition difficile à documenter pour l’utilisateur et à appliquer dans le compilateur. Diverses propositions autour de cette question ont été discutées, y compris la simple réponse de refus de continue
avec la repeat ... until
style de boucle. Jusqu’à présent, aucun cas d’utilisation suffisamment convaincant n’a été présenté pour les inclure dans la langue.
Le travail consiste généralement à inverser la condition à l’origine de l’exécution continue
et à collecter le rest du corps de la boucle dans cette condition. Donc, la boucle suivante
-- not valid Lua 5.1 (or 5.2) for k,v in pairs(t) do if isssortingng(k) then continue end -- do something to t[k] when k is not a ssortingng end
pourrait être écrit
-- valid Lua 5.1 (or 5.2) for k,v in pairs(t) do if not isssortingng(k) then -- do something to t[k] when k is not a ssortingng end end
C’est assez clair, et généralement pas un fardeau à moins que vous ayez une série de rejets élaborés qui contrôlent le fonctionnement de la boucle.
Dans Lua 5.2, la meilleure solution consiste à utiliser goto:
-- prints odd numbers in [|1,10|] for i=1,10 do if i % 2 == 0 then goto continue end print(i) ::continue:: end
Ceci est supporté dans LuaJIT depuis la version 2.0.1
Vous pouvez envelopper le corps de la boucle dans une repeat until true
supplémentaire repeat until true
, puis utiliser ” do break end
pour continuer. Naturellement, vous devrez configurer des indicateurs supplémentaires si vous souhaitez également sortir de la boucle.
Cela se bouclera 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 se traduit même en littéral un opcode JMP
en bytecode Lua!
$ luac -l continue.lua main (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
La première partie reçoit une réponse dans la FAQ, comme indiqué.
Comme pour une solution de contournement, vous pouvez envelopper le corps de la boucle dans une fonction et return
tôt, 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 fonctionnalités de break
et de continue
, la fonction locale doit effectuer le test, par exemple
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
Directement du designer de Lua lui – même :
Notre principale préoccupation avec “continue” est qu’il existe plusieurs autres structures de contrôle qui (à notre avis) sont plus ou moins importantes que “continue” et peuvent même la remplacer. (Par exemple, la rupture avec les labels [comme en Java] ou même un goto plus générique.) “Continue” ne semble pas plus spécial que les autres mécanismes de structure de contrôle, sauf qu’il est présent dans plus de langues. (Perl a en fait deux instructions “continue”, “next” et “redo”. Les deux sont utiles.)
Je n’ai jamais utilisé Lua auparavant, mais je l’ai googlé et j’ai trouvé ceci:
Vérifiez la question 1.26 .
Ceci est une plainte commune. Les auteurs de Lua ont estimé que continuer n’était que l’un des nombreux mécanismes de stream de contrôle possibles (le fait qu’il ne puisse pas fonctionner avec les règles de scope de répétition / jusqu’à était un facteur secondaire).
Dans Lua 5.2, il existe une instruction goto qui peut être facilement utilisée pour faire le même travail.
Avec l’inversion, vous pouvez simplement utiliser le code suivant:
for k,v in pairs(t) do if not isssortingng(k) then -- do something to t[k] when k is not a ssortingng end
Nous pouvons y arriver comme ci-dessous, il sautera des nombres pairs
local len = 5 for i = 1, len do repeat if i%2 == 0 then break end print(" i = "..i) break until true end
O / P:
i = 1 i = 3 i = 5
Nous avons rencontré ce scénario plusieurs fois et nous utilisons simplement un drapeau pour simuler continuer. Nous essayons également d’éviter l’utilisation des instructions goto.
Exemple: le code a l’intention d’imprimer les nombres de 1 à 10 sauf 3. En outre, il imprime également “loop start”, loop end “,” if start “et” if end “pour simuler d’autres instructions qui existent dans votre code et déclarations nestedes.
size = 10 for i=1, size do print("loop start") if whatever then print("if start") if (i == 3) then print("i is 3") --continue end print(j) print("if end") end print("loop end") end
est réalisé en incluant toutes les instructions restantes jusqu’à la fin de la boucle avec un indicateur de test.
size = 10 for i=1, size do print("loop start") local continue = false; -- initialize flag at the start of the loop if whatever then print("if start") if (i == 3) then print("i is 3") continue = true end if continue==false then -- test flag print(j) print("if end") end end if (continue==false) then -- test flag print("loop end") end end
Je ne dis pas que c’est la meilleure approche mais cela fonctionne parfaitement pour nous.