Frage Was ist der Unterschied zwischen diesen beiden Lua Beispielen? Ist einer besser?


Ich fange gerade erst mit Lua an. In dem Beispiel, von dem ich lerne (die Ghosts & Monsters Corona Open Source), Ich sehe dieses Muster wiederholt.

local director = require("director")

local mainGroup = display.newGroup()

local function main()

   mainGroup:insert(director.directorView)

   openfeint = require ("openfeint")
   openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )

   director:changeScene( "loadmainmenu" )

   return true
end

main()

Ist das eine Art Konvention, die erfahrene Lua-Programmierer empfehlen, oder gibt es echte Vorteile dafür? Warum würdest du die Funktion nicht einfach alle überspringen und dies tun:

local director = require("director")

local mainGroup = display.newGroup()

mainGroup:insert(director.directorView)

local openfeint = require ("openfeint")
openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )

director:changeScene( "loadmainmenu" )

Hat der erste Stil im Laufe der Sekunde einen impliziten Vorteil? Vielen Dank!


5
2017-12-11 22:38


Ursprung


Antworten:


Ist das eine Art Konvention, die erfahrene Lua-Programmierer empfehlen, oder gibt es echte Vorteile dafür?

Es ist nicht typisch. Der Vorteil ist, dass der Objektstatus privat ist, aber das ist nicht genug, um ihn zu empfehlen.

Ich sehe dieses Muster wiederholt.

Ich habe es noch nie zuvor gesehen und es passiert nur einmal in der Quelle, die du gepostet hast.

Bearbeiten: Hinzufügen einer Antwort auf eine Frage in den Kommentaren unter diesem Beitrag gestellt.

Eine Funktion, die auf externe lokale Variablen zugreift bindet zu diesen Variablen und wird eine "Schließung" genannt. Lua (aus historischen Gründen) bezieht sich auf diese gebundenen Variablen als "upvalues". Beispielsweise:

local function counter()
   local i = 1
   return function()
      print(i)
      i = i + 1
   end
end

local a, b = counter(), counter()
a() a() a() b() --> 1 2 3 1

a und b sind an verschiedene Kopien gebundene Verschlüsse i, wie Sie von der Ausgabe sehen können. Mit anderen Worten, Sie können sich eine Schließung als Funktion mit ihrem eigenen privaten Zustand vorstellen. Sie können damit Objekte simulieren:

function Point(x,y)
   local p = {}
   function p.getX() -- syntax sugar for p.getX = function()
      return x
   end
   function p.setX(x_)
      x = x_
   end
   -- for brevity, not implementing a setter/getter for y
   return p
end

p1 = Point(10,20)
p1.setX(50)
print(p1.getX())

Point gibt eine Tabelle mit Schließungen zurück, die jeweils an die Einheimischen gebunden sind x und y. Die Tabelle enthält nicht den Status des Punktes, die Schließungen selbst, über ihre Upvalues. Ein wichtiger Punkt ist, dass jedes Mal Point heißt es erstellt Neu Verschlüsse, was nicht sehr effizient ist, wenn Sie große Mengen an Objekten haben.

Eine andere Möglichkeit zum Erstellen von Klassen in Lua ist das Erstellen von Funktionen, die eine Tabelle als erstes Argument annehmen, wobei der Zustand in der Tabelle gespeichert wird:

function Point(x,y)
   local p = {x=x,y=y}
   function p:getX() -- syntax sugar for p.getX = function(self)
      return self.x
   end
   function p:setX(x)
      self.x = x
   end
   return p
end

p1 = Point(10,20)
p1:setX(50) -- syntax sugar for p1.setX(p1, 50)
print(p1:getX()) -- syntax sugar for p1.getX(p1)

Bis jetzt erstellen wir immer noch neue Kopien jeder Methode, aber jetzt, da wir uns nicht auf die upvalues ​​for state verlassen, können wir das beheben:

PointClass = {}
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
   return {
      x = x,
      y = y,
      getX = PointClass.getX,
      setX = PointClass.getY,
   }
end

Jetzt werden die Methoden einmal und alle erstellt Point Instanzen teilen die gleichen Schließungen. Ein noch besserer Weg, dies zu tun, ist die Metaprogrammierung von Lua, um neue zu schaffen Point Instanzen schauen automatisch rein PointClass für Methoden, die nicht in der Instanz selbst gefunden werden:

PointClass = {}
PointClass.__index = PointClass -- metamethod
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
   return setmetatable({x=x,y=y}, PointClass)
end

p1 = Point(10,20)
-- the p1 table does not itself contain a setX member, but p1 has a metatable, so 
-- when an indexing operation fails, Lua will look in the metatable for an __index
-- metamethod. If that metamethod is a table, Lua will look for getX in that table,
-- resolving p1.setX to PointClass.setX.
p1:setX(50)

Dies ist eine idiomatische Art, Klassen in Lua zu erstellen. Es ist speicherfreundlicher und flexibler (insbesondere lässt es Vererbung einfach implementieren).


8
2017-12-12 05:26



Ich schreibe häufig meine eigenen Lua-Skripte auf diese Weise, weil es in diesem Fall die Lesbarkeit verbessert:

function main()
    helper1( helper2( arg[1] ) )
    helper3()
end

function helper1( foo )
    print( foo )
end

function helper2( bar )
    return bar*bar
end

function helper3()
    print( 'hello world!' )
end

main()

Auf diese Weise ist der Hauptcode ganz oben, aber ich kann immer noch die notwendigen globalen Funktionen definieren, bevor er ausgeführt wird.

Ein einfacher Trick, wirklich. Ich kann mir keinen Grund vorstellen, dies neben der Lesbarkeit zu tun.


3
2017-12-17 05:17



Der erste Stil könnte zu einer besseren Lesbarkeit verwendet werden, aber ich würde der Funktion lieber einen aussagekräftigen Namen geben Main oder einfach ohne die Funktion gehen.

Übrigens, ich denke, es ist immer eine gute Übung, Blöcke von Code zu benennen, d. H. Sie in Funktionen oder Methoden zu setzen. Es hilft Ihnen, Ihre Absicht mit diesem Code zu erklären, und fördert die Wiederverwendung.


1
2017-12-26 15:40



Ich sehe nicht viel auf den ersten Stil, wie Sie es gezeigt haben. Aber wenn es so etwas sagte if arg then main() end Im unteren Bereich könnte das Skript (zusätzlich zu einem eigenständigen Skript) als ladbare "Bibliothek" nützlich sein. Das heißt, mit a main() so schmeckt C, nicht Lua; Ich denke, du hast Recht, es in Frage zu stellen.


0
2017-12-12 04:42