Är det bara jag som tycker det är lite ironiskt att “Lua” står ovanpå en sol? “Lua” betyder “måne” på portugisiska. 😀

Lua-sheriffen

Förra veckan tittade vi på Tables, idag ska vi gå vidare och titta på funktioner!

Vi börjar direkt med att ta ett exempel på en väldigt enkel funktion, fakultet (som vi tittat på tidigare, även denna gång är den rekursiv):

function fakultet(n)
 if n < 2 then
  return 1
 else
  return n * fakultet(n - 1)
 end
end

Kort sagt, om det inskickade talet är mindre än 2 (det vill säga, 1 eller 0), skicka tillbaka 1, annars multipliceras det nuvarande talet med ett nytt fakultet-anrop som tar talet under det nuvarande.

Notera att det finns två “end” i koden, en för if-satsen och en för funktionen. Som synes behöver man i Lua inte ange returtyp, och det går också bra att skriva flera returvärden (uppdelade med kommatecken):

function test()
 return 1, 2
end

a, b = test()

print (a .. " " .. b)

Om man skriver “a = test()” istället kommer det andra värdet som returnerats att förkastas.

Den uppmärksamme, som har varit med ett tag, märker nog att detta påminner ganska mycket om Python.

Funktioner som data

Funktioner i Lua betraktas, som så mycket annat, som vilken data som helst. Man kan exempelvis skicka funktionsnamn som argument i funktioner och därefter exekvera dem med några godtyckliga argument, som här:

-- Multiplicera tal x och y
function multi (x , y)
  return x * y
end

-- Utför operation 'func (x, y)'
function operation (func, x, y)
  return func (x, y)
end

-- körexempel
operation (multi, 2, 3)

Precis som med variabler kan man också sätta ‘x = y’ så följande är helt okej:

-- att skapa flera referenser till samma funktion är enkelt
better_multi = multi

-- detta körexempel anropar samma kod som anropet ovan men funktionsnamnet är nytt
operation (better_multi, 2, 3)

Noterar ni något som är dumt med detta?
Den här versionen av ‘operation’ är inte så praktisk eftersom den bara kan ta två argument utöver den funktion som ska köras. Tänk om vi har en funktion som har ett, eller tre argument?
Istället för att göra separata versioner av varje funktion för olika antal argument kan vi istället skriva så här:

-- Exekvera func med alla efterföljande invariabler som indata
function operation(func, ...)
  return func (...)
end

Detta tillåter oss att ange ett godtyckligt antal argument, och när vi sedan anropar func skickas alla efterföljande argument med i det anropet. Praktiskt va!? 😀
Så när kan man ha nytta för detta? Kanske aldrig! 😉
Värt att veta med ‘…’ är att det går också att plocka ut enstaka argument. Detta görs med funktionen select(x, …) där man får alla argument från x och framåt.
Om man tilldelar returvärdet till en variabel sparas däremot endast värdet i x:

function getX (x, ...)
  return select(x, ...)
end

-- Detta anrop returnerar '2, 3, 4, 5' då det första argumentet anger returvariabel och alla efterföljande returneras
-- OBS! Det första talet ingår inte i sekvensen '...', Position 1 är alltså '2', position 2 är '3' och så vidare.
getX(1, 2, 3, 4, 5)

-- Här blir a = 3 och övriga värden förkastas
a = getX(2, 2, 3, 4, 5)

Varför fungerar det på detta sätt? Bra fråga!

Så vad har vi lärt oss idag?

  • Vad Lua betyder på portugisiska
  • Hur man skapar en funktion i Lua
  • Hur man anger flera returvärden och använder dessa efter anropet
  • Att funktioner kan behandlas som vilken data som helst
  • Hur man kan tillåta ett godtyckligt antal variabler som invärden i en funktion och hur man kan hämta ut dessa vid behov

Det var allt för idag, nästa gång ska vi titta på hur man kan skapa objekt i Lua! Ses då! 🙂