Friday, April 20, 2018

Роберту Иерузалимски "Программирование на языке Lua. Третье издание"

Lua - это легковесный динамически типизированный язык программирования, созданный для работы поверх языка С. Задумка хорошая - тяжелому и низкоуровнему С очень не хватает скриптового дополнения. Сам автор пишет, что Lua задумывался как клей между модулями написанными на С. Задача Lua не оптимизировать выполнение программы, а соединить различные блоки кода с минимальными усилиями. Именно поэтому Lua рантайм весит в развернутом состоянии в районе одного мегабайта, а также при загрузке можно определить набор стандартных библиотек (которые можно и совсем не подключать) сократив размер Lua до минимума. Все это сделало Lua широко используемым в программировании микроконтроллеров и игровых движках (которые, собственно, и послужили моей мотивацией к прочтению данной книги). 

Как я уже написал, Lua - динамически типизированный язык и, возможно, для того времени когда создавалась первая версия это казалось хорошей идеей. В современных реалиях, к сожалению, динамизм приносит больше проблем, чем пользы и даже автор явно указывает на это в книге. Я не изучал вопрос, но возможно к Lua уже есть расширения для статической типизации, типа Type Script для Javascript, даже если так, программисту стоит несколько раз подумать прежде чем добавлять в рантайм языка, парадигма которого минимализм, библиотеку для синтаксического сахара. 

У Lua и Javascript есть много общих моментов и, в принципе, понимая как работает Javascript, проблем с Lua возникнуть не должно. Представления объектов как ассоциативных массивов, области видимости переменных (по умолчанию в Lua все переменные глобальные), замыкания - все это работает очень похожим образом. Чисто теоретически, Lua можно использовать как формат описания данных, заменяя тем самым JSON, и выигрывая по скорости чтения и интерпретации данных (естественно, с запущенным интерпретатором).

Lua довольно гибкий язык и с этой гибкостью следует быть очень осторожным. Например, все функции в Lua анонимные, а если у функции есть название, то это всего лишь переменная, ссылающаяся на анонимную функцию. Что это значит? Что стоит вам переприсвоить переменную, как вы тут же навсегда потеряете свою функцию. И, несмотря на то, что в своем коде ты сам себе злобный буратино, полная мутабельность данных превращает всю ситуацию в поле из граблей. Полная мутабельность данных означает что даже библиотеку, написанную на Lua можно изменить (если программист не предпринял дополнительных мер для запрета мутабельности) и переприсвоить функции из библиотеки любое значение которое захочет пользователь. То есть ваша библиотека вместо функции может попытаться вызвать численное значение, потому что пользователь решил переприсвоить переменную, содержащую функцию. Взрыв мозга.

В Lua есть корутины (или сопрограммы) однако настоящей многопоточности нет. Добиться эмуляции многопоточности можно ручным переключением контекста, выполняя каждый шаг разных корутин. Также можно реализовать многопоточный код на С, однако стоит заметить, что тогда он будет платформо-зависимым и придется делать разную реализацию для разных платформ. Уверен в свободном доступе есть библиотеки дающие реальную многопоточность Lua корутинам.

Память в Lua контроллируется сборщиком мусора. До Lua 5.0 сборщик мусора был stop-the-world, в следующих версиях при каждом выделении памяти интерпретатор выполняет какое-то количество шагов сборщика мусора, таким образом достигается псевдо параллельность и ускоряется работа программы. Есть возможность контроллировать количество шагов сборщика мусора, отключать его и включать снова как из С так и из Lua. Любые объекты для которых память выделялась в ручную из С также должны быть собраны вручную, так как сборщик мусора о них ничего не знает.

API совместимости с С с одной стороны очень низкоуровневое, с другой максимально легковесное. Работа осуществляется через стек, на стек кладутся значения аргументов функций, со стека также забирается результат. Существуют функции позволяющие менять стек, манипулировать значениями не снимая их со стека (например конкатенировать строки). Между различными модулями используется общий реестр, хранящий глобальные значения, а также можно использовать значения upvalue, которые представляют собой замыкания, но для С функций.

"Программирование на языке Lua" считается библией языка - той книгой, которую стоит давать каждому, кто собирается использовать Lua. Тот факт что она состоит всего из 300 с лишним страниц, говорит о его размерах и о количестве знаний требующихся для его понимания. Однако компактность и легкость языка делает его сложным для разработки, в том плане, что нужно быть постоянно внимательным и следить за всем, что ты пишешь, так как ни одна IDE не может понять в динамических языках что на самом деле имел в виду программист.

Со своими целями Lua справляется очень хорошо. Писать небольшой скрипт для склейки блоков написанных на С должно быть быстро и эффективно, но писать на нем какой-то более масштабный проект кажется не лучшей затеей.

No comments:

Post a Comment