Lua/Syntax

Aus wiki.archlinux.de

Dieser Wiki-Artikel gibt einen kurzen Überblick über die Lua-Syntax.

Natürlich kann hier kein vollständiges und komplett umfassendes Lua-Tutorial erfolgen. Es können lediglich einige Aspekte beleuchtet werden, die eventuell für die Konfiguration von Programmen interessant sind die Lua als Konfigurationssprache einsetzen, sowie ein grundlegender Überblick geschaffen werden.

Es es sei für tiefer gehende Beschäftigung mit der Programmierung in Lua auf das sehr gute Reference Manual verwiesen (siehe Weblinks).

Übersicht

Sofern nicht explizit anders angegeben, gehen die folgenden Beispiele davon aus, dass die Script-Dateien per Befehlszeile an die aktuelle Lua-Version übergeben werden (siehe hier).

Schlüsselwörter

Es gibt in Lua 5.4, der aktuellen Version zum Zeitpunkt der Erstellung des Artikels, nur 22 vordefinierte Schlüsselwörter (zur Einordnung: Python hat 35, PHP 58, und C++ zum Beispiel hat 60 Schlüsselwörter).

and       break     do        else      elseif    end
false     for       function  goto      if        in
local     nil       not       or        repeat    return
then      true      until     while

Die Schlüsselwörter sind schreibungsabhängig. Das reservierte Schlüsselwort or und ein anderweitig frei vergebenes oder genutztes OR zum Beispiel sind zwei verschiedene Dinge. Es wird dazu geraten, Keine Namen (Variablen, Funktionen, etc.) zu verwenden, die mit einem Unterstrich beginnen, und nur aus Großbuchstaben bestehen (_FOOBAR).

Lua verwendet bis auf den Doppelpunkt praktisch keine Zeichen zur Steuerung des Programmablaufs, jegliche Abläufe werden durch verschiedene Schlüsselwörter definiert.

Kommentare

Kommentare werden mittels -- eingeleitet, und gelten bis zum Ende der Zeile. Mehrzeilige Kommentare können mittels --[[ ... ]]-- umfasst werden.

-- Ich bin ein Kommentar!

… bzw …

--[[
Ich bin ein …

… mehrzeiliger …

… Kommentar!
]]--

Typen

Bei Lua handelt es sich um eine dynamisch typisierte Sprache, das Bedeutet, dass der Typ einer Variable über dessen Wert bestimmt wird, und nicht vordefiniert werden kann, welchen Wert eine Variable annehmen soll. Insgesamt besitzt Lua lediglich 8 Datentypen. …

  • string -> Zeichenketten mit bis zu 264-1 Zeichen
  • number -> Positive und Negative Integer, Fließkommazahlen, und Dezimalzahlen mit 64 Bit Länge
  • table -> Der einzige Datenstrukturiermechanismus in Lua, siehe Abschnitt Tables
  • function -> In sich geschlossener Chunk mit Code, der „als ganzes“ ausgeführt werden kann
  • nil -> Zur Unterscheidung von allen anderen Datentypen (kein Wert, aber nicht leer)
  • boolean -> Die Wahrheitswerte true und false
  • userdata -> Ein Block beliebiger roher C-Speicherdaten, der nicht durch Lua verändert werden kann
  • thread -> Repräsentationen von Co-Routinen (kollaboratives Multithreading), nicht Betriebssystemthreads

Bei Vergleichen ergeben sowohl nil als auch false ein boolsches unwahr, allerdings sind nil und false untereinander nicht identisch.

Variablen

Alle Datentypen in Lua können in Variablen gespeichert werden, durch Funktionen zurückgegeben werden, in Tables strukturiert werden, oder sonstwie innerhalb eines Sripts benutzt werden. Variablen können mittels .. verkettet werden.

Variablen sind standardmäßig global. Mittels des Keywords local kann man sie auf den Chunk beschränken, in dem sie definiert sind.

bar = 'globale Variable'       -- Global definiert
local foo = 'lokale Variable'  -- Lokal definiert

-- In diesem Beispiel hier macht es keinen Unterschied: Beide Variablen werden ausgegeben.
print(foo..'\n'..bar)
lokale Variable
globale Variable

Variablen können nach der initialen Definition jederzeit mittels variablenname = 'neuer Wert' mit neuen Werten belegt werden, ihren Scope (lokal oder global) behalten sie dabei bei. Der Typ der Variable ändert sich je nach dem, was der Variablen als Wert zugewiesen wurde. mittels type() kann man sich den Typen einer Variable ausgeben lassen.

local foobar = 6     -- Die Variable wird lokal mit einer Zahl definiert
print(type(foobar))  -- Der Typ wird ausgegeben
foobar = 'Hallo'     -- Der Variablen wird ein String als neuer Wert zugewiesen
print(type(foobar))  -- Es wird erneut der Typ ausgegeben
number
string

Es wird empfohlen, wenn möglich lokale Variablen zu benutzen. In einem Chunk definierte Variablen sind in Chunks die innerhalb dieses Chunks erstellt werden ebenfalls verfügbar.

Funktionen

Eine Funktion ist ein einer Variablen zugewiesener Chunk, der über den Variablennamen aufrufbar ist. In neueren Versionen von Lua gibt es „syntaktischen Zucker“, der die Funktionsdefinition hinter dem Schlüsselwort function versteckt.

function sag_was (text)
    print(text)
end

local sag_was_anderes = function (text)
    print(text)
