Я изучаю Lua по книге Программирование на Lua, первое издание. У меня проблемы с пониманием метатаблиц.
Это код и пояснения, которые появляются на странице 108:
Set = {} function Set.new (t) local set = {} for _, l in ipairs(t) do set[l] = true end return set end function Set.union (a,b) local res = Set.new{} for k in pairs(a) do res[k] = true end for k in pairs(b) do res[k] = true end return res end function Set.intersection (a,b) local res = Set.new{} for k in pairs(a) do res[k] = b[k] end return res end
Чтобы помочь проверить наши примеры, мы также определяем функцию для печати наборов:
function Set.tostring (set) local s = "{" local sep = "" for e in pairs(set) do s = s .. sep .. e sep = ", " end return s .. "}" end function Set.print (s) print(Set.tostring(s)) end
Теперь мы хотим, чтобы оператор сложения (
+
) вычислял объединение двух наборов. Для этого мы сделаем так, чтобы все таблицы, представляющие наборы, совместно использовали метатаблицу, и эта метатаблица будет определять, как они реагируют на оператор сложения. Наш первый шаг - создать обычную таблицу, которую мы будем использовать в качестве метатаблицы для наборов. Чтобы не загрязнять наше пространство имен, мы сохраним его в таблице Set:Set.mt = {} -- metatable for sets
Следующим шагом является изменение функции Set.new, которая создает наборы. В новой версии есть только одна дополнительная строка, которая устанавливает mt в качестве метатаблицы для создаваемых ею таблиц:
function Set.new (t) -- 2nd version local set = {} setmetatable(set, Set.mt) for _, l in ipairs(t) do set[l] = true end return set end
После этого каждый набор, который мы создаем с помощью Set.new, будет иметь ту же таблицу, что и его метатаблица:
s1 = Set.new{10, 20, 30, 50} s2 = Set.new{30, 1} print(getmetatable(s1)) --> table: 00672B60 print(getmetatable(s2)) --> table: 00672B60
Наконец, мы добавляем в метатаблицу так называемый метаметод, поле __add, которое описывает, как выполнить объединение:
Set.mt.__add = Set.union
Всякий раз, когда Lua пытается добавить два набора, он вызывает эту функцию с двумя операндами в качестве аргументов.
Имея метаметод на месте, мы можем использовать оператор сложения для объединения наборов:
s3 = s1 + s2 Set.print(s3) --> {1, 10, 20, 30, 50}
Когда я попытался запустить его, то получил результат: { union, mt, intersection, tostring, new, print}
вместо чисел в s3
. Кажется, вместо этого я распечатал содержимое метатаблиц. Может кто-нибудь объяснить, что здесь происходит? В книге описана версия 5.0, и я использую Lua 5.1. Может ли это быть причиной этого?