2012-02-08 22 views
11

He estado buscando en algún código fuente Lua, y veo a menudo este tipo de cosas en el principio del archivo:¿Por qué hacer que las funciones globales de Lua sean locales?

local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc.. 

No sólo hacen las funciones locales para dejar Lua acceder a ellos más rápido cuando se usa a menudo ?

+1

Es posible que desee echar un vistazo a http://stackoverflow.com/questions/4643814/why-would-this-lua-optimization-hack-help –

Respuesta

12

Los datos locales están en la pila y, por lo tanto, tienen acceso a ellos más rápido. Sin embargo, dudo mucho que el tiempo de llamada a la función setmetatable sea realmente un problema importante para algún programa.

Estas son las posibles explicaciones para esto:

  1. prevención de la contaminación del medio ambiente mundial. La convención moderna de Lua para módulos es no hacer que se registren directamente en la tabla global. Deben construir una tabla local de funciones y devolverlas. Por lo tanto, el único forma de acceder a ellos es con una variable local. Esto fuerza un número de cosas:

    1. Un módulo no puede sobrescribir accidentalmente las funciones de otro módulo.

    2. Si un módulo hace esto accidentalmente, las funciones originales en la tabla devuelta por el módulo seguirán estando accesibles. Solo mediante el uso de local modname = require "modname" tendrá la garantía de obtener exactamente y solo lo que expuso ese módulo.

    3. Los módulos que incluyen otros módulos no pueden interferir entre sí. La tabla que obtiene de require es siempre lo que almacena el módulo.

  2. Una optimización prematura por alguien que leen "local variables se accede más rápido" y luego decidieron hacer todo lo local.

En general, esta es una buena práctica. Bueno, a menos que sea por # 2.

+0

3. Silenciar un linter que cree que la llamada incorporada tales como rawset o ipairs es malo. – andyn

0

lo hago porque me permite ver las funciones utilizadas por cada uno de mis módulos

Además se le protege de otros que cambian las funciones en el entorno global. Que es una optimización gratuita (prematura) es una bonificación.

+1

No hay nada que impida que su módulo use funciones que no están en esa lista. Entonces, si tienes una necesidad repentina de una función global y te olvidas de agregarla a la lista, entonces estás usando globales. Además, si alguien cambia las funciones globales, es probable que haya una * buena * razón para que lo haga, como monitorear el uso de ciertas funciones y demás. –

+0

Actualmente existe; Tengo un gancho precompromiso que usa luac para buscar códigos de operación GETGLOBAL y avisarme. – daurnimator

+0

Eso es mucho trabajo para implementar algo tan simple. Acaba de utilizar entornos para proporcionar un espacio global específico para cada función, por lo que no podrían afectar a los demás. El libro Programación en Lua te dice todo acerca de cómo hacer esto. –

4

Además de la respuesta de Nicol Bolas, me gustaría añadir a la tercera cuestión:

  • Esto permite a su código que se ejecuta dentro de una caja de arena después de que ha sido cargado.

Si las funciones se han excluido del sandbox y el código se carga desde el sandbox, no funcionará. Pero si el código se carga primero, el sandbox puede llamar al código cargado y poder excluir setmetatable, etc. del sandbox.

0

Otro beneficio sutil: documenta claramente qué variables (funciones, módulos) son importadas por el módulo. Y si está utilizando la instrucción del módulo, impone dichas declaraciones, porque el entorno global es reemplazado (por lo tanto, los globales no están disponibles).

Cuestiones relacionadas