Zoeken…


Generiek voor lus

Iterators gebruiken een vorm van de for lus die bekend staat als de generieke for-lus .

De generieke vorm van de for lus gebruikt drie parameters:

  1. Een iteratorfunctie die wordt aangeroepen wanneer de volgende waarde nodig is. Het ontvangt zowel de invariante status als de besturingsvariabele als parameters. Terugkerende nil signaleert beëindiging.
  2. De invariante staat is een waarde die niet verandert tijdens de iteratie. Het is meestal het onderwerp van de iterator, zoals een tabel, string of gebruikersgegevens.
  3. De besturingsvariabele vertegenwoordigt een beginwaarde voor iteratie.

We kunnen een for lus schrijven om alle sleutel / waarde-paren in een tabel te herhalen met behulp van de volgende functie.

local t = {a=1, b=2, c=3, d=4, e=5}

-- next is the iterator function
-- t is the invariant state
-- nil is the control variable (calling next with a nil gets the first key)
for key, value in next, t, nil do
  -- key is the new value for the control variable
  print(key, value) 
  -- Lua calls: next(t, key)  
end

Standaard Iterators

De standaardbibliotheek van Lua biedt twee iteratorfuncties die kunnen worden gebruikt met een for lus om sleutel / waarde-paren binnen tabellen te doorlopen.

Om een sequentietabel te herhalen, kunnen we de bibliotheekfunctie ipairs gebruiken .

for index, value in ipairs {'a', 'b', 'c', 'd', 'e'} do
  print(index, value)  --> 1 a, 2 b, 3 c, 4 d, 5 e
end

Om iterator over alle sleutels en waarden in een tabel kunnen we de functie uit de bibliotheek te gebruiken paren .

for key, value in pairs {a=1, b=2, c=3, d=4, e=5} do
  print(key, value)  --> e 5, c 3, a 1, b 2, d 4  (order not specified)
end

Staatloze Iterators

Beide paren en ipairs vertegenwoordigen staatloze iterators. Een stateless iterator gebruikt alleen de generieke regelvariabele en invariante status van de lus om de iteratiewaarde te berekenen.

Paren Iterator

We kunnen de stateless pairs iterator implementeren met behulp van de next functie.

-- generator function which initializes the generic for loop
local function pairs(t)
  -- next is the iterator function
  -- t is the invariant state
  -- control variable is nil
  return next, t, nil
end

Ipairs Iterator

We kunnen de ipairs iterator in twee afzonderlijke functies implementeren.

-- function which performs the actual iteration
local function ipairs_iter(t, i)
  local i = i + 1  -- next index in the sequence (i is the control variable)
  local v = t[i]   -- next value (t is the invariant state)
  if v ~= nil then
    return i, v    -- index, value
  end
  return nil       -- no more values (termination)
end

-- generator function which initializes the generic for loop
local function ipairs(t)
  -- ipairs_iter is the iterator function
  -- t is the invariant state (table to be iterated)
  -- 0 is the control variable (first index)
  return ipairs_iter, t, 0
end

Karakter Iterator

We kunnen nieuwe stateless iterators maken door te voldoen aan het contract van de generieke for loop.

-- function which performs the actual iteration
local function chars_iter(s, i)
  if i < #s then
    i = i + 1
    return i, s:sub(i, i)
  end
end

-- generator function which initializes the generic for loop
local function chars(s)
  return chars_iter, s, 0
end

-- used like pairs and ipairs
for i, c in chars 'abcde' do
    print(i, c) --> 1 a, 2 b, 3 c, 4 f, 5 e
end

Priemgetallen Iterator

Dit is nog een eenvoudig voorbeeld van een stateless iterator.

-- prime numbers iterator
local incr = {4, 1, 2, 0, 2}
function primes(s, p, d)
   s, p, d = s or math.huge, p and p + incr[p % 6] or 2, 1
   while p <= s do
      repeat
         d = d + incr[d % 6]
         if d*d > p then return p end
      until p % d == 0
      p, d = p + incr[p % 6], 1
   end
end

-- print all prime numbers <= 100
for p in primes, 100 do  -- passing in the iterator (do not call the iterator here)
   print(p)  -->  2  3  5  7  11 ... 97
end

-- print all primes in endless loop
for p in primes do  -- please note: "in primes", not "in primes()"
   print(p)
end

Stateful Iterators

Stateful iterators bevatten aanvullende informatie over de huidige status van de iterator.

Tabellen gebruiken

De toevoegstatus kan worden verpakt in de generieke status voor de invariante status van de lus .

  local function chars_iter(t, i)
    local i = i + 1
    if i <= t.len then
      return i, t.s:sub(i, i)
    end
  end

  local function chars(s)
    -- the iterators state
    local t = {
      s = s,    -- the subject
      len = #s  -- cached length
    }
    return chars_iter, t, 0
  end

  for i, c in chars 'abcde' do
    print(i, c) --> 1 a, 2 b, 3 c, 4 d, 5 e
  end

Sluitingen gebruiken

Extra status kan binnen een functiesluiting worden gewikkeld. Aangezien de status volledig binnen het bereik van de afsluiting valt, zijn de invariante status en de besturingsvariabele niet nodig.

  local function chars(s)
    local i, len = 0, #s
    return function() -- iterator function
      i = i + 1
      if i <= len then
        return i, s:sub(i, i)
      end
    end
  end

  for i, c in chars 'abcde' do
    print(i, c) --> 1 a, 2 b, 3 c, 4 d, 5 e
  end

Coroutines gebruiken

Extra status kan worden opgenomen in een coroutine, opnieuw zijn de invariante status en de besturingsvariabele niet nodig.

  local function chars(s)
    return coroutine.wrap(function()
      for i = 1, #s do
        coroutine.yield(s:sub(i, i))
      end
    end)
  end

  for c in chars 'abcde' do
    print(c) --> a, b, c, d, e
  end


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow