IT

루아에는 왜“계속”진술이 없습니까?

lottoking 2020. 6. 28. 17:59
반응형

루아에는 왜“계속”진술이 없습니까?


지난 몇 달 동안 Lua를 많이 다루었 고 대부분의 기능을 정말로 좋아하지만 여전히 그중 하나가 빠져 있습니다.

  • continue없습니까?
  • 어떤 해결 방법이 있습니까?

Lua 5.2에서 가장 좋은 해결 방법은 goto를 사용하는 것입니다.

-- prints odd numbers in [|1,10|]
for i=1,10 do
  if i % 2 == 0 then goto continue end
  print(i)
  ::continue::
end

버전 2.0.1 이후 LuaJIT에서 지원됩니다.


언어는 어휘 범위를 관리하는 방법은 모두를 포함하여 문제 생성 gotocontinue. 예를 들어

local a=0
repeat 
    if f() then
        a=1 --change outer a
    end
    local a=f() -- inner a
until a==0 -- test inner a

local a내부 루프 본문 선언은 명명 된 외부 변수를 숨기고 a해당 로컬의 범위는 until명령문 의 조건에 걸쳐 확장 되므로 조건이 가장 안쪽을 테스트합니다 a.

continue존재하는 경우 조건에 사용 된 모든 변수가 범위에 들어간 후에 만 ​​의미 적으로 유효하도록 제한되어야합니다. 이것은 사용자에게 문서화하고 컴파일러에서 적용하기 어려운 조건입니다. 이 문제를 해결 다양한 제안 허용하지의 간단한 대답을 포함하여 논의되었다 continuerepeat ... until루프 스타일. 지금까지 아무도 언어에 포함시킬만큼 충분한 유스 케이스가 없었습니다.

해결 방법은 일반적으로 a continue가 실행되도록 하는 조건을 반전시키고 해당 조건 에서 나머지 루프 본문을 수집하는 것입니다. 따라서 다음 루프

-- 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

쓸 수 있었다

-- 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

루프 작업을 제어하는 ​​일련의 정교한 컬이없는 한 충분히 명확하며 일반적으로 부담이되지 않습니다.


루프 바디를 추가로 포장 repeat until true한 다음 do break end계속 을 위해 내부를 사용할 수 있습니다 . 물론 실제로 break루프를 벗어나 려면 추가 플래그를 설정해야합니다 .

5 번 반복되며 매번 1, 2, 3을 인쇄합니다.

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

이 구조 JMP는 루아 바이트 코드 에서 문자 그대로 하나의 opcode 변환됩니다 !

$ 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


첫 번째 부분은 살해 된 것으로 FAQ 에서 답변 됩니다 .

해결 방법은 루프 본문을 함수로 감싸서 return일찍 시작할 수 있습니다.

-- 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

또는 기능 breakcontinue기능을 모두 원한다면 로컬 기능으로 테스트를 수행하십시오.

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

루아 자신의 디자이너로부터 직접 :

Our main concern with "continue" is that there are several other control structures that (in our view) are more or less as important as "continue" and may even replace it. (E.g., break with labels [as in Java] or even a more generic goto.) "continue" does not seem more special than other control-structure mechanisms, except that it is present in more languages. (Perl actually has two "continue" statements, "next" and "redo". Both are useful.)


I've never used Lua before, but I Googled it and came up with this:

http://www.luafaq.org/

Check question 1.26.

This is a common complaint. The Lua authors felt that continue was only one of a number of possible new control flow mechanisms (the fact that it cannot work with the scope rules of repeat/until was a secondary factor.)

In Lua 5.2, there is a goto statement which can be easily used to do the same job.


We can achieve it as below, it will skip even numbers

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

We encountered this scenario many times and we simply use a flag to simulate continue. We try to avoid the use of goto statements as well.

Example: The code intends to print the statements from i=1 to i=10 except i=3. In addition it also prints "loop start", loop end", "if start", and "if end" to simulate other nested statements that exist in your code.

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

is achieved by enclosing all remaining statements until the end scope of the loop with a test flag.

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

I'm not saying that this is the best approach but it works perfectly to us.


Again with the inverting, you could simply use the following code:

for k,v in pairs(t) do
  if not isstring(k) then 
    -- do something to t[k] when k is not a string
end

참고URL : https://stackoverflow.com/questions/3524970/why-does-lua-have-no-continue-statement

반응형