Alles auf einer Seite
Diese Seite stellt für Lua-Programmierer einige Besonderheiten der Sprache zusammen, die im Scribunto-Tutorial nicht oder nur verborgen dargestellt sind.
Außerdem gibt es eigene Hilfeseiten zu Sonderthemen:
mw und Hilfsbibliothekenmw (für MediaWiki) einige Wiki-spezifische Bibliotheken an, die auch gut mit der sonstigen Architektur eines Wiki-Servers kooperieren.mw.addWarning()Es gibt vier Ursachen für Skriptfehler:
Von sich aus gab Lua dabei bis zum Herbst 2014 immer nur eine einzige Fehlermeldung von sich: „Skriptfehler“. Das war langweilig und half niemandem bei der Beseitigung. Inzwischen wird der Name des Moduls, die Zeilennummer und eine konkrete Situationsanalyse in jeder einbindenden Seite angezeigt. Die Fehlermeldung ist verlinkt mit einer Popup-Box, die die Aufruffolge mit einzelnen Modulnamen und Zeilennummer wiedergibt.
Außerdem wird die Kategorie:Wikipedia:Seite mit Skriptfehlern mit allen einbindenden Seiten gefüllt – das sollte vermieden werden, sondern Laufzeitfehler sollten abgefangen und in Modul-spezifische Wartungskategorien geleitet werden.
Ein Syntaxfehler ist oft ein trivialer Schreibfehler. Dieser müsste eigentlich zur Folge haben, dass das Abspeichern der Modul-Seite unterbunden wird; es sei denn, man hätte bis zum Herbst 2014 dem Feld „⧼scribunto-ignore-errors⧽“ ein Häkchen gegeben. Das ist nicht länger möglich.
Beim Anzeigen der Seitenvorschau des Moduls erhält man eine möglichst qualifizierte Fehlermeldung mitsamt Zeilennummer. Bei schweren Syntaxproblemen kann das jedoch nicht geleistet werden und es kommt der lakonische „Skriptfehler“.
In der „Fehlerbereinigungskonsole“ lassen sich beim Bearbeiten differenziertere Hinweise zur Fehlersuche gewinnen.
Ein typischer qualifizierbarer Fehler wäre ein einzelner Punkt statt zwei zur Verkettung von Zeichenketten (PHP-Stil). Ohne konkrete Hilfestellung bleibt jedoch fehlendes then oder end und auch eine nicht geschlossene Zeichenkette.
Wenn es durch die Programmstruktur in einigen Fällen zu ungeeigneten Datentypen kommt, in manchen nicht, so ist das schwer zu finden. Wird dann etwa versucht, auf ein nil eine Zeichenketten-Funktion anzuwenden, gibt das den bekannten undefinierten Fehler. Für den Einbinder einer Vorlage ist das nicht aufzulösen. Möglichst alle Pfade sind deshalb auf Testseiten durchzuspielen, und die Voraussetzungen hinsichtlich Datentyp und Wertebereich sind in den Funktionen zu überprüfen.
Wenn eine Seite transcludiert wird, kann es sein, dass dieser Seitenname nicht existiert; insbesondere die erwartete Seite verschoben wurde oder beim Komponieren eines zusammengesetzten Namens ein Fehler auftrat. Um diese Situation auflösen zu können, wird eine präzise Information benötigt, welche Seite fehlt. LuaWiki.transclude() ermöglicht eine sichere Einbindung und sorgt für eine präzise Fehlermeldung.
Was immer die Vorlagenprogrammierer und Einbinder von Vorlagen an Parametern eingeben, muss analysiert und bei Problemen mit einer konkreten Nachricht versehen werden, damit eine Berichtigung möglich wird.
Defensives Programmieren ist ratsam.
#invoke wenigstens immer vom Typ string.fun mit Parameterliste args.e, v = pcall( fun, args )e im Fehlerfall false und v die Fehlermeldung.e den Wert true und v nebst allen folgenden Variablen sind die üblichen Rückgabewerte von fun.pcall steht für protected call.args ist eine Komma-getrennte Aufzählung von null bis beliebig vielen Parameterwerten.assert( v, message, ... )error(), jedoch nur, wenn die Bedingung v nicht erfüllt ist (also nil oder false ist).message sollte eine spezifische Fehlermeldung mitgegeben werden; es wäre sonst ein lapidares assertion failed! – zumindest wird aber immer die Zeilennummer des assert in der Meldung gezeigt, nebst dem Namen des Moduls.nil noch false ist, werden alle Argumente einschließlich v und message zurückgegeben.pcall() geschützten Umgebung sinnvoll; ansonsten wird bloß ein allgemeiner „Skriptfehler“ ohne nähere Einzelheiten ausgelöst.pcall() gesprungen; etwa die Schnittstelle zum #invoke. Damit erspart man sich das Durchreichen von besonderen Rückgabewerten von Funktion zu Funktion.error( message, level )pcall() geschützten Umgebung sinnvoll; ansonsten wird bloß ein allgemeiner „Skriptfehler“ ohne nähere Einzelheiten ausgelöst.pcall() ausgehenden Funktionsfolge wird die Fehlermeldung message zurückgegeben.level ist in der Original-Sprache Lua eine Aufruf-Folge oder stack, dessen anzuzeigende Tiefe vorgegeben werden kann.
allowEnvFuncs nicht zugelassen wird.level nicht angegeben oder ist Null oder zu groß, so wird keine Information zum Ort gezeigt.level immer mit 1 oder gar nicht anzugeben.assert().Anders als bei anderen Programmiersprachen gilt:
0 wie auch die leere Zeichenkette "" sind „etwas“.nil und false sind „nichts“.{} ist gleichbedeutend mit nil.Das ist vor allem für if-Abfragen wichtig.
Auf Werte und Funktionen als Komponenten einer table wird mit einem . als t.k zugegriffen, neben der Notation t["k+"] auch für Namen von Komponenten, die nicht rein alphanumerisch sind.
Die Elemente einer Tabelle können mit verschiedenen Iteratoren erfasst werden. Typisch sind folgende Universaliteratoren:
local Beispieltabelle = {"eins", "zwei", 3, "Quattro stagioni"}
for meinIndex, meinWert in ipairs(Beispieltabelle) do
...
end
iteriert durch die unbenannten Elemente einer Tabelle, während
local Beispieltabelle = {erster="eins", zweiter="zwei", dritter=3, vierter="Quattro stagioni"}
for meinSchlüssel, meinWert in pairs(Beispieltabelle) do
...
end
durch die benannten Werte der Tabelle iteriert.
Bei einem Objekt (einer Instanz, durch eine von Lua oder Scribunto angeboten Bibliothek) wird auf Eigenschaften ebenfalls mit einem . zugegriffen. Für Funktionen (Methoden) ist hingegen ein : zu verwenden. Beispiele siehe String-Funktionen.
Die Notation mit Doppelpunkt gilt nicht nur für Lua- und Scribunto-Objekte, sondern auch für benutzerdefinierte Objekte. Dabei erhält die Methode implizit einen zusätzlichen Parameter self, auf den innerhalb der Methode zugegrffen werden kann. Dieser repräsentiert die Instanz des Objekt-table, während die table einer „Klasse“ entspräche. Die beiden Anweisungen
function meinObjekt:f ( params ) body end
und
meinObjekt.f = function ( self, params ) body end
sind äquivalent.
Bei Funktionen in Objekten (Methoden) gibt es außerdem die Möglichkeit, benannte Argumente zu verwenden. Statt runder Klammern sind dann geschweifte Klammern {} zu benutzen. Dieses Format ist meist eine zusätzliche Option; in manchen Fällen wie bei frame:expandTemplate{} aber der einzige unterstützte Zugriff.
Die Vorlagenprogrammierung wird dadurch unterstützt, dass der or-Operator den links stehenden Disjunktionsausdruck zurückgibt, wenn dieser weder nil noch false ist, und sonst den Ausdruck auf der rechten Seite.
Damit lassen sich auch Datentypen bei fehlenden Angaben sichern:
saveString = frame.args.optional or ""
saveTable = getTable() or {}
Wenn der Wert leer und/oder dabei vom falschen Datentyp ist, wird mit dem richtigen Datentyp initialisiert.
Weil oft Bibliotheksfunktionen in bestimmten Situationen nil oder false zurückgeben, diese Zeichenketten aber nicht als Ergebnis der Vorlageneinbindung auftreten sollen, kann man etwa einen wirklich „leeren“ Wert mit der folgenden Anweisung sicherstellen:
return fun(x) or ""
Gibt fun(x) einen echten Wert zurück, wird dieser an das #invoke zurückgegeben; ist das nichts, greift das "".
Analog kann man den Wert 1 bei „nichts“ oder „etwas“ sicherstellen:
return fun(x) and "1" or ""
Weil diese Notation nicht sehr übersichtlich ist, sollte man es aber bei diesem Kniff bewenden lassen.
Die Reihenfolge lokaler Funktionen ist signifikant. Eine lokale Funktion muss in der physischen Abfolge der Definitionen definiert gewesen sein, bevor sie verwendet werden darf.
Bei einer Zählschleife
for v = e1, e2 do
werden die Argumente nur einmal zu Beginn ausgewertet; danach in interne Variablen überführt.
Es ist nicht möglich, innerhalb der Schleife die Endbedingung auszulösen, etwa durch e1=e2. Vielmehr ist eine break-Anweisung auszuführen.
Unbenannte Zeichenketten-Parameter sollten stets getrimmt werden, wenn sie aus Vorlagen stammen und Leerzeichen nicht signifikant wären. In der Vorlagenprogrammierung war dies nur mit Tricks möglich gewesen:
{{#if:trim|{{{1}}}}}In Lua wäre der Weg eine Bibliotheksfunktion, wenn gesichert ist, dass s eine Zeichenkette ist:
s = mw.text.trim( s )
Insbesondere während der Entwicklungsphase kann mit dem folgenden Statement möglichst früh in den ausführbaren Zeilen eine verschärfte Syntaxkontrolle angefordert werden.
require( "strict" )
Zurzeit bewirkt dies lediglich, dass gesichert wird, dass alle Variablenbezeichner auch explizit als local deklariert sein müssen.
local vereinbart sein (ausgenommen automatische lokale Variablen in Schleifen).Weil dies im produktiven Stadium Performance und Ressourcen kostet, sollte es in fertigen Versionen nicht mehr aktiv vorhanden sein.
Es wäre vermessen, Lua als objektorientierte Sprache anzusehen. Gleichwohl lassen sich über eine metatable einer table einige objektartige Eigenschaften geben.
Damit lassen sich spezifische Methoden definieren für:
Weil die table ohnehin Funktionen als Elemente enthalten kann, lassen sich nach Art eines selbstdefinierbaren Objekts Methoden und Eigenschaften darstellen und über eine Generierungsfunktion auch allen Instanzen einer „Klasse“ zuweisen; diese sogar geeignet vererben und überschreiben. Das traut man der schlichten Sprache auf den ersten Blick nicht zu.
Mittels der Funktion mw.addWarning( wikitext ) können im Kopfbereich der Seitenvorschau Warnungen angezeigt werden.
wikitext wird dabei noch geparset.error-54381975 generieren, der im Seitenkopf verlinkt und an der Einbindung verankert wird.Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.