Luan / Documentación - software reaccionario por fschmidt

Manual de Referencia de Luan

Copyright original © 2015 Lua.org, PUC-Rio. Disponible libremente bajo los términos de la licencia de Lua. Modificado para Luan.


Contenido


Introducción

contenidos

Luan es un lenguaje de programación de alto nivel basado en Lua. Una gran fortaleza de Lua es su simplicidad y Luan lleva esto aún más lejos, siendo incluso más simple que Lua. El objetivo es proporcionar un lenguaje de programación simple para el programador ocasional con la menor cantidad de conceptos posible para que uno pueda aprender rápidamente el lenguaje y luego entender fácilmente cualquier código escrito en Luan.

Luan está implementado en Java y está estrechamente acoplado con Java. Por lo tanto, es un gran lenguaje de scripting para programadores de Java.

A diferencia de Lua, que está destinado a ser embebido, Luan está destinado a ser un lenguaje de scripting completo. Esto se logra no añadiendo características a Luan, sino proporcionando un conjunto completo de librerías.

Conceptos Básicos

contenido

Esta sección describe los conceptos básicos del lenguaje.

Valores y Tipos

contenido

Luan es un lenguaje de tipado dinámico. Esto significa que las variables no tienen tipos; solo los valores los tienen. No hay definiciones de tipo en el lenguaje. Todos los valores llevan su propio tipo.

Todos los valores en Luan son valores de primera clase. Esto significa que todos los valores pueden ser almacenados en variables, pasados como argumentos a otras funciones y devueltos como resultados.

Hay ocho tipos básicos en Luan: nil, booleano, número, cadena, binario, función, java, y tabla. Nil es el tipo del valor nil, cuya propiedad principal es ser diferente de cualquier otro valor; normalmente representa la ausencia de un valor útil. Nil se implementa como el valor Java null. Booleano es el tipo de los valores false y true. Booleano se implementa como la clase Java Boolean. Número representa tanto números enteros como números reales (de punto flotante). Número se implementa como la clase Java Number. Cualquier subclase de Java de Number está permitida y esto es invisible para el usuario de Luan. Las operaciones en números siguen las mismas reglas de la implementación subyacente de Java. Cadena se implementa como la clase Java String. Binario se implementa como el tipo Java byte[].

Luan puede llamar (y manipular) funciones escritas en Luan y funciones escritas en Java (ver Llamadas a Funciones). Ambas están representadas por el tipo función.

El tipo java se proporciona para permitir que objetos Java arbitrarios sean almacenados en variables de Luan. Un valor java es un objeto Java que no es uno de los tipos estándar de Luan. Los valores Java no tienen operaciones predefinidas en Luan, excepto la asignación y la prueba de identidad. Los valores Java son útiles cuando el acceso a Java está habilitado en Luan.

El tipo tabla implementa arreglos asociativos, es decir, arreglos que pueden ser indexados no solo con números, sino con cualquier valor de Luan excepto nil. Las tablas pueden ser heterogéneas; es decir, pueden contener valores de todos los tipos (excepto nil). Cualquier clave con valor nil no se considera parte de la tabla. Por el contrario, cualquier clave que no sea parte de una tabla tiene un valor asociado nil.

Las tablas son el único mecanismo de estructuración de datos en Luan; pueden ser usadas para representar arreglos ordinarios, secuencias, tablas de símbolos, conjuntos, registros, gráficos, árboles, etc. Para representar registros, Luan usa el nombre del campo como un índice. El lenguaje soporta esta representación proporcionando a.name como azúcar sintáctica para a["name"]. Hay varias formas convenientes de crear tablas en Luan (ver Constructores de Tablas).

Usamos el término secuencia para denotar una tabla donde el conjunto de todas las claves numéricas positivas es igual a {1..n} para algún entero no negativo n, que se llama la longitud de la secuencia (ver El Operador de Longitud).

Al igual que los índices, los valores de los campos de la tabla pueden ser de cualquier tipo. En particular, debido a que las funciones son valores de primera clase, los campos de la tabla pueden contener funciones. Por lo tanto, las tablas también pueden llevar métodos (ver Definiciones de Funciones).

La indexación de tablas sigue definición de igualdad cruda en el lenguaje. Las expresiones a[i] y a[j] denotan el mismo elemento de tabla si y solo si i y j son crudos iguales (es decir, iguales sin metamétodos). En particular, los flotantes con valores integrales son iguales a sus respectivos enteros (por ejemplo, 1.0 == 1).

Los valores de Luan son objetos: las variables no contienen realmente valores, sólo referencias a ellos. La asignación, el paso de parámetros y los retornos de funciones siempre manipulan referencias a valores; estas operaciones no implican ningún tipo de copia.

La función de librería Luan.type devuelve una cadena que describe el tipo de un valor dado.

Entornos

contenido

El entorno de un fragmento comienza con solo una variable local: require. Esta función se usa para cargar y acceder a librerías y otros módulos. Todas las demás variables deben ser añadidas al entorno usando declaraciones locales.

Como se discutirá en Variables y Asignación, cualquier referencia a un nombre libre (es decir, un nombre no vinculado a ninguna declaración) var puede ser traducida sintácticamente a _ENV.var si _ENV está definido.

Manejo de Errores

contenido

El código Luan puede generar explícitamente un error llamando a la error función. Si necesitas capturar errores en Luan, puedes usar la Declaración Try.

Siempre que hay un error, una tabla de errores se propaga con información sobre el error. Ver Luan.new_error.

Metatablas y Metamétodos

contenido

Cada tabla en Luan puede tener una metatabla. Esta metatabla es una tabla Luan ordinaria que define el comportamiento del valor original bajo ciertas operaciones especiales. Puedes cambiar varios aspectos del comportamiento de las operaciones sobre un valor estableciendo campos específicos en su metatabla. Por ejemplo, cuando una tabla es el operando de una suma, Luan busca una función en el campo "__add" de la metatabla de la tabla. Si encuentra una, Luan llama a esta función para realizar la suma.

Las claves en una metatabla se derivan de los nombres de eventos; los valores correspondientes se llaman metamétodos. En el ejemplo anterior, el evento es "add" y el metamétodo es la función que realiza la suma.

Puedes consultar la metatabla de cualquier tabla usando la función get_metatable.

Puedes reemplazar la metatabla de las tablas usando la función set_metatable.

Una metatabla controla cómo se comporta una tabla en operaciones aritméticas, operaciones bit a bit, comparaciones de orden, concatenación, operación de longitud, llamadas e indexación.

A continuación se da una lista detallada de eventos controlados por metatablas. Cada operación se identifica por su nombre de evento correspondiente. La clave para cada evento es una cadena con su nombre precedido por dos guiones bajos, '__'; por ejemplo, la clave para la operación "add" es la cadena "__add". Ten en cuenta que las consultas para metamétodos son siempre crudas; el acceso a un metamétodo no invoca otros metamétodos. Puedes emular cómo Luan consulta un metamétodo para un objeto obj con el siguiente código:

raw_get(get_metatable(obj) or {}, "__" .. event_name)

Aquí están los eventos:

Recolección de Basura

contenido

Luan usa la recolección de basura de Java.

El Lenguaje

contenido

Esta sección describe la léxis, la sintaxis y la semántica de Luan. En otras palabras, esta sección describe qué tokens son válidos, cómo pueden combinarse, y qué significan sus combinaciones.

Los constructos del lenguaje se explicarán usando la notación BNF extendida habitual, en la cual {a} significa 0 o más a's, y [a] significa un a opcional. Los no terminales se muestran como no-terminal, las palabras clave se muestran como kword, y otros símbolos terminales se muestran como ‘=’. La sintaxis completa de Luan se puede encontrar en §9 al final de este manual.

Convenciones Léxicas

contenido

Luan ignora espacios y comentarios entre elementos léxicos (tokens), excepto como delimitadores entre nombres y palabras clave. Luan considera el final de una línea como el final de una declaración. Esto detecta errores y fomenta la legibilidad. Si deseas continuar una declaración en otra línea, puedes usar una barra invertida seguida de un salto de línea que se tratará como espacio en blanco.

