Tenho lidado muito com Lua nos últimos meses e realmente gosto da maioria dos recursos, mas ainda estou perdendo algo entre eles:
- Por que não existe
continue
? - Quais soluções alternativas existem para isso?
loops
lua
language-design
Dant
fonte
fonte
goto
declaração que pode ser usada para implementar continue. Veja as respostas abaixo.Respostas:
No Lua 5.2, a melhor solução alternativa é usar goto:
Isso é suportado no LuaJIT desde a versão 2.0.1
fonte
continue
um dia real . Agoto
substituição não parece muito agradável e precisa de mais linhas. Além disso, isso não criaria problemas se você tivesse mais de um loop fazendo isso em uma função, ambos com::continue::
? Criar um nome por loop não parece uma coisa decente.A maneira como o idioma gerencia o escopo lexical cria problemas com a inclusão de ambos
goto
econtinue
. Por exemplo,A declaração de
local a
dentro do corpo do loop mascara a variável externa denominadaa
e o escopo desse local se estende pela condição dauntil
instrução, para que a condição esteja testando o mais internoa
.Se
continue
existisse, teria que ser restrito semanticamente para ser válido somente depois que todas as variáveis usadas na condição entrassem em escopo. Essa é uma condição difícil de documentar para o usuário e impor no compilador. Várias propostas em torno dessa questão foram discutidas, incluindo a resposta simples de desaprovarcontinue
orepeat ... until
estilo do loop. Até o momento, nenhum teve um caso de uso suficientemente atraente para incluí-los no idioma.A solução alternativa é geralmente inverter a condição que causaria
continue
a execução de um e coletar o restante do corpo do loop sob essa condição. Então, o seguinte looppoderia ser escrito
É claro o suficiente, e geralmente não é um fardo, a menos que você tenha uma série de abates elaborados que controlam a operação do loop.
fonte
until...
.goto
no Lua 5.2. Naturalmente,goto
tem o mesmo problema. Eles finalmente decidiram que, independentemente do custo de tempo de execução e / ou de geração de código, os benefícios valiam por ter um sistema flexívelgoto
que pode ser usado para emular os doiscontinue
e os vários níveisbreak
. Você precisaria procurar nos arquivos da lista Lua os segmentos relevantes para obter os detalhes. Desde que eles introduziramgoto
, obviamente não era intransponível.local
é uma diretiva apenas para compilador - não importa quais são as instruções de tempo de execuçãolocal
e o uso variável - você não precisa alterar nada no compilador para manter o mesmo comportamento de escopo. Sim, isso pode não ser tão óbvio e precisa de alguma documentação adicional, mas, para reiterar novamente, requer ZERO alterações no compilador.repeat do break end until true
Por exemplo, na minha resposta já gera exatamente o mesmo bytecode que o compilador continuaria, a única diferença é quecontinue
você não precisaria de uma sintaxe extra feia para usá-lo.do{int i=0;}while (i == 0);
falha ou em C ++:do int i=0;while (i==0);
também falha ("não foi declarado neste escopo"). Tarde demais para mudar isso agora em Lua, infelizmente.Você pode envolver o corpo do loop em adicional
repeat until true
e, em seguida, usá-lodo break end
para efeito de continuar. Naturalmente, você precisará configurar sinalizadores adicionais se também quiser realmentebreak
ficar fora de loop.Isso repetirá 5 vezes, imprimindo 1, 2 e 3 a cada vez.
Essa construção é traduzida literalmente em um opcode
JMP
no lua bytecode!fonte
luac
resultados no SO! Tenha umDiretamente do designer do próprio Lua :
fonte
continue
Lua, desculpe".A primeira parte é respondida no FAQ como morto fora pontudo.
Quanto a uma solução alternativa, você pode agrupar o corpo do loop em uma função e
return
desde o início, por exemplo,Ou, se você deseja ambos
break
econtinue
funcionalidade, faça com que a função local realize o teste, por exemplofonte
collectgarbage("count")
mesmo após suas 100 tentativas simples e depois conversaremos. Essa otimização "prematura" salvou um projeto de alta carga da reinicialização a cada minuto na semana passada.Eu nunca usei Lua antes, mas pesquisei no Google e criei isso:
http://www.luafaq.org/
Verifique a pergunta 1.26 .
fonte
Podemos alcançá-lo como abaixo, pulará números pares
O / P:
fonte
Encontramos esse cenário muitas vezes e simplesmente usamos um sinalizador para simular a continuação. Tentamos evitar o uso de instruções goto também.
Exemplo: O código pretende imprimir as instruções de i = 1 a i = 10, exceto i = 3. Além disso, ele também imprime "loop start", loop end "," if start "e" if end "para simular outras instruções aninhadas que existem no seu código.
é alcançado colocando-se todas as instruções restantes até o escopo final do loop com um sinalizador de teste.
Não estou dizendo que essa é a melhor abordagem, mas funciona perfeitamente para nós.
fonte
Lua é uma linguagem de script leve que deseja menor quanto possível. Por exemplo, muitas operações unárias, como pré / pós incremento, não estão disponíveis
Em vez de continuar, você pode usar ir como
fonte
Novamente com a inversão, você pode simplesmente usar o seguinte código:
fonte
Por que não há como continuar?
Porque é desnecessário¹. Existem muito poucas situações em que um desenvolvedor precisaria.
A) Quando você tem um loop muito simples, digamos um liner de 1 ou 2, você pode simplesmente mudar a condição do loop e ainda assim é legível.
B) Ao escrever código processual simples (também conhecido como como escrevemos código no século passado), você também deve aplicar programação estruturada (também conhecido como como escrevemos melhor código no século passado)
C) Se você estiver escrevendo código orientado a objeto, seu corpo do loop deve consistir em não mais de uma ou duas chamadas de método, a menos que possa ser expresso em uma ou duas linhas (nesse caso, consulte A)
D) Se você estiver escrevendo código funcional, basta retornar uma chamada final simples para a próxima iteração.
O único caso em que você deseja usar uma
continue
palavra-chave é codificar Lua como se fosse python, o que simplesmente não é.²Quais soluções alternativas existem para isso?
A menos que A) se aplique; nesse caso, não há necessidade de soluções alternativas, você deve estar fazendo programação estruturada, orientada a objetos ou funcional. Esses são os paradigmas para os quais Lua foi criada, então você estaria lutando contra a linguagem se se esforçar para evitar os padrões deles.³
Alguns esclarecimentos:
Lua é uma linguagem muito minimalista. Ele tenta ter o mínimo de recursos possível e uma
continue
declaração não é um recurso essencial nesse sentido.Acho que essa filosofia do minimalismo é bem capturada por Roberto Ierusalimschy nesta entrevista de 2019 :
² Parece haver uma grande quantidade de programadores chegando a Lua de outras linguagens, porque qualquer programa que eles estão tentando criar o script o usa, e muitos deles querem não parecem querer escrever outra coisa senão a linguagem deles. opção, o que leva a muitas perguntas como "Por que Lua não possui o recurso X?"
Matz descreveu uma situação semelhante com Ruby em uma entrevista recente :
³ Existem algumas maneiras de contornar isso; alguns usuários sugeriram o uso
goto
, o que é uma aproximação suficientemente boa na maioria dos casos, mas fica muito feio muito rapidamente e quebra completamente com loops aninhados. O uso degoto
s também coloca você em risco de ter uma cópia do SICP sempre que você mostra seu código a mais alguém.fonte
continue
pode ser um recurso conveniente, mas isso não o torna necessário . Muitas pessoas usam Lua muito bem sem ele, então não há realmente nenhum caso de ser algo além de um recurso interessante que não é essencial para qualquer linguagem de programação.