Что можно ожидать от Луа 5.2?

    Опубликована первая превью-версия Луа 5.2


    Луа (Lua) — мощный, быстрый, лёгкий, расширяемый и встраиваемый скриптовый язык программирования. Луа удобно использовать для написания бизнес-логики приложений.

    Несмотря на то, что исходный код Луа открыт, разработка новых версий языка — достаточно закрытый, консервативный и неспешный процесс (что, в случае с языком программирования, не так уж и плохо). Каждую новую версию языка в коммьюнити ждут с нетерпением и смакуют просачивающиеся на публику детали.

    То, что выложено на публику даже не альфа — это просто снапшот рабочего кода. К релизу может измениться всё, что угодно.

    Анонс здесь: http://article.gmane.org/gmane.comp.lang.lua.general/61229

    Дополненный список изменений от авторов здесь: http://article.gmane.org/gmane.comp.lang.lua.general/61505

    Скачать исходники можно здесь: http://www.lua.org/work/lua-5.2.0-work1.tar.gz

    Сборка под Windows здесь: http://article.gmane.org/gmane.comp.lang.lua.general/61528

    Посмотреть исходники в онлайне можно, например, здесь.

    Update: Выложен 5.2.0-work2, анонс здесь.

    Что изменилось


    Официальной информации пока мало. Список изменений взят, в основном, из анализа diff-ов руководства пользователя. Детали можно найти там же. Изменения даны в произвольном порядке. Список, скорее всего, неполон и будет в меру сил уточняться.

    Общие изменения

    • ABI и байткод, как и ожидалось, несовместимы с 5.1.
    • Почти все фичи, объявленные более неподдерживаемыми (deprecated) в 5.1 в новой версии удалены.
    • Фичи, объявленные deprecated в 5.2 в этой версиии отключены по умолчанию. Для их включения нужно пересобирать интерпретатор.

    Работа с окружениями из Lua


    Это наиболее противоречивый набор изменений. Вокруг него в луашной рассылке сейчас ломается большая часть копий.

    Lexical environments

    Добавлены «лексические окружения» (lexical environments), позволяющие подменить для определённого куска кода глобальное окружение на указанную таблицу.

    Новая функция loadin()

    Добавлена новая функция loadin(), позволяющая загрузить код в заданное окружение:

    Функции setfenv() и getfenv()

    Функции setfenv() и getfenv() больше не поддерживаются. Вместо них предлагается использовать новые лексические окружения или новую функцию loadin().

    Для страждущих оставлены debug.setfenv() и debug.getfenv().

    У корутин больше нет отдельных окружений

    Все корутины в стейте имеют одно общее фиксированное окружение.

    Новые метаметоды


    Метаметод __len работает для таблиц и строк

    Код работы с таблицами и строками теперь обращает внимание на метаметод __len при определении длины данных.

    Новые метаметоды __ipairs и __pairs

    Теперь можно переопределять обход объекта при использовании ipairs и pairs.

    Модуль debug


    Модуль debug больше не подгружается по умолчанию

    Если код его использует, нужно явно вызывать require(«debug»).

    Новые функции для работы с upvalue

    Добавлены debug.upvalueid(), debug.upvaluejoin() и соответствующие им lua_upvalueid() и lua_upvaluejoin(). (Часть из них пока не документирована.)

    Теперь можно получить уникальный идентификатор upvalue (нужен, чтобы понять, указывают ли два upvalue на один и тот же объект).

    При помощи upvaluejoin можно сделать, чтобы два разных upvalue указывали указывали на один объект. Это должно позволить делать сериализацию функций с upvalue без патчей кода Луа.

    Расширена доступная отладочная информация

    В записи, возвращаемой debug.getinfo() и lua_getinfo(), появились новые поля. Теперь о функции в стеке вызовов можно узнать следующее:
    • была ли функция вызывана через tail call;
    • число upvalue функции;
    • число параметров функции;
    • была ли функция объявлена как функция с переменным числом аргументов.

    Прочие изменения в API Луа


    Bitlib

    Добавлена библиотека для выполнения бинарных операций.

    Улучшено экранирование символов в %q

    Теперь string.format("%q") экранирует все управляющие символы.

    Frontier pattern

    Шаблон поиска %f («frontier pattern») теперь документирован.

    Изменено поведение ipairs()

    Теперь при определении длины таблицы ipairs() следует общим правилам (раньше обход таблиц проводился строго до первой дырки).

    Негативные числа в select()

    Теперь select()-у можно передать в качестве номера первого аргумента выборки отрицательное число — будет возвращено соответствующее ему число аргументов с конца (в прямом порядке).

    math.log10() больше не поддерживается

    Теперь в math.log() можно указывать основание логарифма.

    Функция table.maxn() больше не поддерживается

    Если она вам и в самом деле нужна, напишите её сами.

    Функции table.unpack() и table.pack()

    Функция unpack() перенесена в модуль table. К ней в пару добавлена новая функция table.pack(), сохраняющая аргументы в новую таблицу (число аргументов сохраняется в поле «n» в этой таблице).

    Фильтрация по типу чанка в load()

    Функции load() теперь можно запретить загружать байт-код либо текстовые исходники.

    Это полезно, поскольку, в отличие от текста, загружать байт-код из недоверенных источников не рекомендуется. Луа 5.2 больше не пытается валидировать корректность загружаемого байт-кода.

    package.config теперь документирован

    Теперь из Луа официально доступны настройки времени компиляции системы модулей:
    • разделитель директорий в пути;
    • разделитель путей в шаблоне поиска;
    • символ для обозначения точек подстановки в шаблоне;
    • символ для подстановки пути к исполнимому файлу, в котором выполняется скрипт (для Windows);
    • символ границы значимой части имени файла для построения имени функции luaopen_* при открытии модуля.
    Добавлена функция package.searchpath()

    Функция, использующаяся для поиска файлов по заданному набору путей. (Та же, что используется в require.)

    Аргументы в xpcall()

    Теперь в xpcall() можно задавать аргументы для вызываемой функции, аналогично pcall().

    Проверка аргументов в os.date()

    Функция os.date() теперь проверяет переданную ей форматную строку с тем, чтобы обезопаситься от падучих реализаций strftime().

    Улучшена поддержка пайпов

    Если файл был открыт при помощи io.popen(), file:close() вернёт код завершения соответствующего ему процесса.

    Улучшен интерфейс file:write()

    Теперь file:write() возвращает file, что позволяет делать цепочку вызовов.

    Сборщик мусора


    Emergency GC

    Луа форсирует полную сборку мусора если не может аллоцировать память.

    Эфемерные таблицы

    Сборщик мусора теперь корректно обрабатывает циклические ссылки между ключами и значениями в таблицах со слабыми ключами.

    Скорректировано поведение инкрементального сборщика мусора

    Попытка выполнения шага сборки мусора больше не перезапускает сборщик мусора если он был остановлен.

    Остановлен ли GC?

    Теперь можно узнать, остановлен ли GC. В Луа: collectgarbage(«isrunning»), в C: lua_gc(LUA_GCISRUNNING).

    Прочие изменения в языке


    Работа с локалью

    Определение типа символа (ctype) при компиляции теперь полностью ведётся по внутренним фиксированным таблицам, не зависящим от текущей локали.

    Идентификаторы могут использовать только символы, не зависящие от локали.

    Шестнадцатиричные коды в строковых литералах

    Теперь в строках можно писать, например, \xFF (раньше — только \255).

    Упрощёна свёртка констант

    Во избежание проблем с числами с плавающей точкой компилятор больше не делает свёртку констант (constant folding) для операторов деления и получения остатка от деления.

    Улучшена поддержка нестроковых сообщений об ошибках

    Если обработчику ошибок в интерпретаторе приходит вместо строки — сообщения об ошибке объект, он пытается вызвать метаметод __tostring перед выводом ошибки на экран.

    Работа с окружениями из С API


    Новые поля в реестре

    В реестре (registry, специальная таблица, доступная только сишному коду) появились предустановленные поля, доступные по следующим целочисленным ключам:
    • LUA_RIDX_MAINTHREAD — главная корутина текущего стейта (неявно создаётся вместе с ним);
    • LUA_RIDX_GLOBALS — глобальное окружение луашного кода (таблица);
    • LUA_RIDX_CPCALL — функция cpcall() для вызова сишных функций, работающих с Луа без создания для них замыканий (то есть для «незабинженных» функций). Функция lua_cpcall() была убрана из API.
    Убран псевдоиндекс LUA_GLOBALSINDEX

    Если окружение сишной функции не было изменено, вместо него можно использовать LUA_ENVIRONINDEX. Иначе нужно получить глобальное окружение из реестра.

    Изменена логика работы макросов lua_getglobal(), lua_setglobal(), и lua_register()

    Теперь они работают с окружением функций вместо глобального окружения стейта. Это больше соответствует тому, как Луа работает с глобальными переменными.

    Прочие изменения в Lua C API


    Переименована функция luaL_typerror()

    Теперь она называется luaL_typeerror().

    Добавлена функция lua_compare()

    Её нужно использовать вместо более не поддерживаемых lua_equal() и lua_lessthan().

    lua_arith()

    Новая функция lua_arith() позволяет выполнять из C арифметические операции с луашными значениями по правилам Луа (с учётом метаметодов и проч.).

    Определение длины объекта

    Функция lua_objlen() переименована. Теперь она называется lua_rawlen(). Добавлена функция lua_len(), знающая про метаметод __len у таблиц.

    Улучшена функция lua_checkstack()

    Теперь гарантировано, что она не может вызвать ошибку выделения памяти.

    Улучшены функции lua_pushstring() и lua_pushlstring()

    Теперь они возвращают указатель на внутреннюю копию строки.

    lua_copy()

    Новая функция lua_copy() позволяет копировать значения на луашном стеке данных из одного слота в другой (при этом старое значение в другом слоте замещается копируемым).

    Проверка версии рантайма

    Теперь можно проверить версии рантайма Луа при помощи новых функций lua_version() и luaL_checkversion().

    Больше того, поскольку эти функции возвращают указатели, можно проверить, что луашный стейт и выполняющийся сейчас код находятся в одном адресном пространстве. Это позволяет отловить ситуацию, когда Луа несколько раз слинкована с приложением.

    Функция luaL_checkversion() выполняет такую проверку автоматически. Эту функцию вызывает luaL_register(), так что теперь соответствие рантаймов будет проверяться автоматически при подключении каждого модуля.

    luaL_testudata()

    Добавлена новая функция luaL_testudata() для теста userdata на принадлежность данному типу. (Раньше была доступна только валидация через luaL_checkudata(), вызывавшая ошибку при передаче userdata неверного типа.)

    luaL_traceback()

    Новая функция luaL_traceback(), чтобы делать стектрейсы из C, подобно debug.traceback() в Lua.

    luaL_tolstring()

    Функция luaL_tolstring() теперь документирована. Она позволяет конвертировать луашные значения аналогично функции tostring() в Луа. Реализовать свой собственный print() теперь проще чем когда бы то ни было!

    Поддержка yield'ов через границу Луа—C

    Добавлены новые методы API, позволяющие писать код на C, сквозь который можно было бы делать yield в Луа:
    • lua_yieldk()
    • lua_callk()
    • lua_pcallk()
    • lua_getctx()
    Пример использования можно увидеть, например, в новой реализации функции table.foreach() (которая почему-то до сих пор живёт в исходном коде, хотя была объявлена deprecated в 5.1).

    Эти методы достаточно широко используются в самой реализации Луа 5.2, так что теперь можно будет делать yield через метаметоды, итераторы цикла for и функции pcall() и xpcall()!

    Новый код ошибки LUA_ERRGCMM

    Появился новый код ошибки LUA_ERRGCMM, означающий, что возникла ошибка при выполнении метаметода __gc при сборке мусора. (По понятным причинам, обычно не имеет отношения к коду на который указывает стектрейс.)

    Для симметрии также добавлен код «ошибки» LUA_OK, означающий, что вызов был сделан успешно.

    Улучшена загрузка динамических библиотек под никсами

    Теперь loadlib корректно работает с библиотеками с глобальными символами (за счёт использования RTLD_GLOBAL).

    Изменения в реализации


    Увеличено максимальное число констант на функцию (чанк)

    Теперь в одном чанке может быть до 226 констант (раньше было до 218). Превышение этого лимита вызывает ошибку времени компиляции «constant table overflow».

    Теперь можно сохранять ещё более монструозные данные в виде луашных конструкторов таблиц, не заботясь о разбиении генерируемого кода на отдельные функции.

    Оптимизирован парсер

    Парсер теперь отъедает гораздо меньше сишного стека за счёт отказа от использования автоматических массивов (auto arrays).

    Новая хэш-функция для чисел с плавающей запятой

    Теперь хэширование выполняется корректно вне зависимости от размера lua_Number (раньше на некотрых 64-хбитных платформах возникали проблемы, если переопределить lua_Number в long double).

    Известные проблемы в текущем снапшоте

    • luac ещё не работает должным образом, в частности сломан дизассемблер байткода;
    • код не собирается под Windows из-за конфликта с имёнем функции LoadString и проблем с макросом lua_number2uint() (в рассылке опубликованы неофициальные патчи);
    • код пока не собирается как C++;
    • в luaconf.h по умолчанию задан старый LUA_CPATH с «5.1» в пути;
    • package.searchpath() пока ничего не знает про точки в имени модуля;
    • документация пока в некотором беспорядке, поэтому не для всех новых функций понятно, будут ли они официальными, или останутся недокументированными.
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 57
    • 0
      Кат!
      • 0
        Да уж, простыня, мама не горюй!
        • +2
          Пардон, кат потерялся по дороге :-)
          • +7
            На самом деле, жалко человека. Судя по «Итак...» он уверен, что кат есть. А минусовать, между тем, уже начали(
        • +1
          Было бы не плохо вначале поста написать в паре слов о том что это вообще такое «луа»
          • +1
            А что незнающим о луа интересно чего в нем нового?
            • +2
              Для начала интересно узнать о чем идет речь
            • +1
              Спасибо, дополнил.
            • +1
              Спасибо. Большая работа вами проделана! странно что минусуют
              • +2
                Спасибо на добром слове. Увы, не угадал с катом. :-)
                • +1
                  врятли. «Быстрых, легких» скриптовых языков примерно дохрена. А вся статья состоит из перечисления минусов этого языка. Причем минусы такие, хорошие и жирные.

                  А после 4х часов утра на хабре сидят очень злые и невыспавшиеся люди. Сейчас народ к 11 на работу подтянется, будут вам плюсы )
                  • 0
                    Ну так на то это и новая версия, чтобы минусы исправлять, разве нет?
                    • +2
                      А по поводу «быстрых и лёгких» дохрена — это спорное заявление. К тому же, фишка Луа в том, что в языке достигнут хороший баланс по всем перечисленным показателям, не только по быстроте и скорости.

                      Но мне холиваров по поводу языка разводить здесь совсем не хочется. Я никого Луа использовать не заставляю. Те, кто использует — те обычно знают «в чём фишка». ;-)
                      • +2
                        Злых и невыспавшихся всегда хватает, хватает и тех кто минусует то чего не понимает, но хороший пост такими людьми не испортить.
                  • +1
                    Видел в песочнице хорошее руководство по созданию игры space invaders на lua в ubuntu, но не сохранил =(
                    Ни у кого не осталось?
                    • 0
                      Луа используется ведь в игре ВоВ?
                    • 0
                      squirrel наше все.
                      • 0
                        А про поддержку юникода опять забыли.
                        • 0
                          Не забыли, но и не добрались пока.

                          С другой стороны, UTF-8 вполне можно пользоваться (стиснув зубы).

                          http://penlight.luaforge.net/FAQ/#T9
                          • 0
                            Ну, в Аегисабе (для которого я и пишу на Lua) для UTF-8 есть свой костыль. Про отдельные библиотеки тоже давно знаю, но хочется же, чтобы всё это было родное.
                            • 0
                              Вот, специально уточнил позицию авторов (хотя и так было примерно понятно).

                              http://article.gmane.org/gmane.comp.lang.lua.general/61523

                              Там дальше в треде народ пошёл ещё раз перечислять проблемы с Юникодом у тех, кто использует Луа под Windows… Можно излить свои печали, иногда это работает.
                              • 0
                                Хочу уточнить на всякий случай, что проблемы с Юникодом под Windows возникают в основном при работе с юникодной файловой системой через io.* (что всё равно обычно отдаётся на откуп движку — так что не страшно). Сами юникодные строки можно использовать — так же как и на других платформах.
                        • +1
                          знакомился луа, очень похож на javascript, понравилась идея метатаблиц. Как встраиваемый язык — вещь
                          • 0
                            А есть ли ссылка на какой-нить вменяемый туториал (желательно под с++), как связать и в чем сила использования Луа? Просьба не минусовать, а отнестись с пониманием. Луа на слуху уже года 3 как (или даже больше), периодически то тут, то там всплывает информация. Но найти простой, и главное содержательный и показательный урок по её использованию пока не удалось. Буду благодарен за толковый линк на статейку, где показаны все прелести и радости от использования Луа.
                            • +1
                              Сайт посвященный луа на русском. На нем есть список полезных ссылок. К примеру Язык Lua и использование скриптов на нем в программах на С++, Я люблю Lua.
                              По этим ссылкам недавно обучался один знакомый с нуля.
                              Туториалы на английском
                              Большая статья на gamedev.net (перевод, но тут говориться про lua 4.0.1 — а с тех пор язык достаточно изменился, но для начала можно почитать)
                              • 0
                                статья с gamdev.net есть переведенная на русский на gamedev.ru. видел эту статью, изучал, но понимания чем lua в данных примерах лучше банального ini файла не появилось. остальные ссылки спасибо посмотрю, но кажется там тоже не совсем реальная жизнь отражена.
                                • +1
                                  Ну тогда в статье на ibm.com есть раздел Зачем встраивать язык? — можете его почитать.
                                  • 0
                                    Поддерживаю, хорошая статья.

                                    Вот ещё есть паттерн Alternate Hard and Soft Layers, там есть несколько полезных мыслей по поводу использования скриптовых языков вообще. Там, правда довольно сумбурно написано.
                                    • +1
                                      всем спасибо за информацию. ссылки сохранил и в ближайшее время вернусь к изучению темы :)
                            • 0
                              Еще б ей многопоточность…
                              • +2
                                в каком виде? share nothing с изолированными состояними и обменом сообщениями есть в виде минимум нескольких библиотек (lua lanes, например). share everything — авторы против такого подхода.
                                • 0
                                  Распараллеливание кода в Луа отлично получается и без поддержки системных потоков самим языком. (Понятное дело, что для этого нужны изолированные стейты, но это и хорошо, лучше масштабируется.)
                                  • 0
                                    Все игрушки, в которых внедрена луа — напрочь отказываются использовать больше одного ядра. Даже если сам движок игры поддерживает многоядерные архитектуры? Чем можно объяснить? Ленью разрабов?

                                    Сразу приведу пример: NWN II (только 1 ядро), GarrysMod (на движе Half-Life 2 Ep2, который поддерживает до 4 ядер).
                                    • 0
                                      В отличие от «некоторых других» динамических языков, в Луа можно параллельно работать одновременно с несколькими стейтами в одном процессе.

                                      Если нужно организовать параллельную работу логики на Луа, обычно создаётся по стейту на поток и организуется механизм обмена данными между стейтами. Например, налаживается система посылки сообщений между потоками или данные просто расшариваются тем или иным способом между стейтами с обеспечением синхронизации доступа кодом движка.

                                      Почему разработчики отдельных игр пренебрегают такой возможностью мне сказать сложно. Может быть считают, что овчинка не стоит выделки, и игровая логика отлично будет работать и на одном ядре…
                                      • 0
                                        Скорее время пересылки данных между стейтами больше времени обработки микроскриптов, которые предварительно скомпилированы. 100% знаю, что в том же гаррис моде скорость работы Lua очень критична, так как от неё зависит два внутренних языка программирования + все-все добавленные обьекты и физические игрушки.
                                        • +1
                                          Тут уже всё сильно зависит от деталей конкретной ситуации.
                                          • +1
                                            Хм, хотя в том же крайсисе луа отвечает за все скрипты, и при этом многопоточна. С другой стороны, от поддержки системных потоков самим языком хуже явно не станет, другое дело что внедрить подобное, не нарушив идеологию языка (и желаний разработчиков) — весьма и всемьса сложно.
                                • 0
                                  Выложили билд Луа 5.2-work1 под Windows, можно играться.

                                  http://article.gmane.org/gmane.comp.lang.lua.general/61528
                                  • +1
                                    Опубликован дополненный список изменений от авторов: http://article.gmane.org/gmane.comp.lang.lua.general/61505.
                                    • +1
                                      После анализа этого поста внёс следующие дополнения в статью:

                                      • Подтверждено, что в 5.2 можно будет делать yield через метаметоды, итераторы цикла for и функции pcall() и xpcall()!
                                      • Новые коды ошибок: LUA_ERRGCMM и LUA_OK.
                                      • Функцию lua_arith() теперь считаем документированной.
                                      • Упомянута функция lua_len(), уважающая, в отличие от lua_rawlen(), метаметод __len у таблиц.
                                      • Новые функции: lua_copy() и luaL_tolstring().
                                      • Функции lua_pushstring() и lua_pushlstring() теперь возвращают указатель на внутреннюю копию строки.
                                      • Если файл был открыт при помощи io.popen(), file:close() вернёт код завершения соответствующего ему процесса.
                                      • Теперь file:write() возвращает file.
                                      • Теперь можно узнать, был ли остановлен GC.
                                      • У корутин больше нет отдельных окружений
                                      • Тип символа при компиляции теперь не зависит от локали.
                                      • Увеличено максимальное число констант на функцию (чанк).
                                      • Парсер теперь отъедает гораздо меньше сишного стека.
                                      • Улучшена хэш-функция для чисел с плавающей запятой.
                                      • Улучшена загрузка динамических библиотек под никсами

                                    • 0
                                      я вот главное не понял :-D
                                      он быстрей стал?
                                      • 0
                                        Куда уж быстрей-то? Есть подозрение, что без JIT-а сильно быстрее уже не получится. А с JIT-ом — см. LuaJIT 2, в среднем всего в 2.37 раза медленнее C++. 5.2, конечно, пока LuaJIT не поддерживает, но ближе к релизу, скорее всего, будет.

                                        Если говорить про стандартную реализацию 5.2, то, говорят, стало где-то чуть медленнее, где-то чуть быстрее. Существенной разницы с 5.1 нет.
                                        • 0
                                          ну понятно что быстрей c jit :)
                                          я на луа использовал для lua_newthread, вот у меня там еще проблема была что надо переменные в скриптах как local обновлять. а то они между thread'ами шарились…
                                          но как понял это типа не баг а фича
                                          • 0
                                            Переменные в скриптах в Lua в принципе нужно объявлять как local. Иначе они глобальные. Со всеми вытекающими.
                                            • 0
                                              угу.
                                              а как тогда быть если мне нужно чтобы скриптам можно было не доверять?
                                              как-то можно перехватить попытку создать глобальную переменную?
                                              • 0
                                                Ненадёжный код нужно помещать в песочницу. (По-хорошему ещё нужно ограничивать память через lua_setallocf и время выполнения через debug.sethook, этого по ссылке нет.)

                                                Если нужно только перехватывать «нелегальные» глобальные переменные (а это полезно делать всегда, не только в песочнице), то нужно повесить на глобальное окружение (это же табличка на самом деле) хитрую метатаблицу, которая будет в __index и __newindex перехватывать обращения и проверять их.

                                                См. etc/script.lua в луашном дистрибутиве. (Здесь — версия, которой я пользуюсь)

                                                Подробнее про проблему можно почитать здесь.
                                                • 0
                                                  о спасибо, что-то типа этого я и искал.
                                                  мне правда это надо на уровне си сделать, но тут уже все проще )
                                                  спасибо
                                                  • 0
                                                    Ну… Всё, что можно сделать на Луашном API, можно сделать и в Си :-)
                                                    Будут проблемы — добро пожаловать в Луашную рассылку, поможем.

                                                    www.lua.org/lua-l.html
                                                    • 0
                                                      да давно там, через nntp читаю :)
                                                      стеснялся спросить
                                                      • 0
                                                        Уверен, стесняться здесь нечего. ;-)
                                      • 0
                                        Выложили lua-5.2.0-work2:

                                        www.lua.org/work/
                                        • 0
                                          Обновил описание lua_version() и luaL_checkversion(). Оказывается, крайне полезные функции.
                                          • 0
                                            Выложили lua-5.2.0-work3:

                                            www.lua.org/work/

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.