end

sag_was('Hallo')
sag_was_anderes('Tschüß')
Hallo
Tschüß

Die beiden Definitionen sind technisch identisch. Beide definieren eine aufrufbare Funktion.

Tables

Tables erlauben das Strukturieren beliebiger Daten, inklusive anderer Tables.

Einträge in Tables können dabei mit beliebigen Werten indiziert werden. Werte in Tables werden durch Komma getrennt. Es kann gezielt auf Einträge zugegriffen werden, und über Tables iteriert werden. Wenn kein expliziter Index angegeben wird, werden Einträge in Tables von 1 beginnend durchnummeriert. Alle Methoden der Indizierung von Einträgen können innerhalb eines Tables gemischt werden.

Tables werden mittels {} definiert. Wenn man sie per print() ausgibt, wird die Referenz des Tables innerhalb der Ausführung des Scripts angegeben.

local foobar = { 'a', 'b'}  -- Erstelle einen Table mit zwei Werten
print(foobar)               -- Gebe die referenz des Tables aus
table: 0x560e2fd87fd0

Will man sich die Werte des Tables ausgeben, so kann man auf das Modul inspect zurückgreifen. Das Modul befindet sich als lua-inspectAUR auch im AUR.

Tables erlauben eine Vielzahl an verschiedenen Index-Varianten.

local foobar = {
  'direkte Hinzufügung Nummer 1',      -- Hinzufügen ohne genannten Index
  foo = 'Benannt',                     -- Eine explizit beannte ID als Index
  [42] = 'Explizite ID',               -- Es können beliebige Index-Nummern gesetzt werden ...
  [10] = 'Andere explizite ID',        -- ... die auch nicht aufeinanderfolgend sein müssen
  ['langer Index'] = 'das geht auch',  -- Eine Index-ID mit Leerzeichen
  'direkte Hinzufügung Nummer 2',      -- Automatische indizierung
  [name] = 'Index per Variable'        -- Der Index ist der Inhalt der Variable `name`
}

Der Zugriff erfolgt mittels Angabe des gewünschten Index.

print(foobar.foo) -- Syntaktischer Zucker für foobar['foo']
print(foobar[1])
print(foobar['langer Index'])
Benannt
direkte Hinzufügung Nummer 1
das geht auch

Will man die Werte in einem Table zählen, so geht dies mittels #variablenname, allerdings zählt dies nur die direkt hinzugefügten Werte. Will man alle Werte erfassen, so muss man über den Table iterieren, siehe das Beispiel zu for im Abschnitt Ablaufsteuerung.

Ablaufsteuerung

Lua verfügt über vier Strukturen zur Ablaufsteuerung: if then elseif else, repeat until, while, und for in zwei Varianten. Zudem gibt es noch die logischen Operatoren and, or, und not.

Folgende relationale Operatoren gibt es:

  • == -> ist gleich
  • ~= -> ist ungleich
  • < / > -> ist kleiner/größer als
  • <= / >= -> kleiner/größer oder gleich

Hieraus lassen sich diverse Steuerungen realisieren.

--Prüfe ob foobar ein Table ist und setze dies als Wert
local test = type(foobar) == 'table'

-- Wenn test ein boolsches wahr ist, gebe setze ersten wert,
-- ansonsten setze den zweiten Wert
local result = test and 'ist ein Table' or 'ist kein Table'

-- Gebe das Ergebnis aus
print(result)
ist ein Table

Im Beispiel ist foobar also eine Tabelle. Eine andere Variante wäre eine if-Abfrage.

if type(foobar) == 'table' then
  print('ist ein Table')
else
  print('ist kein Table')
end

Dies ist im Ergebnis das gleiche.

Mittels for man zum Beispiel über einen Table iterieren Das folgende Beispiel Iteriert über den zuvor erstellten Table fobar, und gibt dabei die IDs der Werte, sowie die dazugehören werte aus. Zusätzlich wird ein Counter definiert und hochgezählt.

local counter = 0

for id,value in pairs(foobar) do
  print(id..' = '..value)
  counter = counter + 1
end

print('\nDer Table foobar beinhaltet '..counter..' Werte.')
1 = direkte Hinzufügung Nummer 1
2 = direkte Hinzufügung Nummer 2
42 = Andere explizite ID
langer Index = das geht auch
per Variable = Index per Variable
5 = Explizite ID
foo = Benannt

Der Table foobar beinhaltet 7 Werte.

Will man nur den Counter hochzählen, geht dies auch in einer kürzeren Variante

local counter = 0
for _ in pairs(foobar) do counter = counter + 1 end
print(counter)
7

Es hat sich etabliert, in Loops einen Unterstrich zu setzen, wenn man an dem Wert nicht interessiert ist.

Mittels repeat until kann man eine Schleife durchlaufen, die mindestens einmal, und dann so lange ausgeführt wird bis das gewünschte Ergebnis erreicht ist. Die Ergebnisprüfung hat Zugriff auf die in der Schleife gesetzten Variablen.

local foo = 0              -- Setze die Zählvariable auf 0
repeat                     -- Schleifenbeginn
  foo = foo + 1            -- Erhöhe die Zählvariable um 1
  local fertig = foo == 5  -- Setze den Wert auf das Ergebnis der Abfrage
  print(foo)               -- Gebe die Zählvariable aus
until fertig               -- Ende der Schleife, wenn `fertig` boolsch wahr ist
1
2
3
4
5

Weblinks