7.3 – Stateless Iterators(Lặp không trạng thái)


Như tên của nó, một trình lặp không trạng thái là một trình lặp không giữ bất kỳ trạng thái nào của chính nó. Do đó, chúng tôi có thể sử dụng cùng một trình lặp không trạng thái trong nhiều vòng lặp, tránh chi phí tạo các bao đóng mới.

Trên mỗi lần lặp, vòng lặp for gọi hàm trình lặp của nó với hai đối số: trạng thái bất biến và biến điều khiển. Một trình lặp không trạng thái tạo ra phần tử tiếp theo cho lần lặp chỉ sử dụng hai đối số này. Một ví dụ điển hình của loại trình lặp này là ipairs, lặp lại trên tất cả các phần tử trong một mảng, như minh họa tiếp theo:

a = {"one", "two", "three"}
    for i, v in ipairs(a) do
      print(i, v)
    end

Trạng thái của vòng lặp là bảng đang được duyệt (trạng thái bất biến, không thay đổi trong vòng lặp), cộng với chỉ số hiện tại (biến điều khiển). Cả hai cặp và trình lặp mà nó trả về đều khá đơn giản; chúng ta có thể viết chúng bằng Lua như sau:

function iter (a, i)
      i = i + 1
      local v = a[i]
      if v then
        return i, v
      end
    end
    
    function ipairs (a)
      return iter, a, 0
    end

Khi Lua gọi các ipairs (a) trong vòng lặp for, nó nhận được ba giá trị: hàm iter làm trình vòng lặp, a là trạng thái bất biến và 0 là giá trị ban đầu cho biến điều khiển. Sau đó, Lua gọi iter (a, 0), kết quả là 1, a [1] (trừ khi a [1] đã là nil). Trong lần lặp thứ hai, nó gọi iter (a, 1), kết quả là 2, a [2], v.v., cho đến phần tử nil đầu tiên.

Hàm cặp, lặp lại trên tất cả các phần tử trong bảng, cũng tương tự, ngoại trừ hàm lặp là hàm tiếp theo, là một hàm nguyên thủy trong Lua:

function pairs (t)
      return next, t, nil
    end

Lệnh gọi next (t, k), với k là một khóa của bảng t, trả về một khóa tiếp theo trong bảng, theo thứ tự tùy ý. (Nó cũng trả về giá trị được liên kết với khóa đó, dưới dạng giá trị trả về thứ hai.) Lệnh gọi next (t, nil) trả về một cặp đầu tiên. Khi không còn cặp nào nữa, tiếp theo trả về nil.

Một số người thích sử dụng tiếp theo trực tiếp mà không cần gọi các cặp:

for k, v in next, t do
      ...
    end

Hãy nhớ rằng danh sách biểu thức của vòng lặp for được điều chỉnh thành ba kết quả, vì vậy Lua nhận được next, t và nil, chính xác những gì nó nhận được khi gọi cặp (t).

Leave a comment