LIMSpec Wiki
Contenidos
Inicio | Discusión | Ayuda e introducción | Módulos disponibles | Zona de pruebas |
- Gran parte de esta página está basada en la presentación en PDF de Tim Starling del hackathon 2012 de Berlín
Bienvenidos a la introducción de Lua con Scribunto, la página de ayuda para los principiantes para aprender a hacer scripts Lua en MediaWiki, y un resumen para programadores más avanzados.
El contenido está destinado principalmente a los desarrolladores familiarizados con las plantillas de MediaWiki. Si eres un experto en plantillas MediaWiki, pero recién llegado a Lua, aprenderáss algunas nuevas instrucciones mágicas. Si tiene experiencia con Lua pero no con plantillas, puede encontrar más información en Ayuda: Plantilla. Tenga en cuenta que algunas cosas de Scribunto no se aplican en la distribución Lua. Si no sabe ni lo uno ni lo otro, encontrará que en la comunidad de Wikipedia hay gente dispuesta a ayudarle.
Introducción para nuevos programadores
Hola mundo
El primer ejercicio típico es saber escribir Hola mundo con el nuevo lenguaje. Cree una página en el espacio de nombres Module. El formato recomendado para pruebas es: Module:Zona de pruebas/nombre de usuario/nombre del módulo. A continuación se explica en detalle el formato de Módulo:Demo:
local p = {} -- Todos los módulos en Wikipedia comienzan definiendo una variable
-- que tendrá todas las funciones accesibles externamente
-- Estas variables pueden tener el nombre que desee
function p.hola(frame) -- Añadir una función al objeto "p"
-- Estas funciones se podrán invocar en otras páginas vía #invoke
-- "frame" contiene los datos que Wikipedia envía a esta función
return '¡Hola mundo!' -- Sale de la función con la información a devolver a la Wikipedia
end -- Final de la función "hola"
return p -- Todos los módulos terminan retornando a la Wikipedia la variable
-- que contiene las funciones
Puede ejecutar en una página wiki, por ejemplo en la misma página de discusión de pruebas:
{{#invoke:mi_módulo|hola}}
Esto invoca el módulo mi_módulo, o como lo haya llamado, y la función exportada "hola" de este módulo. Sustituye la invocación por el texto devuelto por la función. Normalmente las invocaciones se harán desde una plantilla.
Estructuras de control
si ... entonces... | si ... entonces... si no ... | si ... entonces... o si ... si no ... |
if color == 'negro' then
cssColor = '#000'
end
|
if color == 'negro' then
cssColor = '#000'
else
cssColor = color
end
|
if color == 'negro' then
cssColor = '#000'
elseif color == 'blanco' then
cssColor = '#fff'
else
cssColor = color
end
|
Los dos signos ==
comprueban la igualdad. Un solo signo =
es para asignar.
f = 1 -- asigna el valor inicial
for i = 1, 5 do
f = f * i
end
return 'El factorial de 5 es ' .. f
Los dos guiones -
son para añadir comentarios. Los dos puntos seguidos ..
son para concatenar.
Tipos de datos
- Cadena (string), entre comillas simples ('...') o dobles ("..."). Cuidado con los apóstrofos rectos.
- Numérico, con punto decimal.
- Booledana: "true" o "false" (verdadero o falso)
- "Nil" (nulo)
- Tabla
- "Function" (función)
Operadores lógicos
and : Los dos son verdaderos
|
or : Uno, el otro o ambos
|
not : Lo que sigue es falso
|
if tostada and mantequilla then
return 'desayuno'
end
|
if pechuga or muslo then
return 'almuerzo'
end
|
if not hambre then
return 'ayunar'
end
|
Funciones
Declaración de funciones:
sin argumentos | con argumentos | función no local para llamar fuera del módulo |
local function getColour()
return 'azul'
end
|
local function plural(mundo)
return mundo .. 's'
end
|
local p = {}
function p.hola()
return '¡Hola mundo!'
end
return p
|
Para llamar a la función:
colour = getColour()
colorPlural = plural('azul')
Variables
Hay tres tipos de variables: variables globales, variables locales y tablas. Una variable se considera global a no ser que se declare explícitamente con la clave local
. Una variable local es visible dentro del bloque donde ha sido declarada. Una variable declarada sin asignación tiene valor nil (nulo).
x = 10 -- variable global
do -- nuevo bloque
local x = x -- nueva x asignada el valor de la anterior
x = x + 1 -- 11
end -- cierra el bloque y sus variables locales
return x -- 10, la global
|
local x
if ready then
x = 've allí'
end
-- x es 've allí' si
-- ready, si no nil (nulo)
|
Creación de una tabla:
números = {uno = 1, dos = 2, tres = 3}
Acceso a un elemento de la tabla:
return números.dos -- devuelve 2
return números['dos'] -- también devuelve 2
Tabla numerada:
africanFlatbreads = {
'Aish Mehahra',
'Injera',
'Lahoh',
'Ngome'
}
return africanFlatbreads[2] -- devuelve 'Injera'
Iteración de elementos de la tabla:
pairs : par clave/valor en orden aleatorio
|
ipairs : claves numéricas en orden ascendente
|
for nombre, número in pairs(números) do
...
end
|
for index, bread in ipairs(africanFlatbreads) do
...
end
|
Cadenas
# , longitud
|
sub , substring
|
s = 'hola'
return #s -- devuelve 4
|
s = 'hola'
return s:sub(2,3) -- devuelve 'ol'
return s:sub(2) -- devuelve 'ola'
return s:sub(-2) -- devuelve 'la'
|
Introducción para los programadores
Léxico
- El formato de comentarios recuerda SQL
-- comentario en una única línea
--[[
comentario largo
--]]
- Los saltos de línea son ignorados.
- Los puntos y comas para terminar las declaraciones son opcionales y no son recomendados.
Tipos de datos
- Nil (nulo)
- Numèricos, un único formato de punto flotante de precisión doble.
- Strings (cadenas), 8-bit
- Booledanos
- Funciones
- Valores de primera clase.
- Devuelve valores múltiples.
- Los valores de retorno múltiples no están ligados a un tipo de dato.
- Sintaxis anónima
x = function()
...
end
- Tablas
- Implementadas como hashtable
- Usadas para OOP, com Javascript
- Sintaxis literal:
{nombre = valor}
o{a, b, c}
- Acceso con
foo.bar
ofoo['bar']
Operadores
- No igual:
~=
(en lugar de!=
) - Concatenación:
..
- Longitud:
#
- Lógicos:
and
,or
,not
- Exponencial:
^
- Con el significado habitual:
<
,>
,<=
,>=
,==
,+
,-
,*
,/
,%
- Operadores omitidos:
- Ningún operador de asignación com
+=
. Un solo igual=
no es realmente un operador. - Ningún operador bit a bit
- Ningún operador ternario
?:
- Ningún operador de asignación com
- Asignación. Como en BASIC, la asignación es una declaración completa, no una expresión.
Asignación múltiple | Asignación con declaración de variable local |
a, b = c, d
a, b = foo()
|
local a, b = c, d
local a = b, c = d -- así no!
|
Estructuras de control
- Bloque explícito
do
...
end
- Bucles
Bucle con condición inicial | Bucle con condición final |
while cond do
...
end
|
repeat
...
until cond
|
For numèrico | For genèrico |
for i = start, stop do
...
end
|
for i in iterator
...
end
|
- La variable de índice es local del bucle
- If
if cond then
...
elseif cond then
...
else
...
end
Datos
- Variables
- Ámbito léxico, casi idéntico a JavaScript.
- Una variable no determinada es idéntica a una variable nil.
- Ninguna sintaxis especial para suprimir, simplemente x = nil.
- El acceso a variables no definidas no genera errores.
- Objetos
- Hechos de tablas utilizando una variedad de sintaxis, similar a JavaScript.
- Variables de elementos privados implementadas con ámbito léxico, como en JavaScript.
- Punto para métodos estáticos: obj.func ()
- Dos puntos para métodos no estáticos: obj: func ()
- Ejemplo de estilo de construcción de una función:
function newObj()
local private = 1
local obj = {}
function obj:getPrivate()
return private
end
return obj
end
- Metatablas
- Cada tabla puede tener una metatabla asociada
- Proporciona sobrecarga de operadores
- El campo índice de la metatabla se utiliza para la herencia de objetos y la programación basada en prototipos
Interfaz de MediaWiki
Todo el código Lua está en el espacio de nombres Módulo. Hay disponible un editor de código Ace.
Invocación:
{{ #invoke: nombre_módulo | nombre_función | arg1 | arg2 | nombre1 = valor1 }}
Las instancias de invocación son aisladas, los globales definidos en una no están disponibles en otra.
Un módulo es un bloque Lua que devuelve una tabla de exportación. Se proporciona require ()
y librería package
. La función de exportación devuelve una cadena de texto wiki, convirtiendo los valores que no son string. Los valores múltiples de retorno son concatenados.
Métodos frame:
args
:
local nombre1 = frame.args.nombre1
argumentPairs()
:
local t = {}
for nombre, valor in frame:argumentPairs() do
t[name] = value
end
getParent()
: Proporciona acceso al frame superior, por ejemplo los argumentos de la plantilla que llamó#invoke
- Preproceso de texto wiki
frame:preprocess('{{plantilla}}')
- Invocación estructurada de plantilla
frame:expandTemplate{
title = 'plantilla',
args = {foo = foo}}
- Los argumentos son siempre expandidos. No es necesario construir preprocesar las entradas de los argumentos.
Posibilidades en el futuro:
- Invocación interwiki de módulos.
- Otros lenguajes diferentes a Lua.
- Funciones de fecha y hora.
- Acceso directo a funciones parser y variables como
{{PAGENAME}}
,{{#ifexists:}}
.
Depuración de los módulos
Cuando el resultado no es lo que esperábamos de un módulo que hemos creado o retocado, y no acabamos de encontrar el error al repasar el código, entonces querremos ver los valores que toman algunas variables o el flujo del programa (señalando con unas etiquetas las líneas por donde debería seguir el flujo). Este proceso de revisión y corrección es lo que se denomina depuración. Aquí mencionaremos como se puede revisar el código.
Revisión simple
Cuando queremos ver el valor de una variable en un solo punto del módulo:
Modificando el código
Podemos utilizar la función (para cualquier punto del módulo) error()
. Así si queremos saber el valor de var
, añadiremos una línea en el módulo con error(var)
.
Pero en el caso de que sea una tabla (tab
, en lo que sigue) tendremos que utilizar mw.dumpObject(tab)
o, si no tiene tablas anidadas, también se puede utilizar table.concat(tab,', ')
como parámetro de la función error.
Sin modificar el código
Para obtener variables y los valores devueltos por funciones (no locales en ambos casos) podemos utilizar la "consola de depuración de errores" que aparece debajo de todo de la página del módulo (cuando se lo está editando). Para ello utilizaremos mw.log
y mw.logObject
. Veamos su utilidad en un ejemplo descrito a continuación (módulo que se puede encontrar aquí):
local p = {}
p.Hola = 'Hola'
function p.calcula(num)
return num
end
function p.sum_mult(num)
return num + num, num * num
end
function p.mtable(num)
return {num, num+1}
end
return p
Peticiones en la "consola de depuración de errores":
Petición | Valor devuelto |
---|---|
mw.log(p.Hola) | "Hola" |
mw.log(p.calcula(10/2) | 5 |
mw.log(p.sum_mult(3))) | 6 9 |
mw.log(p.mtable(4)) | table |
mw.logObject(p.mtable(4)) |
table#1 {
} |
La consola de edición no guarda las peticiones y se tienen que copiar o reescribir de nuevo en cada modificación del módulo.
Revisión del flujo y de los valores de las variables en diversos puntos
Las funciones del Módulo:SimpleDebug se utilizan para casos como los anteriormente citados o para casos más complejos:
- Cuando una variable o el valor (o valores) devueltos por una función sean locales.
- Cuando interese los valores que toma una variable (o varias) en varios puntos (incluidos en módulos requeridos).
- Para ver si el flujo del programa pasa por un punto (al que etiqueta).
- Para limitar el número de valores devueltos dentro de un bucle o establecer condiciones para que sea efectivo el registro de dichos valores.
Para saber más
- MediaWiki y Scribunto:
- Scribunto/Lua referencia manual (en inglés)
- Recursos externos:
- Programming in Lua (en inglés)
- Manual de referencia ver 5.1
- Manual de referencia ver 5.2 (en inglés)
- Lua-users (en inglés)