Ich habe in den letzten Monaten viel mit Lua zu tun gehabt und ich mag die meisten Funktionen wirklich, aber mir fehlt immer noch etwas unter diesen:
- Warum gibt es keine
continue
? - Welche Problemumgehungen gibt es dafür?
loops
lua
language-design
Dant
quelle
quelle
goto
Erklärung, die zur Implementierung von continue verwendet werden kann. Siehe die Antworten unten.Antworten:
In Lua 5.2 ist die beste Problemumgehung, goto zu verwenden:
Dies wird in LuaJIT seit Version 2.0.1 unterstützt
quelle
continue
einen Tag enthalten. Dergoto
Ersatz sieht nicht sehr gut aus und benötigt mehr Zeilen. Würde das nicht auch Probleme verursachen, wenn Sie mehr als eine Schleife in einer Funktion hätten, beide mit::continue::
? Einen Namen pro Schleife zu erfinden, klingt nicht nach einer anständigen Sache.Die Art und Weise, wie die Sprache den lexikalischen Bereich verwaltet, führt zu Problemen beim Einbeziehen von
goto
undcontinue
. Beispielsweise,Die Deklaration
local a
innerhalb des Schleifenkörpers maskiert die genannte äußere Variablea
, und der Gültigkeitsbereich dieses lokalen Bereichs erstreckt sich über die Bedingung deruntil
Anweisung, sodass die Bedingung die innerste testeta
.Wenn
continue
vorhanden, müsste es semantisch eingeschränkt werden, um erst gültig zu sein, nachdem alle in der Bedingung verwendeten Variablen in den Geltungsbereich gekommen sind. Dies ist eine schwierige Bedingung, die dem Benutzer dokumentiert und im Compiler durchgesetzt werden kann. Verschiedene Vorschläge zu diesem Thema wurden diskutiert, einschließlich der einfachen Antwort,continue
denrepeat ... until
Stil der Schleife nicht zuzulassen. Bisher hatte keiner einen ausreichend überzeugenden Anwendungsfall, um sie in die Sprache aufzunehmen.Die Umgehung besteht im Allgemeinen darin, die Bedingung umzukehren, die dazu führen würde, dass a
continue
ausgeführt wird, und den Rest des Schleifenkörpers unter dieser Bedingung zu sammeln. Also die folgende Schleifekönnte geschrieben werden
Es ist klar genug und normalerweise keine Belastung, es sei denn, Sie haben eine Reihe von aufwändigen Keulungen, die den Schleifenbetrieb steuern.
quelle
until...
.goto
Lua 5.2 wurde in der Lua-Community viel darüber diskutiert . Hat natürlichgoto
das gleiche Problem. Sie entschieden schließlich, dass unabhängig von den Laufzeit- und / oder Codegenerierungskosten zum Schutz die Vorteile einer Flexibilitätgoto
, die sowohl zur Emulationcontinue
als auch auf mehreren Ebenen verwendet werden kann, wert sindbreak
. Sie müssten die Lua-Listenarchive nach den relevanten Threads durchsuchen , um die Details zu erhalten. Da sie eingeführt habengoto
, war es offensichtlich nicht unüberwindbar.local
ist eine reine Compiler-Direktive - es spielt keine Rolle, zwischen welchen Laufzeitinstruktionenlocal
und variabler Verwendung sie liegen - Sie müssen im Compiler nichts ändern, um das gleiche Gültigkeitsbereichsverhalten beizubehalten. Ja, dies ist möglicherweise nicht so offensichtlich und erfordert zusätzliche Dokumentation. Um es jedoch noch einmal zu wiederholen, sind NULL-Änderungen im Compiler erforderlich.repeat do break end until true
Beispiel in meiner Antwort generiert bereits genau den gleichen Bytecode, mit dem der Compiler fortfahren würde. Der einzige Unterschied besteht darin, dasscontinue
Sie für die Verwendung keine hässliche zusätzliche Syntax benötigen würden.do{int i=0;}while (i == 0);
fehlgeschlagen oder in C ++:do int i=0;while (i==0);
schlägt ebenfalls fehl ("wurde in diesem Bereich nicht deklariert"). Leider zu spät, um das jetzt in Lua zu ändern.Sie können den Schleifenkörper zusätzlich einwickeln
repeat until true
und danndo break end
innen verwenden, um fortzufahren. Natürlich müssen Sie zusätzliche Flags einrichten, wenn Sie auch wirklichbreak
außerhalb der Schleife sein möchten.Dies wird 5 Mal wiederholt und jedes Mal 1, 2 und 3 gedruckt.
Diese Konstruktion übersetzt sogar einen wörtlichen Opcode
JMP
in Lua-Bytecode!quelle
luac
auf SO! Habe eine wohlverdiente Gegenstimme :)Direkt vom Designer von Lua selbst :
quelle
continue
in Lua zu stecken, sorry."Der erste Teil ist in der antwortete FAQ als getötet aufgezeigt.
Als Problemumgehung können Sie den Körper der Schleife in eine Funktion einbinden und
return
frühzeitig daraus, zWenn Sie beides
break
undcontinue
Funktionalität wünschen , lassen Sie die lokale Funktion den Test durchführen, zquelle
collectgarbage("count")
auch nach Ihren einfachen 100 Versuchen, und dann werden wir reden. Eine solche "vorzeitige" Optimierung hat letzte Woche ein Hochlastprojekt vor dem Neustart jede Minute bewahrt.Ich habe Lua noch nie benutzt, aber ich habe es gegoogelt und mir Folgendes ausgedacht:
http://www.luafaq.org/
Überprüfen Sie Frage 1.26 .
quelle
Wir können es wie folgt erreichen, es werden gerade Zahlen übersprungen
O / P:
quelle
Wir sind diesem Szenario oft begegnet und verwenden einfach ein Flag, um die Fortsetzung zu simulieren. Wir versuchen, die Verwendung von goto-Anweisungen ebenfalls zu vermeiden.
Beispiel: Der Code beabsichtigt, die Anweisungen von i = 1 bis i = 10 mit Ausnahme von i = 3 zu drucken. Außerdem werden "Schleifenstart", "Schleifenende", "Wenn Start" und "Wenn Ende" gedruckt, um andere verschachtelte Anweisungen zu simulieren, die in Ihrem Code vorhanden sind.
wird erreicht, indem alle verbleibenden Anweisungen bis zum Ende der Schleife mit einem Testflag versehen werden.
Ich sage nicht, dass dies der beste Ansatz ist, aber er funktioniert perfekt für uns.
quelle
Auch beim Invertieren können Sie einfach den folgenden Code verwenden:
quelle
Lua ist eine leichte Skriptsprache, die so klein wie möglich sein soll. Beispielsweise sind viele unäre Operationen wie das Inkrementieren vor / nach dem Inkrementieren nicht verfügbar
Anstatt fortzufahren, können Sie goto like verwenden
quelle
Warum gibt es keine Fortsetzung?
Weil es unnötig ist¹. Es gibt sehr wenige Situationen, in denen ein Entwickler es brauchen würde.
A) Wenn Sie eine sehr einfache Schleife haben, z. B. einen 1- oder 2-Liner, können Sie die Schleifenbedingung einfach umdrehen und sie ist immer noch gut lesbar.
B) Wenn Sie einfachen prozeduralen Code schreiben (auch bekannt als wie wir Code im letzten Jahrhundert geschrieben haben), sollten Sie auch strukturierte Programmierung anwenden (auch bekannt als wie wir besseren Code im letzten Jahrhundert geschrieben haben).
C) Wenn Sie objektorientierten Code schreiben, sollte Ihr Schleifenkörper aus nicht mehr als einem oder zwei Methodenaufrufen bestehen, es sei denn, er kann in einem Ein- oder Zweizeiler ausgedrückt werden (in diesem Fall siehe A).
D) Wenn Sie Funktionscode schreiben, geben Sie einfach einen einfachen Tail-Call für die nächste Iteration zurück.
Der einzige Fall, in dem Sie ein
continue
Schlüsselwort verwenden möchten, ist, wenn Sie Lua wie Python codieren möchten, was es einfach nicht ist.²Welche Problemumgehungen gibt es dafür?
Sofern A) nicht zutrifft, sollten Sie in diesem Fall keine Problemumgehungen vornehmen. Sie sollten eine strukturierte, objektorientierte oder funktionale Programmierung durchführen. Das sind die Paradigmen, für die Lua gebaut wurde. Sie würden also gegen die Sprache kämpfen, wenn Sie alles daran setzen, ihre Muster zu vermeiden.³
Einige Klarstellungen:
¹ Lua ist eine sehr minimalistische Sprache. Es wird versucht, so wenige Funktionen wie möglich zu haben, und eine
continue
Aussage ist in diesem Sinne kein wesentliches Merkmal.Ich denke, diese Philosophie des Minimalismus wird von Roberto Ierusalimschy in diesem Interview von 2019 gut festgehalten :
² Es scheint eine große Anzahl von Programmierern zu geben, die aus anderen Sprachen nach Lua kommen, weil jedes Programm, für das sie ein Skript erstellen, es zufällig verwendet, und viele von ihnen scheinen nichts anderes als ihre Sprache schreiben zu wollen Auswahl, die zu vielen Fragen wie "Warum hat Lua keine X-Funktion?" führt.
Matz hat kürzlich in einem Interview eine ähnliche Situation mit Ruby beschrieben :
³ Es gibt einige Möglichkeiten, sich darum zu kümmern. Einige Benutzer haben die Verwendung vorgeschlagen
goto
, was in den meisten Fällen eine gute Annäherung ist, aber sehr schnell sehr hässlich wird und vollständig mit verschachtelten Schleifen bricht. Wenn Siegoto
s verwenden, besteht auch die Gefahr, dass Sie eine Kopie von SICP erhalten, wenn Sie Ihren Code jemand anderem zeigen.quelle
continue
Möglicherweise ist dies eine praktische Funktion, die jedoch nicht erforderlich ist . Viele Leute benutzen Lua ganz gut ohne es, also gibt es wirklich keinen Grund dafür, dass es etwas anderes als eine nette Funktion ist, die für keine Programmiersprache wesentlich ist.