Nombres (también llamados identificadores) en Luan pueden ser cualquier cadena de letras, dígitos y guiones bajos, no comenzando con un dígito. Los identificadores se usan para nombrar variables, campos de tabla y etiquetas.

Las siguientes palabras clave están reservadas y no pueden usarse como nombres:

and break catch continue do else elseif end_do end_for end_function end_if end_try end_while false finally for function if in local nil not or repeat return then true try until while

Luan es un lenguaje sensible a mayúsculas y minúsculas: and es una palabra reservada, pero And y AND son dos nombres diferentes y válidos.

Las siguientes cadenas denotan otros tokens:

+ - * / // % ^ # & ~ | == ~= <= >= < > = ( ) { } [ ] ; , . .. ... %> <% <%=

Cadenas literales pueden estar delimitadas por comillas simples o dobles coincidentes, y pueden contener las siguientes secuencias de escape similares a C: '\a' (campana), '\b' (retroceso), '\f' (salto de formulario), '\n' (nueva línea), '\r' (retorno de carro), '\t' (tabulación horizontal), '\v' (tabulación vertical), '\\' (barra invertida), '\"' (comillas [comillas dobles]), y '\'' (apóstrofo [comillas simples]). Una barra invertida seguida de una nueva línea real resulta en una nueva línea en la cadena. La secuencia de escape '\z' omite el siguiente tramo de caracteres de espacio en blanco, incluyendo saltos de línea; es particularmente útil para dividir e indentar una cadena literal larga en varias líneas sin agregar los saltos de línea y espacios en el contenido de la cadena.

Luan puede especificar cualquier carácter en una cadena literal por su valor numérico. Esto se puede hacer con la secuencia de escape \xXX, donde XX es una secuencia de exactamente dos dígitos hexadecimales, o con la secuencia de escape \uXXXX, donde XXXX es una secuencia de exactamente cuatro dígitos hexadecimales, o con la secuencia de escape \ddd, donde ddd es una secuencia de hasta tres dígitos decimales. (Tenga en cuenta que si una secuencia de escape decimal debe ser seguida por un dígito, debe expresarse usando exactamente tres dígitos.)

