Таблицы в Lua
Таблицы в языке Lua играют роль ассоциативного массива. В нём в качестве индексов выступают различные типы данных, кроме nil (ничто).
Свойства таблиц:
- Т. — это объект;
- Она может иметь неограниченный размер;
- Т. – это пары ключ-значение. При этом и в ключе, и в значении может быть любой тип данных, кроме nil.
Разработчики Lua позиционируют таблицы как ведущий инструмент структурирования данных в своём языке.
Создаём таблицу в Луа
Пустая простая таблица
local t = {}
Чтоб получить доступ к её полю, используется такой синтаксис:
переменная[ключ]
Пример 1 с разными типами
t[1] = 10
t[«Пушкин»] = «поэт»
t[3] = truelocal function f()
return 1
endt[f] = «функция»
t[«функция»] = f
t.me = t — тоже самое, что t[«me»] = t — ссылка на самого себя
print(t[«функция»]()) — > 1
Идентификация таблицы при создании
local t = {1, 2, 3, x = 5, [«Пушкин»] = «поэт»}
Пример 2
t = {}
t[1] = «first» — новое поле с ключом 1 и значением «first»
t[2] = 20 – поле с ключом 2 и значением 20
k = «name»
t[k] = «Jane»
a = t[1] — присваиваем a значение «first»
b = t[2]
c = t[«name»]
Строковые ключи t[«name»] записать проще — t.name:
t.name = «name» — равнозначно t[«name»] = «name»
a = t.name — равнозначно a = t[«name»]
Важно! В 1 случае представлено поле таблицы с ключом «name» (оно равнозначно t[«name»]). Второе выражение — это поле, где ключ есть идентификатор переменной name. Рассмотрим различие более подробно:
t = {}name = «somebody» t[name] = «Jane» — в поле «somebody» помещено значение «Jane»a = t[name] — переменная a получает значение поля «somebody» («Jane»)b = t.name — переменная b получает nilc = t.somebody — переменная c получает значение поля «somebody» («Jane»)
Если поля с заданным ключом нет, обращение к нему возвращает nil:
t = {}
a = t.name — переменная a получает значение nil
Как следствие, можно удалить поле, присвоив ему пустое nil:
t.second = nil
Заполнение таблицы при создании. В {} помещаем ключи и значения по примеру из начала статьи. Элементы следует разделять запятыми или точками с запятой:
t = {[«apple»]=»яблоко», [«orange»]=»апельсин», [«lemon»]=»лимон»}
Это равнозначно коду ниже:
t = {}
t.apple = «яблоко»; t.orange = «апельсин»; t.lemon = «лимон»
При работе со строковыми ключами квадратные скобки (и двойные кавычки) можно опустить:
t = {apple=»яблоко», orange=»апельсин», lemon=»лимон»}
Можно создать таблицу, где поля тоже являются таблицами:
points = {
a = {x=20, y=1},
b = {x=40, y=2}
}
Или:
points = {}
p.a = {x=20, y=1},
p.b = {x=40, y=2}
Массивы
Если при инициализации таблицы ключи не были указаны, то язык сам присваивает значения ключей, начиная с 1.
Важно! Адресация массивов начинается не с 0, а 1.
local t = {3, 4, 5}
print(t[1], t[2], t[3]) — > 3, 4, 5
Чтобы не нарушать структуру при работе с элементами массива, надо использовать библиотеку Lua table.
local t = {1, 2, 3, 4, 5}
- table.insert(t, 6) — добавляет элемент в конец массива. Теперь t = {1, 2, 3, 4, 5, 6}
- table.insert(t, 0, 1) — вставляет элемент по индексу, сдвигая оставшиеся элементы массива. Теперь t = {0, 1, 2, 3, 4, 5, 6}
- table.remove(t, 3) — удаляет из таблицы элемент по индексу 3 и сдвигает оставшиеся элементы. Теперь t = {0, 1, 3, 4, 5, 6}
Чтобы посчитать размер массива, используйте #:
local count = #t
Оператор # возвращает max индекс непрерывной последовательности ключей от начала массива.
local t = {1, [100] = 2}
print(#t) — > 1, поскольку t[1] не nil, а t[1 + 1] равно nil.
У массива, в котором значения хранятся одно за другим, # вернёт количество его элементов.
Обход элементов таблицы
Выяснить, сколько элементов содержится в таблице Lua можно только с помощью их обхода. Исключение — это массивы и оператор # для определения длины массива. Обходим массив с помощью цикла for:
local t = {1, 2, 3, «Ваня»}
for i = 1, #t, 1 do
print(t[i])
end— > 1
— > 2
— > 3
— > Ваня
Обычные таблицы обходятся циклом for:
local t = {1, 2, x = 4, y = 5, [«Пушкин»] = «поэт»}
for key, value in pairs(t) do
print(key, value)
end— > 1 1
— > 2 2
— > y 5
— > x 4
— > Пушкин поэт
Порядок элементов в таблице отличается от порядка, в котором значения помещали в таблицу.
Методы
Попытка смоделировать объектно-ориентированное программирование:
local t = {x = 1}
function t:fun()
print(self.x)
endt:fun()
— > 1
Что означает этот код?
- Создание таблицы t;
- В ней ввели поле x и присвоили ему значение 1;
- В таблице создали функцию fun;
- Внутри неё обратились к таблице через переменную self (где self это первый скрытый параметр у функции. Вызов функции как t:fun() аналогичен вызову t.fun(t))
- Вызвали в таблице t метод fun;
Мы создали объект, его метод и вызов. При этом нет возможности создавать объекты с определённым типом. Объект и метод существуют в одном виде. Для того, чтобы создать объект типа tt, который действует так же, как объект типа t, нам следует повторить код с самого начала
Есть ли решение? Да. Но для этого надо изучить метатаблицы.
local tt = {x = 2}
function tt:fun()
print(self.x)
endfunction checkMetod(x)
x:fun()
endcheckMetod(t)
checkMetod(tt)—> 1
—> 2
Метатаблицы
Мета таблицы переопределяют действие встроенных типов. Они подобны конструкции operator() в Cpp. Рассмотрим, как можно сложить две таблицы (в Lua данная возможность не встроена).
local data1 = {x = 1}
local data2 = {x = 2}
— создаем таблицу
local meta = {}
— в таблице определяем специальное поле __add (оператор +)
function meta.__add(op1, op2)
return op1.x + op2.x
endsetmetatable(data1, meta)
print(data1 + data2) —> 3
Создаём два объекта, в каждом присутствует поле х. Затем создаём таблицу meta. В ней определяем функцию с именем __add. В завершении установили метатаблицу первому операнду.
Заключение
Таблица – это фундаментальная основа Lua, воплощающая практически все его возможности.
Так как функции относятся к значениям первого класса, поля таблицы могут содержать и функции. Таким образом, таблицы хранят и методы.
Реализация ассоциативных массивов в Lua крайне эффективна. Скорость вычисления хэш-функций в Lua практически безупречна. Интерпретируемые Lua скрипты справляются с этой задачей в 2 раза медленнее программ на языке C. А вычисление функций значительно быстрее, чем аналоги на Perl, Ruby и Python.