Почему это было бы полезно?В любом случае, работа компилятора заключается в том, чтобы делать это.Почему программист должен выполнять работу компилятора?
Lua - динамический язык.Компиляторы могут много рассуждать в статических языках, например, извлекать константные выражения из цикла.В динамических языках ситуация немного отличается.
Основная (и единственная) структура данных Lua - таблица.math
также является просто таблицей, хотя здесь она используется как пространство имен.Никто не может помешать вам модифицировать функцию math.sin
где-то в цикле (даже подумав, что это было бы неразумно), и компилятор не может знать об этом при компиляции кода.Поэтому компилятор делает именно то, что вы ему указываете: на каждой итерации цикла ищите функцию sin
в таблице math
и вызывайте ее.
Теперь, если вы знаете, что вы несобираясь изменить math.sin
(т.е. вы собираетесь вызывать ту же функцию), вы можете сохранить ее в локальной переменной вне цикла.Поскольку нет поиска в таблице, результирующий код работает быстрее.
С LuaJIT ситуация немного отличается - он использует трассировку и некоторую продвинутую магию, чтобы увидеть, что ваш код делает во время выполнения таким образом, он может фактически оптимизировать цикл, перемещая выражение за пределы цикла и другие оптимизации, кроме фактической компиляции его в машинный код, что делает его быстрым безумным.
Относительно «переопределения переменных как локальных»- много раз при определении модуля вы хотите работать с оригинальной функцией.При доступе к pairs
, max
или к чему-либо с использованием их глобальных переменных никто не может заверить вас, что это будет одна и та же функция при каждом вызове.Например, stdlib переопределяет множество глобальных функций.
Создавая локальную переменную с тем же именем, что и у глобальной, вы, по сути, сохраняете функцию в локальной переменной, и потому что локальные переменные (которые имеют лексическую область, то есть они видны в текущей области и во всех вложенных областях) имеют приоритет перед глобальными переменными, вы всегда должны вызывать одну и ту же функцию.Если кто-то изменит глобальный позже, это не повлияет на ваш модуль.Не говоря уже о том, что это также быстрее, потому что глобальные переменные ищутся в глобальной таблице (_G
).
Обновление : я только что прочитал Советы по производительности Lua отРоберто Иерусалимский, один из авторов Lua, и он в значительной степени объясняет все, что вам нужно знать о Lua, производительности и оптимизации.ИМО самые важные правила:
Правило № 1 : Не делайте этого.
Правило № 2 : Не делайтепока не делай(только для экспертов)