Las cadenas literales también pueden definirse usando un formato largo delimitado por corchetes largos. Definimos un corchete largo de apertura de nivel n como un corchete cuadrado de apertura seguido de n signos de igual seguidos de otro corchete cuadrado de apertura. Entonces, un corchete largo de apertura de nivel 0 se escribe como [[, un corchete largo de apertura de nivel 1 se escribe como [=[, y así sucesivamente. Un corchete largo de cierre se define de manera similar; por ejemplo, un corchete largo de cierre de nivel 4 se escribe como ]====]. Un literal largo comienza con un corchete largo de apertura de cualquier nivel y termina en el primer corchete largo de cierre del mismo nivel. Puede contener cualquier texto excepto un corchete de cierre del mismo nivel. Los literales en esta forma entre corchetes pueden extenderse por varias líneas, no interpretan ninguna secuencia de escape, y ignoran los corchetes largos de cualquier otro nivel. Cualquier tipo de secuencia de fin de línea (retorno de carro, nueva línea, retorno de carro seguido de nueva línea, o nueva línea seguida de retorno de carro) se convierte en una nueva línea simple.

Cualquier carácter en una cadena literal no afectado explícitamente por las reglas anteriores se representa a sí mismo. Sin embargo, Luan abre archivos para analizar en modo texto, y las funciones de archivo del sistema pueden tener problemas con algunos caracteres de control. Por lo tanto, es más seguro representar datos no textuales como un literal entre comillas con secuencias de escape explícitas para caracteres no textuales.

Por conveniencia, cuando el corchete largo de apertura es seguido inmediatamente por una nueva línea, la nueva línea no se incluye en la cadena. Como ejemplo las cinco cadenas literales a continuación denotan la misma cadena:

a = 'alo\n123"' a = "alo\n123\"" a = '\97lo\10\04923"' a = [[alo 123"]] a = [==[ alo 123"]==]

Una constante numérica (o número) puede escribirse con una parte fraccionaria opcional y un exponente decimal opcional, marcado por una letra 'e' o 'E'. Luan también acepta constantes hexadecimales, que comienzan con 0x o 0X. Las constantes hexadecimales también aceptan una parte fraccionaria opcional más un exponente binario opcional, marcado por una letra 'p' o 'P'. Una constante numérica con un punto fraccionario o un exponente denota un flotante; de lo contrario, denota un entero. Ejemplos de constantes enteras válidas son

3   345   0xff   0xBEBADA

Ejemplos de constantes flotantes válidas son

3.0     3.1416     314.16e-2     0.31416E1     34e1
0x0.1E  0xA23p-4   0X1.921FB54442D18P+1

Un comentario comienza con un doble guion (--) en cualquier lugar fuera de una cadena. Si el texto inmediatamente después de -- no es un corchete largo de apertura, el comentario es un comentario corto, que se extiende hasta el final de la línea. De lo contrario, es un comentario largo, que se extiende hasta el corchete largo de cierre correspondiente. Los comentarios largos se utilizan con frecuencia para deshabilitar código temporalmente.

Variables

contenido

Las variables son lugares que almacenan valores. Hay tres tipos de variables en Luan: variables globales, variables locales y campos de tabla.

Un solo nombre puede denotar una variable global o una variable local (o un parámetro formal de una función, que es un tipo particular de variable local):

var ::= Name

Name denota identificadores, como se define en Convenciones Léxicas.

Las variables locales son de ámbito léxico: las variables locales pueden ser accedidas libremente por funciones definidas dentro de su ámbito (ver Reglas de Visibilidad).

Antes de la primera asignación a una variable, su valor es nil.

Los corchetes se usan para indexar una tabla:

var ::= prefixexp ‘[’ exp ‘]

El significado de los accesos a campos de tabla puede cambiarse mediante metatablas. Un acceso a una variable indexada t[i] es equivalente a una llamada gettable_event(t,i). (Ver Metatablas y Metamétodos para una descripción completa de la función gettable_event. Esta función no está definida ni es invocable en Luan. La usamos aquí solo con fines explicativos.)

La sintaxis var.Name es solo azúcar sintáctico para var["Name"]:

var ::= prefixexp ‘.’ Name

Las variables globales no están disponibles por defecto. Para habilitar la variable global, debes definir _ENV como una variable local cuyo valor es una tabla. Si _ENV no está definido, entonces un nombre de variable no reconocido producirá un error de compilación. Si _ENV está definido, entonces un acceso a un nombre de variable no reconocido se considerará una variable global. Entonces, un acceso a la variable global x es equivalente a _ENV.x. Debido a la forma en que se compilan los fragmentos, _ENV nunca es un nombre global (ver Entornos).

Declaraciones

contenido

Luan admite un conjunto casi convencional de declaraciones, similar a las de Pascal o C. Este conjunto incluye asignaciones, estructuras de control, llamadas a funciones, y declaraciones de variables.

Bloques

contenido

Un bloque es una lista de declaraciones, que se ejecutan secuencialmente:

block ::= {stat}

Luan tiene declaraciones vacías que te permiten separar declaraciones con punto y coma, iniciar un bloque con un punto y coma o escribir dos puntos y coma en secuencia:

stat ::= ‘;

Un bloque puede delimitarse explícitamente para producir una sola declaración:

stat ::= do block end_do
end_do ::= end_do | end

Los bloques explícitos son útiles para controlar el ámbito de las declaraciones de variables. Los bloques explícitos también se utilizan a veces para agregar una declaración return en el medio de otro bloque (ver Estructuras de Control).

Fragmentos

contenido

La unidad de compilación de Luan se llama fragmento. Sintácticamente, un fragmento es simplemente un bloque:

chunk ::= block

Luan maneja un fragmento como el cuerpo de una función anónima con un número variable de argumentos (ver Definiciones de Funciones). Como tal, los fragmentos pueden definir variables locales, recibir argumentos y devolver valores.

Un fragmento puede almacenarse en un archivo o en una cadena dentro del programa anfitrión. Para ejecutar un fragmento, Luan primero carga el mismo, compilando el código del fragmento, y luego Luan ejecuta el código compilado.

Asignación

contenido

Luan permite múltiples asignaciones. Por lo tanto, la sintaxis para la asignación define una lista de variables en el lado izquierdo y una lista de expresiones en el lado derecho. Los elementos en ambas listas están separados por comas:

stat ::= varlist ‘=’ explist
varlist ::= var {‘,’ var}
explist ::= exp {‘,’ exp}

Las expresiones se discuten en Expresiones.

Antes de la asignación, la lista de valores se ajusta a la longitud de la lista de variables. Si hay más valores de los necesarios, los valores en exceso se descartan. Si hay menos valores de los necesarios, la lista se extiende con tantos nil como sea necesario. Si la lista de expresiones termina con una llamada a función, entonces todos los valores devueltos por esa llamada ingresan a la lista de valores, antes del ajuste (excepto cuando la llamada está encerrada entre paréntesis; ver Expresiones).

La declaración de asignación primero evalúa todas sus expresiones y solo entonces se realizan las asignaciones. Así que el código

i = 3 i, a[i] = i+1, 20

asigna a[3] a 20, sin afectar a[4] porque el i en a[i] se evalúa (a 3) ante de que se asigne 4. De manera similar, la línea

x, y = y, x

intercambia los valores de x y y, y

x, y, z = y, z, x

permuta cíclicamente los valores de x, y y z.

El significado de las asignaciones a variables globales y campos de tabla puede cambiarse mediante metatablas. Una asignación a una variable indexada t[i] = val es equivalente a settable_event(t,i,val). (Ver Metatablas y Metamétodos para una descripción completa de la función settable_event. Esta función no está definida ni es invocable en Luan. La usamos aquí solo con fines explicativos.)

Una asignación a un nombre global x = val es equivalente a la asignación _ENV.x = val (ver Entornos). Los nombres globales solo están disponibles cuando _ENV está definido.

Estructuras de Control

contenido

Las estructuras de control if, while y repeat tienen el significado habitual y sintaxis familiar:

stat ::= while exp do block end_while
stat ::= repeat block until exp
stat ::= if exp then block {elseif exp then block} [else block] end_if
end_while ::= end_while | end
end_if ::= end_if | end

Luan también tiene una declaración for (ver Declaración For).

La expresión de condición de una estructura de control debe ser un booleano. Cualquier otro tipo de valor producirá un error. Esto ayuda a detectar errores y hace que el código sea más legible.

En el bucle repeatuntil, el bloque interno no termina en la palabra clave until, sino solo después de la condición. Por lo tanto, la condición puede referirse a variables locales declaradas dentro del bloque del bucle.

La declaración break termina la ejecución de un bucle while, repeat o for, saltando a la siguiente declaración después del bucle:

stat ::= break

Un break termina el bucle más interno.

La declaración continue salta al comienzo de un bucle while, repeat o for para la siguiente iteración, saltando la ejecución de declaraciones dentro del cuerpo del bucle para la iteración actual:

stat ::= continue

La declaración return se usa para devolver valores de una función o un fragmento (que es una función anónima). Las funciones pueden devolver más de un valor, así que la sintaxis para la declaración return es

stat ::= return [explist] [‘;’]

Declaración For

contenido

La declaración for funciona sobre funciones, llamadas iteradores. En cada iteración, la función iteradora se llama para producir un nuevo valor, deteniéndose cuando este nuevo valor es nil. El bucle for tiene la siguiente sintaxis:

stat ::= for namelist in exp do block end_for
namelist ::= Name {‘,’ Name}
end_for ::= end_for | end

Una declaración for como

for var_1, ···, var_n in exp do block end

es equivalente al código:

do local f = exp while true do local var_1, ···, var_n = f() if var_1 == nil then break end block end end

Nota lo siguiente:

Declaración Try

contenido

La declaración try tiene la misma semántica que en Java.

stat ::= try block [catch Name block] [finally block] end_try
end_try ::= end_try | end

Llamadas a Funciones como Declaraciones

contenido

Para permitir posibles efectos secundarios, las llamadas a funciones pueden ejecutarse como declaraciones:

stat ::= functioncall

En este caso, todos los valores devueltos se descartan. Las llamadas a funciones se explican en Llamadas a Funciones.

Declaración Lógica

contenido

Expresiones lógicas pueden ser declaraciones. Esto es útil en casos como este:

x==5 or error "x should be 5"

Declaraciones Locales

contenido

Las variables locales pueden declararse en cualquier lugar dentro de un bloque. La declaración puede incluir una asignación inicial:

stat ::= local namelist [‘=’ explist]

Si está presente, una asignación inicial tiene la misma semántica de una asignación múltiple (ver Asignación). De lo contrario, todas las variables se inicializan con nil.

Un fragmento también es un bloque (ver Fragmentos), y por lo tanto las variables locales pueden declararse en un fragmento fuera de cualquier bloque explícito.

Las reglas de visibilidad para las variables locales se explican en Reglas de Visibilidad.

Declaraciones de Plantilla

contenido

Las declaraciones de plantilla proporcionan el equivalente completo de JSP pero de manera general. Las declaraciones de plantilla escriben en la salida estándar. Por ejemplo:

local name = "Bob" %> Hello <%= name %>! Bye <%= name %>. <%

es equivalente al código:

local name = "Bob" require("luan:Io.luan").stdout.write( "Hello ", name , "!\nBye ", name , ".\n" )

Expresiones

contenido

Las expresiones básicas en Luan son las siguientes:

exp ::= prefixexp
exp ::= nil | false | true
exp ::= Numeral
exp ::= LiteralString
exp ::= functiondef
exp ::= tableconstructor
exp ::= ‘...’
exp ::= exp binop exp
exp ::= unop exp
prefixexp ::= var | functioncall | ‘(’ exp ‘)

Los números y las cadenas literales se explican en Convenciones Léxicas; las variables se explican en Variables; las definiciones de funciones se explican en Definiciones de Funciones; las llamadas a funciones se explican en Llamadas a Funciones; los constructores de tablas se explican en Constructores de Tablas. Las expresiones vararg, denotadas por tres puntos ('...'), solo pueden usarse cuando directamente dentro de una función vararg; se explican en Definiciones de Funciones.

Los operadores binarios comprenden operadores aritméticos (ver Operadores Aritméticos), operadores relacionales (ver Operadores Relacionales), operadores lógicos (ver Operadores Lógicos), y el operador de concatenación (ver Concatenación). Los operadores unarios comprenden el menos unario (ver Operadores Aritméticos), el not lógico unario (ver Operadores Lógicos), y el operador de longitud unario (ver El Operador de Longitud).

Tanto las llamadas a funciones como las expresiones vararg pueden resultar en múltiples valores. Si una llamada a función se usa como una declaración (ver Llamadas a Funciones como Declaraciones), entonces su lista de retorno se ajusta a cero elementos, descartando así todos los valores devueltos. Si una expresión se usa como el último (o el único) elemento de una lista de expresiones, entonces no se hace ningún ajuste (a menos que la expresión esté encerrada entre paréntesis). En todos los demás contextos, Luan ajusta la lista de resultados a un elemento, ya sea descartando todos los valores excepto el primero o agregando un solo nil si no hay valores.

Aquí hay algunos ejemplos:

f()                -- ajustado a 0 resultados
g(f(), x)          -- f() se ajusta a 1 resultado
g(x, f())          -- g obtiene x más todos los resultados de f()
a,b,c = f(), x     -- f() se ajusta a 1 resultado (c obtiene nil)
a,b = ...          -- a obtiene el primer parámetro vararg, b obtiene
-- el segundo (tanto a como b pueden obtener nil si no
-- hay un parámetro vararg correspondiente)

a,b,c = x, f()     -- f() se ajusta a 2 resultados
a,b,c = f()        -- f() se ajusta a 3 resultados
return f()         -- devuelve todos los resultados de f()
return ...         -- devuelve todos los parámetros vararg recibidos
return x,y,f()     -- devuelve x, y, y todos los resultados de f()
{f()}              -- crea una lista con todos los resultados de f()
{...}              -- crea una lista con todos los parámetros vararg
{f(), nil}         -- f() se ajusta a 1 resultado

Cualquier expresión encerrada entre paréntesis siempre resulta en solo un valor. Así, (f(x,y,z)) es siempre un solo valor, incluso si f devuelve varios valores. (El valor de (f(x,y,z)) es el primer valor devuelto por f o nil si f no devuelve ningún valor.)

Operadores Aritméticos

contenido

Luan admite los siguientes operadores aritméticos:

La adición, sustracción, multiplicación, división y menos unario son los mismos que estos operadores en Java. La exponenciación utiliza la función Math.pow de Java.

La división de piso (//) es una división que redondea el cociente hacia menos infinito, es decir, el piso de la división de sus operandos.

El módulo se define como el resto de una división que redondea el cociente hacia menos infinito (división de piso). (El operador de módulo de Java no se usa.)

Coerciones y Conversiones

contenido

Luan generalmente evita las conversiones automáticas. La concatenación de cadenas convierte automáticamente todos sus argumentos en cadenas.

Luan proporciona funciones de librería para conversiones de tipo explícitas.

Operadores Relacionales

contenido

Luan admite los siguientes operadores relacionales:

Estos operadores siempre resultan en false o true.

La igualdad (==) primero compara el tipo de sus operandos. Si los tipos son diferentes, entonces el resultado es false. De lo contrario, se comparan los valores de los operandos. Las cadenas, números y valores binarios se comparan de la manera obvia (por valor).

Las tablas se comparan por referencia: dos objetos se consideran iguales solo si son el mismo objeto. Cada vez que creas una nueva tabla, es diferente de cualquier tabla existente previamente. Las clausuras también se comparan por referencia.

Puedes cambiar la forma en que Luan compara tablas usando el metamétodo "eq" (ver Metatablas y Metamétodos).

Los valores de Java se comparan por igualdad con el método equals de Java.

Las comparaciones de igualdad no convierten cadenas en números o viceversa. Por lo tanto, "0"==0 evalúa a false, y t[0] y t["0"] denotan diferentes entradas en una tabla.

El operador ~= es exactamente la negación de la igualdad (==).

Los operadores de orden funcionan de la siguiente manera. Si ambos argumentos son números, entonces se comparan siguiendo la regla habitual para operaciones binarias. De lo contrario, si ambos argumentos son cadenas, entonces sus valores se comparan según la configuración regional actual. De lo contrario, Luan intenta llamar al metamétodo "lt" o "le" (ver Metatablas y Metamétodos). Una comparación a > b se traduce a b < a y a >= b se traduce a b <= a.

Operadores Lógicos

contenido

Los operadores lógicos en Luan son and, or y not. Los operadores and y or consideran tanto false como nil como falsos y cualquier otra cosa como verdadera. Al igual que las estructuras de control (ver Estructuras de Control), el operador not requiere un valor booleano.

El operador de negación not siempre devuelve false o true. El operador de conjunción and devuelve su primer argumento si este valor es false o nil; de lo contrario, and devuelve su segundo argumento. El operador de disyunción or devuelve su primer argumento si este valor es diferente de nil y false; de lo contrario, or devuelve su segundo argumento. Tanto and como or utilizan evaluación de cortocircuito; es decir, el segundo operando se evalúa solo si es necesario. Aquí hay algunos ejemplos:

10 or 20            --> 10
10 or error()       --> 10
nil or "a"          --> "a"
nil and 10          --> nil
false and error()   --> false
false and nil       --> false
false or nil        --> nil
10 and 20           --> 20

(En este manual, --> indica el resultado de la expresión anterior.)

Concatenación

contenido

El operador de concatenación de cadenas en Luan es denotado por dos puntos (".."). Todos los operandos se convierten en cadenas.

El Operador de Longitud

contenido

El operador de longitud está denotado por el operador unario de prefijo #. La longitud de una cadena es su número de caracteres. La longitud de un binario es su número de bytes.

Un programa puede modificar el comportamiento del operador de longitud para cualquier tabla a través del metamétodo __len (ver Metatablas y Metamétodos).

A menos que se proporcione un metamétodo __len, la longitud de una tabla t se define como el número de elementos en secuencia, es decir, el tamaño del conjunto de sus claves numéricas positivas es igual a {1..n} para algún entero no negativo n. En ese caso, n es su longitud. Tenga en cuenta que una tabla como

{10, 20, nil, 40}

tiene una longitud de 2, porque esa es la última clave en secuencia.

Precedencia

contenido

La precedencia de operadores en Luan sigue la tabla a continuación, de menor a mayor prioridad:

or
and
<     >     <=    >=    ~=    ==
..
+     -
*     /     %
operadores unarios (not   #     -)
^

Como de costumbre, puedes usar paréntesis para cambiar las precedencias de una expresión. Los operadores de concatenación ('..') y exponenciación ('^') son asociativos a la derecha. Todos los demás operadores binarios son asociativos a la izquierda.

Constructores de Tablas

contenido

Los constructores de tablas son expresiones que crean tablas. Cada vez que se evalúa un constructor, se crea una nueva tabla. Un constructor puede usarse para crear una tabla vacía o para crear una tabla e inicializar algunos de sus campos. La sintaxis general para los constructores es

tableconstructor ::= ‘{’ fieldlist ‘}’
fieldlist ::= [field] {fieldsep [field]}
field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
fieldsep ::= ‘,’ | ‘;’ | end_of_line

Cada campo de la forma [exp1] = exp2 agrega a la nueva tabla una entrada con clave exp1 y valor exp2. Un campo de la forma name = exp es equivalente a ["name"] = exp. Finalmente, los campos de la forma exp son equivalentes a [i] = exp, donde i son enteros consecutivos comenzando con 1. Los campos en los otros formatos no afectan este conteo. Por ejemplo,

a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

es equivalente a

do local t = {} t[f(1)] = g t[1] = "x" -- 1er exp t[2] = "y" -- 2do exp t.x = 1 -- t["x"] = 1 t[3] = f(x) -- 3er exp t[30] = 23 t[4] = 45 -- 4to exp a = t end

El orden de las asignaciones en un constructor es indefinido. (Este orden solo sería relevante cuando hay claves repetidas.)

Si el último campo en la lista tiene la forma exp y la expresión es una llamada a función o una expresión vararg, entonces todos los valores devueltos por esta expresión ingresan a la lista consecutivamente (ver Llamadas a Funciones).

La lista de campos puede tener un separador final opcional, como una conveniencia para el código generado por máquina.

Llamadas a Funciones

contenido

Una llamada a función en Luan tiene la siguiente sintaxis:

functioncall ::= prefixexp args

En una llamada a función, primero se evalúan prefixexp y args. El valor de prefixexp debe tener tipo función. Esta función se llama con los argumentos dados.

Los argumentos tienen la siguiente sintaxis:

args ::= ‘(’ [explist] ‘)’
args ::= tableconstructor
args ::= LiteralString

Todas las expresiones de argumento se evalúan antes de la llamada. Una llamada de la forma f{fields} es azúcar sintáctico para f({fields}); es decir, la lista de argumentos es una sola nueva tabla. Una llamada de la forma f'string' (o f"string" o f[[string]]) es azúcar sintáctico para f('string'); es decir, la lista de argumentos es una sola cadena literal.

Definiciones de Funciones

contenido

La sintaxis para la definición de funciones es

functiondef ::= function funcbody
funcbody ::= ‘(’ [parlist] ‘)’ block end_function
end_function ::= end_function | end

El siguiente azúcar sintáctico simplifica las definiciones de funciones:

stat ::= function funcname funcbody
stat ::= local function Name funcbody
funcname ::= Name {‘.’ Name} [‘:’ Name]

La declaración

function f () body end

se traduce a

f = function () body end

La declaración

function t.a.b.c.f () body end

se traduce a

t.a.b.c.f = function () body end

La declaración

local function f () body end

se traduce a

local f; f = function () body end

no a

local f = function () body end

(Esto solo hace una diferencia cuando el cuerpo de la función contiene referencias a f.)

Una definición de función es una expresión ejecutable, cuya valor tiene tipo función. Cuando Luan precompila un fragmento, todos sus cuerpos de función también se precompilan. Luego, cada vez que Luan ejecuta la definición de la función, la función es instanciada (o cerrada). Esta instancia de función (o clausura) es el valor final de la expresión.

Los parámetros actúan como variables locales que son inicializadas con los valores de los argumentos:

parlist ::= namelist [‘,’ ‘...’] | ‘...

Cuando se llama a una función, la lista de argumentos se ajusta a la longitud de la lista de parámetros si la lista es demasiado corta, a menos que la función sea una función vararg, que se indica con tres puntos ('...') al final de su lista de parámetros. Una función vararg no ajusta su lista de argumentos; en cambio, recopila todos los argumentos adicionales y los suministra a la función a través de una expresión vararg, que también se escribe como tres puntos. El valor de esta expresión es una lista de todos los argumentos adicionales reales, similar a una función con múltiples resultados. Si una expresión vararg se usa dentro de otra expresión o en el medio de una lista de expresiones, entonces su lista de retorno se ajusta a un elemento. Si la expresión se usa como el último elemento de una lista de expresiones, entonces no se hace ningún ajuste (a menos que esa última expresión esté encerrada entre paréntesis).

Como ejemplo, considera las siguientes definiciones:

function f(a, b) end
function g(a, b, ...) end
function r() return 1,2,3 end

Entonces, tenemos el siguiente mapeo de argumentos a parámetros y a la expresión vararg:

CALL             PARAMETERS

f(3)             a=3, b=nil
f(3, 4)          a=3, b=4
f(3, 4, 5)       error en tiempo de ejecución
f(r(), 10)       error en tiempo de ejecución
f(r())           error en tiempo de ejecución

g(3)             a=3, b=nil, ... -->  (nada)
g(3, 4)          a=3, b=4,   ... -->  (nada)
g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
g(5, r())        a=5, b=1,   ... -->  2  3

Los resultados se devuelven usando la declaración return (ver Estructuras de Control). Si el control llega al final de una función sin encontrar una declaración return, entonces la función devuelve sin resultados.

Comillas Invertidas

contenido

Un bloque entre comillas invertidas se ejecuta y luego lo que se envió a la salida estándar se devuelve como una cadena. Ejemplos:

local s = `%>1 + 1 = <%=1+1%><%` local s = ` fn(whatever) ` local s = `%> ... <%`

Las comillas invertidas complementan declaraciones de plantilla.

Reglas de Visibilidad

contenido

Luan es un lenguaje de ámbito léxico. El ámbito de una variable local comienza en la primera declaración después de su declaración y dura hasta la última declaración no vacía del bloque más interno que incluye la declaración. Considera el siguiente ejemplo:

local x = 10 -- global al módulo do -- nuevo bloque local x = x -- nuevo 'x', con valor 10 print(x) --> 10 x = x+1 do -- otro bloque local x = x+1 -- otro 'x' print(x) --> 12 end print(x) --> 11 end print(x) --> 10 (el global)

Observa que, en una declaración como local x = x, el nuevo x que se está declarando aún no está en el ámbito, y por lo tanto el segundo x se refiere a la variable externa.

Debido a las reglas de ámbito léxico, las variables locales pueden ser accedidas libremente por funciones definidas dentro de su ámbito. Una variable local utilizada por una función interna se llama una upvalue, o variable local externa, dentro de la función interna.

Observa que cada ejecución de una declaración local define nuevas variables locales. Considera el siguiente ejemplo:

local a = {} local x = 20 for i=1,10 do local y = 0 a[i] = function () y=y+1; return x+y end end

El bucle crea diez clausuras (es decir, diez instancias de la función anónima). Cada una de estas clausuras usa una variable y diferente, mientras que todas comparten el mismo x.

Librerías Estándar

contenido

Las librerías estándar de Luan proporcionan funciones útiles que están implementadas tanto en Java como en el propio Luan. Cómo se implementa cada función no debería importar al usuario. Algunas de estas funciones proporcionan servicios esenciales al lenguaje (por ejemplo, type y get_metatable); otras proporcionan acceso a servicios "externos" (por ejemplo, I/O).

Entorno Predeterminado

contenido

Esto se proporciona por defecto como una variable local para cualquier código Luan como se describe en Entornos.

require (mod_uri)

contenido

Uso de ejemplo:

local Table = require "luan:Table.luan"

Podría definirse como:

local function require(mod_name) return Package.load(mod_name) or Luan.error("module '"..mod_name.."' not found") end

Un caso especial es:

require "java"

Esto habilita Java en el bloque actual si ese bloque tiene permiso para usar Java. Si el bloque no tiene permiso para usar Java, entonces se lanza un error.

Funciones Básicas

contenido

Incluye esta librería por:

local Luan = require "luan:Luan.luan"

La librería básica proporciona funciones básicas a Luan que no dependen de otras librerías.

Luan.arg

contenido

Si Luan se ejecutó desde la línea de comandos, entonces esta es una lista de los argumentos de la línea de comandos. Por ejemplo, si uno ejecuta Luan así:

luan t.luan a b c

Entonces Luan.arg contendrá:

{ [0] = "t.luan" [1] = "a" [2] = "b" [3] = "c" }

Y por supuesto #Luan.arg será 3.

Luan.do_file ([uri])

contenido

Podría definirse como:

function Luan.do_file(uri) local fn = Luan.load_file(uri) or Luan.error("file '"..uri.."' not found") return fn() end

Luan.error (message)

contenido

Lanza un error que contiene el mensaje.

Podría definirse como:

function Luan.error(message) Luan.new_error(message).throw() end

Luan.eval (text [, source_name [, env]])

contenido

Evalúa text como una expresión Luan.

Podría definirse como:

function Luan.eval(text,source_name, env) return Luan.load( "return "..text, source_name or "eval", env )() end

Luan.get_metatable (table)

contenido

Si table no tiene una metatabla, devuelve nil. De lo contrario, si la metatabla de la tabla tiene un campo "__metatable", devuelve el valor asociado. De lo contrario, devuelve la metatabla de la tabla dada.

Luan.hash_code (v)

contenido

Devuelve el código hash de v.

Luan.ipairs (t)

contenido

Devuelve una función iteradora para que la construcción

for i,v in ipairs(t) do body end

iterará sobre los pares clave–valor (1,t[1]), (2,t[2]), ..., hasta el primer valor nulo.

Podría definirse como:

function Luan.ipairs(t) local i = 0 return function() if i < #t then i = i + 1 return i, t[i] end end end

Luan.load (text, [source_name [, env [, persist]]])

contenido

Carga un bloque.

El text se compila. Si no hay errores sintácticos, devuelve el bloque compilado como una función; de lo contrario, lanza un error.

El parámetro source_name es una cadena que indica de dónde proviene el texto. Se utiliza para producir mensajes de error. Por defecto es "load".

Si se proporciona el parámetro env, se convierte en el _ENV del bloque.

El parámetro persist es un booleano que determina si el código compilado se almacena en caché de forma persistente en un archivo temporal. Por defecto es false.

Luan.load_file (file_uri)

contenido

Similar a load, pero obtiene el bloque del archivo file_uri. file_uri puede ser una cadena o una tabla uri.

Luan.new_error (message)

contenido

Crea una nueva tabla de error que contiene el mensaje asignado a "message". La tabla de error también contiene una función throw que lanza el error. La tabla también contiene una lista de elementos de traza de pila donde cada elemento de traza de pila es una tabla que contiene "source", "line", y posiblemente "call_to". La tabla también tiene una metatabla que contiene "__to_string" para renderizar el error.

Para imprimir la traza de pila actual, podrías hacer:

Io.print( Luan.new_error "stack" )

Luan.pairs (t)

contenido

Si t tiene un metamétodo __pairs, lo llama con t como argumento y devuelve el resultado de la llamada.

De lo contrario, devuelve una función para que la construcción

for k,v in pairs(t) do body end

iterará sobre todos los pares clave–valor de la tabla t.

Luan.parse (s)

contenido

Este es el equivalente de Luan a JSON.parse() de Javascript, pero para un valor de Luan. Además de los valores JSON habituales, Luan.parse permite cadenas largas y permite especificar tipos numéricos de double, float, integer, y long. Por ejemplo:

local t = Luan.parse[=[ { nothing = nil t = true f = false s = "string" ls = [[long string]] n = 3 d = double(3) f = float(3) i = integer(3) l = long(3) list = { 1, 2, 3 } table = { one = 1 two = 2 three = 3 } ["ugly-key"] = "something" } ]=]

Luan.range (start, stop [, step])

contenido

Basado en la función range() de Python, esto permite iterar a través de una secuencia de números.

Uso de ejemplo:

for i in range(1,10) do Io.print("count up:",i) end for i in range(10,0,-1) do Io.print("count down:",i) end

Podría definirse como:

function Luan.range(start, stop, step) step = step or 1 step == 0 and Luan.error "bad argument #3 (step may not be zero)" local i = start return function() if step > 0 and i <= stop or step < 0 and i >= stop then local rtn = i i = i + step return rtn end end end

Luan.raw_equal (v1, v2)

contenido

Verifica si v1 es igual a v2, sin invocar ningún metamétodo. Devuelve un booleano.

Luan.raw_get (table, index)

contenido

Obtiene el valor real de table[index], sin invocar ningún metamétodo. table debe ser una tabla; index puede ser cualquier valor.

Luan.raw_len (v)

contenido

Devuelve la longitud del objeto v, que debe ser una tabla o una cadena, sin invocar ningún metamétodo. Devuelve un entero.

Luan.raw_set (table, index, value)

contenido

Establece el valor real de table[index] a value, sin invocar ningún metamétodo. table debe ser una tabla, index cualquier valor diferente de nil, y value cualquier valor de Luan. Devuelve el valor antiguo de table[index].

Luan.set_metatable (table, metatable)

contenido

Establece la metatabla para la tabla dada. Si metatable es nil, remueve la metatabla de la tabla dada. Si la metatabla original tiene un campo "__metatable", lanza un error.

Luan.stringify (v [,options])

contenido

Este es el equivalente de Luan a JSON.stringify() de Javascript, pero para un valor de Luan. v es un valor de cualquier tipo que se convierte en una cadena que es una expresión de Luan. options puede ser una tabla o una función. Si options es una tabla, puede contener las siguientes banderas cuyo valor true significa:

Si options es una función, entonces esta función debe tomar un argumento stack y devolver una tabla options. El stack será una lista de claves que indica dónde stringify está procesando actualmente. Esto permite aplicar diferentes opciones en diferentes lugares de una estructura de datos.

Luan.to_string (v)

contenido

Recibe un valor de cualquier tipo y lo convierte en una cadena en un formato legible por humanos.

Si la metatabla de v tiene un campo "__to_string", entonces to_string llama al valor correspondiente con v como argumento, y usa el resultado de la llamada como su resultado.

Luan.type (v)

contenido

Devuelve el tipo de su único argumento, codificado como una cadena. Los posibles resultados de esta función son "nil" (una cadena, no el valor nil), "number", "string", "binary", "boolean", "table", "function", y "java".

Luan.values (···)

contenido

Devuelve una función para que la construcción

for i, v in Luan.values(···) do body end

iterará sobre todos los valores de ···.

Módulos

contenido

Incluye esta librería por:

local Package = require "luan:Package.luan"

La librería de paquetes proporciona facilidades básicas para cargar módulos en Luan.

Package.load (mod_uri)

contenido

Carga el módulo dado. La función comienza buscando en la tabla Package.loaded para determinar si mod_uri ya está cargado. Si lo está, entonces Package.load devuelve el valor almacenado en Package.loaded[mod_uri]. De lo contrario, intenta cargar un nuevo valor para el módulo.

Para cargar un nuevo valor, Package.load primero verifica si mod_uri comienza con "java:". Si es así, entonces esta es una clase Java que se carga mediante un código Java especial.

De lo contrario, Package.load intenta leer el texto del archivo referido por mod_uri. Si el archivo no existe, entonces Package.load devuelve false. Si el archivo existe, entonces su contenido se compila en un bloque llamando a Luan.load. Este bloque se ejecuta pasando mod_uri como argumento. El valor devuelto por el bloque no debe ser nil y se carga.

Si un nuevo valor para el módulo se carga con éxito, entonces se almacena en Package.loaded[mod_uri]. El valor se devuelve.

Package.loaded

contenido

Una tabla utilizada por Package.load para controlar qué módulos ya están cargados. Cuando cargas un módulo mod_uri y Package.loaded[mod_uri] no es nil, Package.load simplemente devuelve el valor almacenado allí.

Esta variable es solo una referencia a la tabla real; asignaciones a esta variable no cambian la tabla utilizada por Package.load.

Manipulación de Cadenas

contenido

Incluye esta librería por:

local String = require "luan:String.luan"

Esta librería proporciona funciones genéricas para la manipulación de cadenas, como encontrar y extraer subcadenas, y coincidencia de patrones. Al indexar una cadena en Luan, el primer carácter está en la posición 1 (no en 0, como en Java). Se permite que los índices sean negativos y se interpretan como indexación hacia atrás, desde el final de la cadena. Por lo tanto, el último carácter está en la posición -1, y así sucesivamente.

String.char (···)

contenido

Recibe cero o más enteros. Devuelve una cadena con longitud igual al número de argumentos, en la que cada carácter tiene el código numérico interno igual a su argumento correspondiente.

String.contains (s, s2)

contenido

Devuelve un booleano que indica si s contiene s2.

String.digest_message (algorithm, s)

contenido

Devuelve una cadena de resumen hexadecimal de s. Podría definirse como:

function String.digest_message(algorithm,s) return Binary.to_hex( Binary.digest_message( algorithm, String.to_binary(s) ) ) end

String.encode (s)

contenido

Codifica el argumento s en una cadena que se puede colocar entre comillas para devolver el valor original de la cadena.

String.ends_with (s, s2)

contenido

Devuelve un booleano que indica si s termina con s2.

String.find (s, s2 [, init])

contenido

Busca la primera subcadena s2 en la cadena s. Si encuentra una coincidencia, entonces find devuelve el índice de s donde comienza esta ocurrencia; de lo contrario, devuelve nil. Un tercer argumento numérico opcional init especifica dónde comenzar la búsqueda; su valor predeterminado es 1 y puede ser negativo.

String.find_reverse (s, s2 [, init])

contenido

Busca la última subcadena s2 en la cadena s. Si encuentra una coincidencia, entonces find devuelve el índice de s donde comienza esta ocurrencia; de lo contrario, devuelve nil. Un tercer argumento numérico opcional init especifica dónde comenzar la búsqueda; su valor predeterminado es -1.

String.format (formatstring, ···)

contenido

Devuelve una versión formateada de su número variable de argumentos siguiendo la descripción dada en su primer argumento (que debe ser una cadena). La cadena de formato sigue las mismas reglas que la función de Java String.format porque Luan llama a esto internamente.

Tenga en cuenta que String.format de Java es demasiado estúpido para convertir entre enteros y flotantes, por lo que debe proporcionar el tipo correcto de número.

String.lower (s)

contenido

Recibe una cadena y devuelve una copia de esta cadena con todas las letras mayúsculas cambiadas a minúsculas. Todos los demás caracteres se dejan sin cambios.

String.regex (s)

contenido

Devuelve una tabla regex para el patrón s.

String.regex_quote (s)

contenido

Devuelve una cadena que coincide con la cadena literal s en una expresión regular. Esta función es simplemente el método de Java Pattern.quote.

String.repeated (s, n [, sep])

contenido

Devuelve una cadena que es la concatenación de n copias de la cadena s separadas por la cadena sep. El valor predeterminado para sep es la cadena vacía (es decir, sin separador). Devuelve la cadena vacía si n no es positivo.

String.replace (s, target, replacement)

contenido

Devuelve una cadena donde cada subcadena target en s es reemplazada por replacement.

String.reverse (s)

contenido

Devuelve una cadena que es la cadena s invertida.

String.split (s, s2 [, limit])

contenido

Divide s usando la subcadena s2 y devuelve los resultados. Si limit es positivo, entonces solo devuelve como máximo esa cantidad de resultados. Si limit es cero, entonces elimina los resultados vacíos finales.

String.starts_with (s, s2)

contenido

Devuelve un booleano que indica si s comienza con s2.

String.sub (s, i [, j])

contenido

Devuelve la subcadena de s que comienza en i y continúa hasta j; i y j pueden ser negativos. Si j está ausente, entonces se asume que es igual a -1 (que es lo mismo que la longitud de la cadena). En particular, la llamada string.sub(s,1,j) devuelve un prefijo de s con longitud j, y string.sub(s, -i) devuelve un sufijo de s con longitud i.

Si, después de la traducción de índices negativos, i es menor que 1, se corrige a 1. Si j es mayor que la longitud de la cadena, se corrige a esa longitud. Si, después de estas correcciones, i es mayor que j, la función devuelve la cadena vacía.

String.to_binary (s)

contenido

Convierte una cadena a binario llamando al método de Java String.getBytes.

String.to_number (s [, base])

contenido

Cuando se llama sin base, to_number intenta convertir su argumento a un número. Si el argumento es una cadena convertible a un número, entonces to_number devuelve este número; de lo contrario, devuelve nil. La conversión de cadenas puede resultar en enteros o flotantes.

Cuando se llama con base, entonces s debe ser una cadena para ser interpretada como un numeral entero en esa base. En bases superiores a 10, la letra 'A' (en mayúsculas o minúsculas) representa 10, 'B' representa 11, y así sucesivamente, con 'Z' representando 35. Si la cadena s no es un numeral válido en la base dada, la función devuelve nil.

String.trim (s)

contenido

Elimina los espacios en blanco al principio y al final llamando al método de Java String.trim.

String.unicode (s [, i [, j]])

contenido

Devuelve los códigos numéricos internos de los caracteres s[i], s[i+1], ..., s[j]. El valor predeterminado para i es 1; el valor predeterminado para j es i. Estos índices se corrigen siguiendo las mismas reglas de la función String.sub.

String.upper (s)

contenido

Recibe una cadena y devuelve una copia de esta cadena con todas las letras minúsculas cambiadas a mayúsculas. Todos los demás caracteres se dejan sin cambios. La definición de lo que es una letra minúscula depende de la configuración regional actual.

Expresiones Regulares

contenido

Las expresiones regulares se manejan usando una tabla regex generada por String.regex.

La coincidencia de patrones se basa en la clase de Java Pattern.

regex.find (s [, init])

contenido

Busca la primera coincidencia de la regex en la cadena s. Si encuentra una coincidencia, entonces find devuelve los índices de s donde comienza y termina esta ocurrencia; de lo contrario, devuelve nil. Un tercer argumento numérico opcional init especifica dónde comenzar la búsqueda; su valor predeterminado es 1 y puede ser negativo.

Si la regex tiene capturas, entonces en una coincidencia exitosa los valores capturados también se devuelven, después de los dos índices.

regex.gmatch (s)

contenido

Devuelve una función iteradora que, cada vez que se llama, devuelve las siguientes capturas de la regex sobre la cadena s. Si la regex no especifica capturas, entonces la coincidencia completa se produce en cada llamada.

Como ejemplo, el siguiente bucle iterará sobre todas las palabras de la cadena s, imprimiendo una por línea:

local r = String.regex[[\w+]] local s = "hello world from Lua" for w in r.gmatch(s) do print(w) end

El siguiente ejemplo recoge todos los pares key=value de la cadena dada en una tabla:

local t = {} local r = String.regex[[(\w+)=(\w+)]] local s = "from=world, to=Lua" for k, v in r.gmatch(s) do t[k] = v end

Para esta función, un acento circunflejo '^' al inicio de un patrón no funciona como un ancla, ya que esto impediría la iteración.

regex.gsub (s, repl [, n])

contenido

Devuelve una copia de s en la que todas (o las primeras n, si se da) ocurrencias de la regex han sido reemplazadas por una cadena de reemplazo especificada por repl, que puede ser una cadena, una tabla o una función. gsub también devuelve, como su segundo valor, el número total de coincidencias que ocurrieron. El nombre gsub proviene de Global SUBstitution.

Si repl es una cadena, entonces su valor se usa para el reemplazo. El carácter \ funciona como un carácter de escape. Cualquier secuencia en repl de la forma $d, con d entre 1 y 9, representa el valor de la d-ésima subcadena capturada. La secuencia $0 representa la coincidencia completa.

Si repl es una tabla, entonces la tabla se consulta para cada coincidencia, usando la primera captura como clave.

Si repl es una función, entonces esta función se llama cada vez que ocurre una coincidencia, con todas las subcadenas capturadas pasadas como argumentos, en orden.

En cualquier caso, si la regex no especifica capturas, entonces se comporta como si toda la regex estuviera dentro de una captura.

Si el valor devuelto por la consulta de la tabla o por la llamada a la función no es nil, entonces se usa como la cadena de reemplazo; de lo contrario, si es nil, entonces no hay reemplazo (es decir, la coincidencia original se mantiene en la cadena).

Aquí hay algunos ejemplos:

local r = String.regex[[(\w+)]] local x = r.gsub("hello world", "$1 $1") --> x="hello hello world world" local r = String.regex[[(\w+)]] local x = r.gsub("hello world", "$0 $0", 1) --> x="hello hello world" local r = String.regex[[(\w+)\s*(\w+)]] local x = r.gsub("hello world from Luan", "$2 $1") --> x="world hello Luan from" local r = String.regex[[\$(.*?)\$]] local x = r.gsub("4+5 = $return 4+5$", function(s) return load(s)() end) --> x="4+5 = 9" local r = String.regex[[\$(\w+)]] local t = {name="lua", version="5.3"} local x = r.gsub("$name-$version.tar.gz", t) --> x="lua-5.3.tar.gz"

regex.match (s [, init])

contenido

Busca la primera coincidencia de la regex en la cadena s. Si encuentra una, entonces match devuelve las capturas de la regex; de lo contrario, devuelve nil. Si la regex no especifica capturas, entonces se devuelve la coincidencia completa. Un tercer argumento numérico opcional init especifica dónde comenzar la búsqueda; su valor predeterminado es 1 y puede ser negativo.

regex.matches (s)

contenido

Devuelve un booleano que indica si la regex se puede encontrar en la cadena s. Esta función es equivalente a

return regex.match(s) ~= nil

regex.set (pattern)

contenido

Cambia el patrón de la regex a pattern.

regex.split (s [, limit])

contenido

Divide s usando la regex y devuelve los resultados. Si limit es positivo, entonces solo devuelve como máximo esa cantidad de resultados. Si limit es cero, entonces elimina los resultados vacíos finales.

Manipulación Binaria

contenido

Incluye esta librería por:

local Binary = require "luan:Binary.luan"

Binary.base64_decode (s)

contenido

Igual que Base64.Decoder.decode de Java.

Binary.base64_encode (b)

contenido

Igual que Base64.Encoder.encodeToString de Java.

Binary.binary (···)

contenido

Recibe cero o más bytes (como enteros). Devuelve un binario con longitud igual al número de argumentos, en el que cada byte tiene el código numérico interno igual a su argumento correspondiente.

Binary.byte (b [, i [, j]])

contenido

Devuelve los códigos numéricos internos de los bytes b[i], b[i+1], ..., b[j]. El valor predeterminado para i es 1; el valor predeterminado para j es i. Estos índices se corrigen siguiendo las mismas reglas de la función String.sub.

Binary.digest_message (algorithm, b)

contenido

Implementado en Java como:

return MessageDigest.getInstance(algorithm).digest(b);

Binary.to_hex (b)

contenido

Convierte un binario a una cadena hexadecimal.

Binary.to_string (b [,charset])

contenido

Si charset no es nulo, entonces convierte el binario b a una cadena usando el constructor de String de Java, de lo contrario, convierte cada byte en un carácter.

Manipulación de Tablas

contenido

Incluye esta librería por:

local Table = require "luan:Table.luan"

Esta librería proporciona funciones genéricas para la manipulación de tablas. Proporciona todas sus funciones dentro de la tabla Table.

Table.case_insensitive ([tbl])

contenido

Devuelve una tabla con claves de cadena insensibles a mayúsculas y minúsculas. Copia tbl o está vacía.

Table.clear (tbl)

contenido

Limpia la tabla.

Table.concat (list [, sep [, i [, j]]])

contenido

Dada una lista, devuelve la cadena list[i]..sep..list[i+1] ··· sep..list[j]. El valor predeterminado para sep es la cadena vacía, el predeterminado para i es 1, y el predeterminado para j es #list. Si i es mayor que j, devuelve la cadena vacía.

Table.copy (tbl [, i [, j]])

contenido

Si i es nil, devuelve una copia superficial de tbl. De lo contrario, devuelve una nueva tabla que es una lista de los elementos tbl[i] ··· tbl[j]. Por defecto, j es #tbl.

Table.insert (list, pos, value)

contenido

Inserta el elemento value en la posición pos en list, desplazando hacia arriba los elementos list[pos], list[pos+1], ···, list[#list].

Table.is_empty (tbl)

contenido

Table.is_list (tbl)

contenido

Table.java_to_table_deep (obj [, java_to_table_shallow])

contenido

Aplica recursivamente java_to_table_shallow para convertir un objeto Java a tablas anidadas. java_to_table_shallow por defecto es Table.java_to_table_shallow.

Table.java_to_table_shallow (obj)

contenido

Convierte un objeto Java a una tabla. Funciona para tipos de colección List, Map, Set, y arreglos de Java.

Table.pack (···)

contenido

Devuelve una nueva tabla con todos los parámetros almacenados en las claves 1, 2, etc. y con un campo "n" con el número total de parámetros. Tenga en cuenta que la tabla resultante puede no ser una secuencia.

Table.remove (list, pos)

contenido

Elimina de list el elemento en la posición pos, devolviendo el valor del elemento eliminado. Cuando pos es un entero entre 1 y #list, desplaza hacia abajo los elementos list[pos+1], list[pos+2], ···, list[#list] y borra el elemento list[#list]; El índice pos también puede ser 0 cuando #list es 0, o #list + 1; en esos casos, la función borra el elemento list[pos].

Table.size (tbl)

contenido

Table.sort (list [, comp])

contenido

Ordena los elementos de la lista en un orden dado, en su lugar, desde list[1] hasta list[#list]. Si se da comp, entonces debe ser una función que reciba dos elementos de la lista y devuelva verdadero cuando el primer elemento debe venir antes que el segundo en el orden final (para que not comp(list[i+1],list[i]) sea verdadero después de la ordenación). Si no se da comp, entonces se utiliza el operador estándar de Lua <.

El algoritmo de ordenación no es estable; es decir, los elementos considerados iguales por el orden dado pueden tener sus posiciones relativas cambiadas por la ordenación.

Table.unpack (list [, i [, j]])

contenido

Devuelve los elementos de la lista dada. Esta función es equivalente a

return list[i], list[i+1], ···, list[j]

Por defecto, i es 1 y j es list.n or #list.

Manipulación de Números

contenido

Incluye esta librería por:

local Number = require "luan:Number.luan"

Number.double (x)

contenido

Devuelve x como un double.

Number.float (x)

contenido

Devuelve x como un float.

Number.integer (x)

contenido

Si el valor x es convertible a un entero, devuelve ese entero. De lo contrario, lanza un error.

Number.long (x)

contenido

Si el valor x es convertible a un long, devuelve ese long. De lo contrario, lanza un error.

Number.long_to_string (i, radix)

contenido

Convierte el valor long i a una cadena llamando a Long.toString.

Number.type (x)

contenido

Devuelve una cadena para el tipo numérico de x. Los posibles valores de retorno incluyen "integer", "long", "double", y "float".

Funciones Matemáticas

contenido

Incluye esta librería por:

local Math = require "luan:Math.luan"

Esta librería proporciona funciones matemáticas básicas. Proporciona todas sus funciones y constantes dentro de la tabla Math.

Math.abs (x)

contenido

Devuelve el valor absoluto de x.

Math.acos (x)

contenido

Devuelve el arcocoseno de x (en radianes).

Math.asin (x)

contenido

Devuelve el arcoseno de x (en radianes).

Math.atan (a)

contenido

Devuelve el arcotangente de un valor; el ángulo devuelto está en el rango -pi/2 a pi/2.

Math.atan2 (y, x)

contenido

Devuelve el arcotangente de y/x (en radianes), pero usa los signos de ambos parámetros para encontrar el cuadrante del resultado. (También maneja correctamente el caso de que x sea cero.)

Math.ceil (x)

contenido

Devuelve el valor integral más pequeño mayor o igual a x.

Math.cos (x)

contenido

Devuelve el coseno de x (se asume que está en radianes).

Math.deg (x)

contenido

Convierte el ángulo x de radianes a grados.

Math.exp (x)

contenido

Devuelve el valor ex (donde e es la base de los logaritmos naturales).

Math.floor (x)

contenido

Devuelve el valor integral más grande menor o igual a x.

Math.fmod (x, y)

contenido

Devuelve el resto de la división de x por y que redondea el cociente hacia cero.

Math.huge

contenido

Un valor mayor que cualquier otro valor numérico.

Math.log (x [, base])

contenido

Devuelve el logaritmo de x en la base dada. El valor predeterminado para base es e (para que la función devuelva el logaritmo natural de x).

Math.max (x, ···)

contenido

Devuelve el argumento con el valor máximo, según el operador de Lua <.

Math.max_integer

contenido

Un entero con el valor máximo para un entero.

Math.min (x, ···)

contenido

Devuelve el argumento con el valor mínimo, según el operador de Lua <.

Math.min_integer

contenido

Un entero con el valor mínimo para un entero.

Math.modf (x)

contenido

Devuelve la parte integral de x y la parte fraccionaria de x.

Math.pi

contenido

El valor de π.

Math.rad (x)

contenido

Convierte el ángulo x de grados a radianes.

Math.random ([m [, n])

contenido

Cuando se llama sin argumentos, devuelve un flotante pseudoaleatorio con distribución uniforme en el rango [0,1). Cuando se llama con dos enteros m y n, Math.random devuelve un entero pseudoaleatorio con distribución uniforme en el rango [m, n]. (El valor m-n no puede ser negativo y debe caber en un entero de Luan.) La llamada Math.random(n) es equivalente a Math.random(1,n).

Esta función es una interfaz para la función generadora pseudoaleatoria subyacente proporcionada por Java. No se pueden dar garantías sobre sus propiedades estadísticas.

Math.sin (x)

contenido

Devuelve el seno de x (se asume que está en radianes).

Math.sqrt (x)

contenido

Devuelve la raíz cuadrada de x. (También puedes usar la expresión x^0.5 para calcular este valor.)

Math.tan (x)

contenido

Devuelve la tangente de x (se asume que está en radianes).