Опишу задачи. Некоторые задачи относятся, скорее, к интерпретируемым языкам, как их сейчас называют "скриптам".
0. LUA хорош тем, что к нему уже написаны так называемые "биндинги" к языкам C++, C. Т.е. она хорошо встраивается в твой C/C++ код, без плясок с бубном.
1. И самая важная задача, это когда надо руками постоянно править/поправить текст программы и тут же получать результат, или смотреть что получается.
Пример из моей проф. практики: есть большая игра. Её с++ проект компилируется приличное время, с современными компиляторами на 4х головых пнях это полминуты-минута, и то потому что я вышвырнул всю метушню. Внутри этой большой игры по плану есть и пишутся небольшие сценки-миниигры, да и вообще просто сцены. Человек десять не сильно продвинутых ребят сидят и "скриптуют" поведение объектов внутри игры путем написания LUA кода. В процессе этого они несколько сотен раз быстро одной кнопкой перезапускают LUA-скрипт. Вот это и есть первейшая задача интерпретируемого языка. Как ты её реализуешь на C++? Каждый раз поправлять и компилять? Производительность труда упадет в несколько раз. Вдобавок, студенты не могут в C/C++. А вот пользоваться простеньким язычком, в котором им не объясняют всех подробностей - могут.
2. Задача когда требуется непредсказуемо, внезапно, вдруг (или наоборот, just planned) изменять поведение программы. Скажем, ее части находятся на сервере и подгружаются. Либо пишутся на местах. Ну и как это сделать с C/C++? Дать юзеру исходники системы? Заставлять его писать на своём C/C++/др.языке и подключать в виде plugins/dynamic libraries?
Часто это задача также возникает в случае если учитывается окружение пользователя, которое очень изменяемо.
3. Задача обратная, лёгкое встраивание в LUA-мир внешних C++/C объектов/сущностей и использование их изнутри LUA скриптов. Пример - система подвижных картинок (спрайтов), система проигрывания звуков, и любое другое. В LUA оно изнутри может выглядеть как такой квази-объект, называется "таблица". Обмен работает в ту и в другую сторону, можно как получать информацию снаружи, так и наоборот, управлять внешним миром. К этому напрямую относится пункт 0, а именно готовое и уже продуманное связывание (binding) внешнего C/C++ с LUA.
4. Все переменные LUA при желании легко сохраняются и восстанавливаются, втч в/из файлов. Втч многократно. Поэтому всё управляемо, всё на ладони.
5. Предыдущие пункты подразумевают на самом деле под собой модульное написание/работу проекта - он может работать не как гигантская каша кода/скриптов, а как постоянно перезагружаемые с нуля скрипты работающие как с постоянными находящимися в памяти переменными, и в том числе и с отгружаемым на диск состоянием/переменными скрипта. Этим удовлетворяется управляемость, предсказуемость отладки — любую задачу можно отлаживать многократно, потому что её состояние у тебя есть и ты его можешь постоянно пере-воспроизвести (а также выслать кому-нибудь) чтобы понять что там происходит.
Система с помощью LUA может быть построена двояко. Она может представлять собой на самом верху высокоуровневую LUA-программу и только так и работать (либо перегружая скрипты, либо догружая их). В этом случае C/C++ это лишь низкоуровневый сервис, API существующей наверху LUA-программы.
Либо, система также может быть построена классически - когда LUA скрипты это всего лишь (мутируемые) под-компоненты C/C++ системы.
6. Задача отладки. (имеет прямое отношение к пункту 1-2). Для отладки в обычном случае потребуется запуск C/C++ отладчика. А это - пересборка в Debug варианте. Иногда это и дольше и проект начинает работать иначе. Конечно это всё решаемо разбиением на модули, один собирается в дебаге, остальные нет, но так или иначе, все это непросто. Не сильно продвинутые ребята с отладкой (указателями, адресами, выделением памяти, битами и байтами) не справятся. Ну а так как LUA интерпретируема, то наблюдать за происходящим и вмешиваться можно из консоли. Хотя под LUA в мое время существовал прямо отдельный отладчик.