Why does Lua have no “continue” statement?

后端 未结 11 1682
无人及你
无人及你 2020-12-07 13:23

I have been dealing a lot with Lua in the past few months, and I really like most of the features but I\'m still missing something among those:

  • Why is there no
相关标签:
11条回答
  • 2020-12-07 14:13

    The first part is answered in the FAQ as slain pointed out.

    As for a workaround, you can wrap the body of the loop in a function and return early from that, e.g.

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

    Or if you want both break and continue functionality, have the local function perform the test, e.g.

    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
    
    0 讨论(0)
  • 2020-12-07 14:15

    The way that the language manages lexical scope creates issues with including both goto and continue. For example,

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

    The declaration of local a inside the loop body masks the outer variable named a, and the scope of that local extends across the condition of the until statement so the condition is testing the innermost a.

    If continue existed, it would have to be restricted semantically to be only valid after all of the variables used in the condition have come into scope. This is a difficult condition to document to the user and enforce in the compiler. Various proposals around this issue have been discussed, including the simple answer of disallowing continue with the repeat ... until style of loop. So far, none have had a sufficiently compelling use case to get them included in the language.

    The work around is generally to invert the condition that would cause a continue to be executed, and collect the rest of the loop body under that condition. So, the following loop

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

    could be written

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

    It is clear enough, and usually not a burden unless you have a series of elaborate culls that control the loop operation.

    0 讨论(0)
  • 2020-12-07 14:17

    Why is there no continue?

    Because it's unnecessary¹. There's very few situations where a dev would need it.

    A) When you have a very simple loop, say a 1- or 2-liner, then you can just turn the loop condition around and it's still plenty readable.

    B) When you're writing simple procedural code (aka. how we wrote code in the last century), you should also be applying structured programming (aka. how we wrote better code in the last century)

    C) If you're writing object-oriented code, your loop body should consist of no more than one or two method calls unless it can be expressed in a one- or two-liner (in which case, see A)

    D) If you're writing functional code, just return a plain tail-call for the next iteration.

    The only case when you'd want to use a continue keyword is if you want to code Lua like it's python, which it just isn't.²

    What workarounds are there for it?

    Unless A) applies, in which case there's no need for any workarounds, you should be doing Structured, Object-Oriented or Functional programming. Those are the paradigms that Lua was built for, so you'd be fighting against the language if you go out of your way to avoid their patterns.³


    Some clarification:

    ¹ Lua is a very minimalistic language. It tries to have as few features as it can get away with, and a continue statement isn't an essential feature in that sense.

    I think this philosophy of minimalism is captured well by Roberto Ierusalimschy in this 2019 interview:

    add that and that and that, put that out, and in the end we understand the final conclusion will not satisfy most people and we will not put all the options everybody wants, so we don’t put anything. In the end, strict mode is a reasonable compromise.

    ² There seems to be a large ammount of programmers coming to Lua from other languages because whatever program they're trying to script for happens to use it, and many of them want don't seem to want to write anything other than their language of choice, which leads to many questions like "Why doesn't Lua have X feature?"

    Matz described a similar situation with Ruby in a recent interview:

    The most popular question is: "I’m from the language X community; can’t you introduce a feature from the language X to Ruby?", or something like that. And my usual answer to these requests is… "no, I wouldn’t do that", because we have different language design and different language development policies.

    ³ There's a few ways to hack your way around this; some users have suggested using goto, which is a good enough aproximation in most cases, but gets very ugly very quickly and breaks completely with nested loops. Using gotos also puts you in danger of having a copy of SICP thrown at you whenever you show your code to anybody else.

    0 讨论(0)
  • 2020-12-07 14:18

    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
    
    0 讨论(0)
  • 2020-12-07 14:19

    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
    
    0 讨论(0)
提交回复
热议问题