Loops

Q-SYS Control 101 Training (German) : Flow Control

3 ) Einfache Kommunikation

12m 54s

4 ) Block Controller

18m 50s

6 ) Flow Control

36m 23s

7 ) Fazit „Control 101“

1m 29s

Übungsbeschreibung

Loops 13m 26s

Lerne, wie du dein Skript aufbauen und handhaben kannst, um Funktionen mit Loops mehrfach zu wiederholen.

Video Transkript

Loops 13m 26s
0:08
Es gibt jede Menge Situationen, in denen derselbe Code-Abschnitt viele Male nacheinander
0:12
ausgeführt werden soll. Eine Schleife ist eine Steuerungsstruktur, die uns erlaubt, eine Anweisung
0:19
oder Gruppe von Anweisungen mehrfach auszuführen, je nachdem, ob bestimmte Bedingungen
0:24
erfüllt werden.
0:25
Im Prinzip ist es so: Wenn das Skript bei deiner Schleife ankommt, analysiert er die Bedingung. Ist die
0:32
Bedingung erfüllt, führt er den bedingten Code aus und analysiert dann die Bedingung neu. Er macht
0:38
damit weiter, bis die Bedingung nicht mehr erfüllt wird, und ignoriert ab dann den Code.
0:44
Lua bietet uns drei Schleifen-Arten, die sich sehr ähneln, aber geringfügig darin unterscheiden, wie
0:49
sie mit ihren bedingten Anweisungen umgehen.
0:53
Eine „while“-Schleife wiederholt den Code wieder und wieder, solange die Bedingte Anweisung wahr
0:58
ist. Wenn sich die Bedingte Anweisung nie ändert, wird die Schleife endlos fortgesetzt, bis er in einer
1:04
Fehlermeldung endet.
1:06
Eine „for“-Schleife führt den Code so viele Male aus, wie es vorher von dir festgelegt wurde.
1:12
Und eine „repeat“-Schleife wiederholt den Code immer wieder, bis eine bestimmte Bedingung erfüllt ist.
1:19
Bauen wir ein paar einfache Schleifen zur Demonstration und wenden sie dann auf unser Q-SYS
1:23
Design an. Zuerst die „while“-Schleife. Definieren wir Variable x als 5 und erstellen eine Schleife, der
1:33
x um 1 erhöht, bis der Wert 10 erreicht ist.
1:37
Unsere Bedingte Anweisung für „while“ kann (x<10) sein. Dann fügen wir das sehr wichtige
1:44
reservierte Wort „do“ ein, das den Hauptteil unseres bedingten Codes einleitet. Wir nehmen einfach
1:52
x und definieren es neu als seinen aktuellen Wert plus 1. Dann geben wir den neuen X-Wert aus als
2:00
Beleg dafür, dass diese Schleife durchgelaufen ist, und schreiben „end“ zum Beenden unserer Anweisung.
2:06
Wenn x zum ersten Mal in die Schleife eintritt, wird 1 addiert, und x wird zu 6. Dann gibt die Schleife
2:15
6 aus und kehrt zur Bedingten Anweisung zurück. Da x – nun mit Wert 6 – kleiner als 10 ist, durchläuft
2:23
es den bedingten Code wieder, wird zu 7, dann 8, dann 9, dann 10. Wenn es nun auf die Bedingte
2:30
Anweisung trifft, erfüllt es nicht mehr die Bedingung „kleiner als 10“, also wird der „do“-Code nicht
2:36
ausgeführt und die Schleife beendet.
2:40
Wir können dies prüfen, indem wir unser Skript laufen lassen und sehen, dass unser Debug-Fenster
2:45
am Ende jede Schleife x ausgibt und dann aufhört. Für uns sieht es natürlich so aus, als ob dies alles
2:52
augenblicklich und nicht sequentiell geschieht, aber wir können sicher sein, dass der Computer die
2:57
Schleifen der Reihe nach abarbeitet.
3:00
Als nächstes nehmen wir eine „for“-Schleife. Das ist ein genau festgelegte Schleife, der für jede von
3:06
uns angegebene Iteration nur einmal abläuft. Ich entferne die „while“-Anweisung und ersetze sie
3:13
durch „for i=1,5“. Hier repräsentiert „i“ eine Iteration, oder eine Instanz, dieser Schleife.
3:25
Hier ist die erste Zahl diejenige, bei der wir anfangen, und die zweite die Zahl, bei der wir aufhören
3:31
wollen. Wenn wir ihn jetzt starten, sieht es so aus, als ob dasselbe passiert wie bei unserer ersten
3:37
Schleife. Bei der ersten Iteration wurde die Schleife ausgeführt und änderte x in 6, bei der zweiten
3:43
wurde x zu 7, usw.
3:46
Nach der fünften Iteration ist x 10 und die Schleife ist beendet. Aber der Grund dafür ist ein
3:52
vollkommen anderer als in unserem vorigen Beispiel. Unsere „while“-Schleife endete, weil x die
3:59
Bedingte Anweisung nicht mehr erfüllt hat, aber hier ist der Schluss einfach dadurch erreicht, dass die
4:05
Schleife am Ende der angewiesenen Zahl von Durchläufen angekommen ist.
4:10
Ich möchte noch betonen, dass „i“ nichts mit „x“ zu tun hat, und es muss auch nicht bei 1 anfangen.
4:17
Ich könnte es von 22 bis 26 laufen lassen und wir würden dasselbe Ergebnis bekommen. Es durchläuft
4:24
eine Schleife für 22, einen für 23, 24, 25 und 26. Es ist einfach ein Bereich, aber die 22. Iteration tut
4:35
exakt dasselbe wie die erste.
4:38
Und zum Schluss schreiben wir eine „repeat“-Schleife. Ich behalte auch hier meinen bedingten Code
4:43
bei, aber wir ersetzen diese erste Zeile durch den Befehl „repeat“. Der größte Unterschied ist hier,
4:50
dass die „repeat“-Schleife nicht mit der bedingten Anweisung beginnt, sondern mit ihr endet. Das
4:57
heißt, dass die erste Schleife wird auf jeden Fall ausgeführt und anschließend geprüft, ob nach dessen
5:03
Beendigung fortgefahren werden soll.
5:06
Was die Syntax angeht, so brauchen wir nichts weiter als das Wort „repeat“, um unsere Schleife zu
5:12
starten. Wir können „end“ auch durch unsere Bedingte Anweisung „until“ ersetzen. Jetzt definieren
5:19
wir, was diese Bedingte Anweisung ist: In diesem Fall ist x gleichbedeutend mit 10.
5:26
Das Konzept ist dem der „while“-Schleife sehr ähnlich, der jedoch führt zuerst seine Analyse durch
5:33
und erledigt dann die Arbeit, während die „repeat“-Schleife zuerst die Arbeit ausführt und dann
5:38
analysiert, ob er weitermachen soll.
5:41
Kombinieren wir dies nun mit einigen der anderen Tools, die wir kennengelernt haben, und bauen
5:45
eine Schleife, der uns tatsächlich etwas bringt. Wir können eine Schleife z. B. dafür verwenden, ein
5:51
ansonsten repetitives Skript zu vereinfachen. Schaut euch diese programmierbare
5:57
Steuerungskomponente an, …
5:59
… in die wir fünf Umschalter namens „Flippy“ eingebaut haben und in der wir den EventHandler des
6:05
ersten „Flippy“ zum Starten einer Funktion verwenden. Diese Funktion enthält eine Wenn/Dann-
6:11
Anweisung. Wenn Flippys Wert 1 ist, zeigt seine .Legend „ON“ an. Sonst lautet seine .Legend „OFF“.
6:22
Das funktioniert: Unser Button zeigt anhand dieses Skripts die entsprechende Kennzeichnung an.
6:28
Aber das funktioniert nur beim ersten Button. Wenn ich das gleiche Verhalten für jeden Button
6:33
haben möchte, muss ich dieses Skript vier weitere Male kopieren, oder?
6:38
Nun, nicht unbedingt – wir können auch eine „for“-Schleife verwenden. Ich kann also stattdessen
6:45
einfach eine bedingte „for“-Anweisung hinzufügen, „for i=1,5 do“ ... und dann wird dieses Skript
6:55
ausgeführt. Ich muss lediglich den Index jedes Steuerungselements ersetzen – statt die Nummer
7:01
dieses ersten zu referenzieren, referenziere ich das „i“-te Steuerungselement. Hier nutze ich unsere
7:08
Iterationsnummer als Variable, die innerhalb unserer Funktion gelten soll.
7:13
Also wird diese Funktion bei der ersten Iteration für Flippy Nr. 1 erstellt, bei der zweiten für Flippy Nr.
7:19
2 usw. Alles was ich tun muss, ist meine „for“-Schleife hier unten zu beenden, und damit ist meine
7:26
Arbeit getan. Jedes meiner Steuerungselemente hat nun dasselbe Verhalten, und das habe ich mit
7:33
zwei Code-Zeilen erreicht anstatt mit dutzenden.
7:36
Wenn man dies auf viel mehr als nur fünf Steuerungselemente erweitert, seht ihr, wie viel Zeit und
7:41
Aufwand das spart. Hier sehen wir auch ein Beispiel dafür, warum unsere Iterationen in einer „for“-
7:47
Schleife nicht immer bei 1 anfangen müssen. Ich könnte diese „for“-Schleife so definieren, dass er
7:53
stattdessen von 2 bis 5 läuft und sich nur auf die Steuerungselemente 2 bis 5 auswirkt, falls ich für 1
8:01
ein anderes Verhalten haben möchte.
8:03
Gut, dann wechseln wir jetzt zum Block Controller und bauen all diese Schleifen auch dort. Ihr findet
8:09
die Schleifen unter „Flow Control“. Zuerst greifen wir uns diesen „repeat“-Block. Das sollte euch
8:16
bekannt vorkommen: Er ist jetzt auf eine bedingte „while“-Anweisung eingestellt, aber ihr könntet
8:22
dies im Aufklappmenü auch auf eine „until“-Bedingung umstellen.
8:27
Genauso wie in Lua richten wir eine Variable ein und setzen sie auf 5, und dann geben wir unserer
8:33
„while“-Schleife die Bedingung, dass x kleiner ist als 10. Wir brauchen also einen logischen Operator,
8:40
den wir auf „weniger als“ setzen. Dann gehen wir in unsere Variablen, holen uns unser x, dann noch
8:49
eine Variable für die zweite Hälfte. Die setzen wir auf 10.
8:53
Für den „do“-Abschnitt unserer Anweisung gehen wir wieder zu den Variablen und setzen x auf etwas
8:59
anderes. Hier muss ein bisschen gerechnet werden, also holen wir uns aus den Operatoren diesen
9:05
Additionsblock. Wieder belegen wir den ersten Slot mit unserer x-Variablen und den zweiten mit
9:13
einem Wert von 1. Jetzt brauchen wir aus dem System-Ordner noch einen „debug print“-Block, damit
9:21
unser neues x ausgegeben wird.
9:24
So – wenn wir diese beiden nebeneinander legen, sehen wir, dass sie genau gleich sind. X ist gleich 5,
9:32
und solange x kleiner als 10 ist, wird 1 zu x hinzuaddiert und das Ergebnis ausgegeben. Tatsächlich
9:41
zeigt ein Blick auf die Lua-Ausgabe des Block Controllers, dass dieser exakt denselben Lua-Code
9:46
generiert, wortgleich mit der „while“-Schleife, den wir selbst geschrieben haben.
9:52
ABER: Eine Sache ist wichtig. Ändern wir diese „while“-Schleife in eine „repeat-until“-Schleife. In Lua
10:00
bedeutet das, wie ihr Euch erinnert, dass wir die Bedingte Anweisung ganz ans Ende stellen. Im Block
10:06
Controller müssen wir einfach nur das „while“ in „until“ ändern.
10:12
Lasst uns noch unsere Bedingten Anweisungen ändern, sodass solange wiederholt wird, bis x größer
10:18
ist als 9, was uns das gleiche Ergebnis wie unser vorheriges Skript liefert. Ich tue das auf beiden
10:25
Seiten. OK, so weit, so gut! Jetzt schaut euch den vom Block Controller erzeugten Lua-Code an.
10:33
Anstatt eine echte „repeat-until“-Schleife zu schreiben, ändert er einfach seine „while“-Schleife mit
10:39
einem „not“-Modifikator. Solange x NICHT größer ist als 9.
10:46
Ja, fürs Erste bewirkt es das gleiche … aber es gibt einen Sonderfall, bei dem dies problematisch sein
10:52
kann. Ich habe bereits erwähnt, dass die „repeat“-Schleife zuerst die Schleife ausführt und erst
10:57
danach anhand der Bedingten Anweisung prüft, ob er fortfahren soll. Was also, wenn die Bedingte
11:03
Anweisung schon erfüllt ist, bevor die Schleife beginnt? Ich ändere das „until“ in größer als 0 …
11:10
… anstelle von größer als 9. Wenn x bei 5 anfängt, ist es schon größer als 0. Eine „repeat“-Schleife in
11:19
Lua wird trotzdem immer erst einmal durchlaufen, bevor er die Bedingungen prüft – im Debug-
11:25
Fenster sehen wir, dass er einen Zyklus durchläuft, bevor er feststellt, dass die Bedingung erfüllt ist
11:31
und dann stoppt.
11:33
Doch der Block Controller ist immer noch eine getarnter „while“-Schleife – er prüft zuerst die
11:38
Bedingung: Und weil 5 schon größer ist als 0, wird die Schleife überhaupt nicht ausgeführt. Diese
11:45
beiden Funktionen scheinen also identisch, liefern aber leicht unterschiedliche Ergebnisse. Dies wird
11:51
für euch wahrscheinlich nie ein Problem sein, doch halte ich es für erwähnenswert.
11:56
So, zum Schluss bauen wir eine „for“-Schleife mit dem Block Controller. Wir ersetzen den „repeat“-
12:02
Block mit dieser „for each item“-Schleife. Der Hauptteil der Schleife bleibt gleich, doch wir brauchen
12:09
ein Array, um zu definieren, wie oft wir diese Aktion ausführen. Mit Arrays haben wir bis jetzt noch
12:16
nicht gespielt, aber ihr könnt Euch ein Array vorstellen wie einen Behälter, in dem mehrere Objekte
12:22
organisiert sind.
12:24
Auf diesem Block steht, dass er diese Aktion für jedes Objekt im Behälter einmal ausführt, also
12:30
müssen wir nur einen Behälter definieren, in dem fünf Dinge Platz finden. Dieser Block erzeugt ein
12:36
Array mit zu definierendem Inhalt, das x-mal wiederholt wird. Es ist egal, welche Objekte sich
12:44
tatsächlich in dem Array befinden, es geht nur um deren Anzahl.
12:49
Ich kann also ein Array mit „irgendwas“ darin erzeugen, einer Zahl, einem String, was auch immer,
12:55
und es so oft wiederholen lassen wie die Schleife laufen soll. Wenn ich das Skript aktualisiere, verhält
13:01
sich unsere Schleife wie erwartet.
13:04
Gut – das war jetzt eine Übersicht zu den Schleifen. Ihr könnt damit noch viel kompliziertere Dinge
13:09
machen – u. a. Schleifen in Schleifen verschachteln, aber in diesem Online-Kurs werden wir das nicht
13:15
weiter vertiefen. Schaut euch das Thema Schleifem in unserem Control Worksheet an. Danach wartet
13:20
das nächste Video auf Euch.