2017-06-01 4 views
1

Ich möchte eine Tabelle erstellen, die die Funktionen einer anderen Tabelle enthält, wie folgt aus:Wie kann ich eine Karte von Methoden in Lua erstellen?

party_animal = {} 

function party_animal:dance() 
    -- dance 
end 

function party_animal:dance_furiously() 
    -- extreme dance 
end 

method_map = { 
    'idea_one': party_animal:dance, 
    'idea_two': party_animal:dance_furiously, 
} 

Dann wird dieser mit ich eine der Funktionen wie folgt aufrufen können: method_map[1][2](). Ich kann das funktionieren, wenn ich den . Operator anstelle von : benutze, aber ich möchte auf self zugreifen.

Der Fehler, den ich bekommen, ist dies:

stdin:2: '}' expected (to close '{' at line 1) near ':' 
+0

method_map [1] [2] nennen. method_map [1] ist also nil, daher können Sie method_map [2] nicht indexieren. Selbst wenn method_map [1] eine Tabelle wäre, wäre method_map [1] [2] gleich Null und Sie können auch keine nil-Werte aufrufen. – Piglet

+0

Das liegt daran, dass ich die falsche Syntax für die Tabelle verwende? – Matt

+1

@MattDeacalionStevens Nein, dies liegt daran, dass Sie beim Erstellen einer Tabelle Zeichenfolgenschlüssel verwenden und versuchen, mit nummerierten Schlüsseln auf Werte zuzugreifen. 'table [1]' versucht auf Schlüssel zuzugreifen, die definiert sind mit: 'table [1] = foo' oder' table = {foo} '. Kurz gesagt, wenn Sie Schlüssel in '{}' weglassen, werden alle Werte mit Zahlen beginnend von * 1 * indiziert. 'table = {" a "," b "," c "}' führt zu 'table [1] ==" a "'. – Green

Antwort

4

aus dem Handbuch Lua Referenz: https://www.lua.org/manual/5.3/manual.html#3.4.9

Tabelle Bauer sind Ausdrücke, die Tabellen zu erstellen. Jedes Mal, wenn ein -Konstruktor ausgewertet wird, wird eine neue Tabelle erstellt. Ein Konstruktor kann verwendet werden, um eine leere Tabelle zu erstellen oder eine Tabelle zu erstellen und einige seiner Felder zu initialisieren. Die allgemeine Syntax für Konstruktoren ist

tableconstructor ::= ‘{’ [fieldlist] ‘}’ 
fieldlist ::= field {fieldsep field} [fieldsep] 
field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp 
fieldsep ::= ‘,’ | ‘;’ 

Jedes Feld der Form [exp1] = exp2 in die neue Tabelle fügt einen Eintrag mit Schlüssel und Wert exp1 exp2. Ein Feld des Formularnamens = exp ist entspricht ["name"] = exp. Schließlich sind Felder der Form exp äquivalent zu [i] = exp, wobei i aufeinanderfolgende Ganzzahlen sind, die mit 1 beginnen. Felder in den anderen Formaten haben keinen Einfluss auf diese Zählung.

Wie Sie sehen etwas wie

method_map = {'idea_one' : party_animal:dance} 

nicht möglich ist, weil es nicht gültige Syntax für Tabellen Konstrukteure.

Ersetzen: mit = und entfernen Sie das '', um es zu einem gültigen Ausdruck zu machen.

method_map = {idea_one = party_animal: Tanz} wird die Fehlermeldung

stdin vermeiden: 2: '}' erwartet (schließen '{' in Zeile 1) in der Nähe von ':'

Aber Sie werden eine andere Fehlermeldung über fehlende Funktionsargumente sehen.

Das liegt daran, dass der Doppelpunkt-Operator nur für Funktionsaufrufe und Definitionen gültig ist. Nicht für die Indizierung von Tabellenelementen, die Sie eigentlich machen möchten.

method_map = {idea_one = party_animal.dance} wird keine Fehler verursachen.

Natürlich können Sie nicht auf party_animal durch Selbst dann zugreifen.

Wie können wir das erreichen? Der Aufruf von method_map:dance() wird sich auf methodmap beziehen.

Aber wenn wir

method_map = {idea_one = function() return party_animal.dance(party_animal) end}

oder die äquivalent

method_map = {idea_one = function() return party_animal:dance() end}

mit dem syntaktischen Zucker mit dem Doppelpunkt-Operator schreiben, wir endlich das bekommen, was wir wollen.

Nun beziehen sich auf party_animal wenn wir method_map:dance()

+1

Das letzte Beispiel kann geändert werden in 'method_map = {idea_one = function() return party_animal: dance() end}'. – nobody

+0

@nobody oh ja natürlich. Ich fügte die optionale syntaktische Zuckerversion hinzu – Piglet

4
party_animal = {} 

function party_animal:dance() 
    -- dance 
end 

function party_animal:dance_furiously() 
    -- extreme dance 
end 

method_map = { 
    idea_one = party_animal.dance, 
    idea_two = party_animal.dance_furiously, 
} 

Dies wird wie vorgesehen. Warum?

Als erstes beachten Sie bitte, dass Ihr Tabellenkörper geändert wurde, um der Lua-Syntax zu entsprechen. Der Fehler, den Sie bekommen haben, wird durch eine unpassende Tabellendefinition verursacht, auf die Piglet sehr detailliert hingewiesen hat.

Zweitens Diese Definition der Funktion

function table:foo() end 

ist die gleiche wie diese

function table.foo(self) end 

Passing Funktionsreferenz nicht seine Parameter ändern. Der erste Parameter ist weiterhin self und wenn Sie diese Funktion mit : aufrufen, wird method_map als self übergeben.

Falls Sie von method_mapparty_animal als self in Funktionen haben Sie zusätzliche Funktionen nutzen müssen:

method_map = { 
    idea_one = function (...) return party_animal.dance(party_animal, ...) end, 
    idea_two = function (...) return party_animal.dance_furiously(party_animal, ...) end, 
} 

Lua 5.3 Reference Manual on function defining and calling.

+0

Ich denke, er will auf party_animal durch self zugreifen. In Ihrem Beispiel würde sich self auf method_map beziehen. Auch die Verwendung der Tabelle als Tabellenname ist nicht sehr nett, da sie bereits verwendet wird, um eine Standard-Tabellenmanipulationsbibliothek von Luas bereitzustellen. – Piglet

+0

@Piglet Ich verstehe es anders: Er macht sich Sorgen, dass das Passieren der Funktion ohne ':' den Zugriff auf 'self' unmöglich macht. Ich denke, wir sollten auf ihn warten. – Green

+0

Danke, diese gründlichen Erklärungen waren brilliant! Und es war ein bisschen von beidem, ich wollte einen Tabellenwert als Callback übergeben, aber ich wollte, dass die Funktion Zugriff auf 'self' hat ... Ich habe verstanden, dass der ':' - Operator das getan hat, aber ich konnte es nicht bekommen arbeiten. Das Ende von @ Piglets Antwort war genau richtig! – Matt

Verwandte Themen