Funciones

Las funciones son un componente básico de la programación: son una forma práctica y eficaz de agrupar sentencias que realizan una tarea. Son la interfaz entre el dispositivo NetScaler y el código de extensión. Para las directivas, se definen funciones de extensión de directivas. En el caso de los protocolos, se implementan funciones de devolución de llamada para los comportamientos del protocolo. Las funciones consisten en definiciones de función que especifican qué valores se pasan a la función y qué instrucciones se ejecutan para la función, así como llamadas a funciones, que ejecutan funciones con datos de entrada específicos y obtienen resultados de la función.

Funciones de devolución de llamada de comportamiento de protocolo

El comportamiento del cliente TCP consiste en una función de devolución de llamada (on_data) que procesa los eventos del flujo de datos del cliente TCP. Para implementar el equilibrio de carga basado en mensajes (MBLB) para un protocolo basado en TCP, puede agregar código para esta función de devolución de llamada para procesar el flujo de datos TCP del cliente y analizar el flujo de bytes en mensajes de protocolo.

Las funciones de devolución de llamada de un comportamiento se llaman con un contexto, que es el estado del módulo de procesamiento. El contexto es la instancia del módulo de procesamiento. Por ejemplo, las devoluciones de llamada de comportamiento del cliente TCP se llaman con contextos diferentes para distintas conexiones TCP del cliente.

Además del contexto, las devoluciones de llamada de comportamiento pueden tener otros argumentos. Por lo general, el resto de los argumentos se pasan como carga útil, que es la colección de todos los argumentos. Por lo tanto, las instancias del módulo de procesamiento programable se pueden ver como una combinación de estado de instancia más funciones de devolución de llamada de evento, es decir, el contexto más el comportamiento. Y el tráfico fluye a través del proceso como carga útil de eventos.

Prototipo de función de devolución de llamada del cliente TCP:



                Function                client on_data (ctxt, payload)

                                                //.code

                end


<!--NeedCopy-->

Donde:

  • ctxt: contexto de procesamiento de clientes TCP
  • cargaútil — carga útil del evento
    • payload.data: datos TCP recibidos, disponibles como un flujo de bytes

Funciones de extensión de directivas

Dado que se escribe el lenguaje de expresión de directivas de NetScaler, la definición de una función de extensión debe especificar los tipos de sus entradas y su valor devuelto. La definición de función Lua se ha ampliado para incluir los siguientes tipos:


function self-type: function-name(parameter1: parameter1-type, and so on): return-type
     statements
end

<!--NeedCopy-->

Donde:

Los tipos son NSTEXT, NSNUM, NSBOOL o NSDOUBLE.

El autotipo es el tipo de autoparámetro implícito que se pasa a la función. Cuando se utiliza la función de extensión en una expresión de directiva de NetScaler, este es el valor generado por la expresión situada a la izquierda de la función. Otra forma de verlo es que la función amplía ese tipo en el lenguaje de directivas de NetScaler.

Los tipos de parámetros son los tipos de cada parámetro especificado en la llamada a la función de extensión en la expresión de directiva. Una función de extensión puede tener cero o más parámetros.

Return-type es el tipo de valor devuelto por la llamada a la función de extensión. Es la entrada de la parte de la expresión de directiva, si la hay, a la derecha de la función, o bien es el valor del resultado de la expresión.

Ejemplo:

function NSTEXT:COMBINE_HEADERS() : NSTEXT

Uso de la función de extensión en una expresión de directiva:

HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n").COMBINE_HEADERS()

Aquí el autoparámetro es el resultado de HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n"), que es un valor de texto. El resultado de la llamada COMBINE_HEADERS() es texto y, como no hay nada a la derecha de esta llamada, el resultado de toda la expresión es texto.

Definición de función local

Además de las funciones de extensión, no se pueden definir funciones globales en un archivo de extensión. Pero las funciones locales se pueden definir dentro de las funciones de extensión utilizando la instrucción de función Lua normal. Esto declara el nombre de la función y los nombres de sus parámetros (también conocidos como argumentos) y, como todas las declaraciones de Lua, no especifica ningún tipo. La sintaxis para esto es:


local function function-name(parameter1-name, parameter2-name, and so on)
     statements
end

<!--NeedCopy-->

Los nombres de las funciones y los parámetros son identificadores. (El nombre de la función es en realidad una variable y la instrucción de función es la abreviatura de nombre de función local = función (parameter1, etc.), pero no es necesario entender esta sutileza para usar funciones.)

Tenga en cuenta que aquí se utiliza y así sucesivamente para continuar el patrón de nombres de parámetros en lugar de lo habitual… Esto se debe a que… en sí mismo significa una lista de parámetros variables, que no se discutirán aquí.

Cuerpo de función y retorno

El bloque de sentencias entre la función y las sentencias end es el cuerpo de la función. En el cuerpo de la función, los parámetros de la función actúan como variables locales, con valores proporcionados por las llamadas a funciones, como se ha descrito anteriormente.

La instrucción return proporciona valores que se devolverán al autor de la llamada de la función. Debe aparecer al final de un bloque (en una función, si es entonces, bucle for, etc. Puede estar en su propio bloque, devolver… final). En él se especifican ninguno, uno o más de un valor devuelto:


return -- returns nil
return expression -- one return value
return expression1, expression2, ... -- multiple return values

<!--NeedCopy-->

Ejemplos:


local function fsum(a)
     local sum = 0
     for i = 1, #a do
          sum = sum + a[i]
     end
     return sum
end

Local function fsum_and_average(a)
     local sum = 0
     for i = 1, #a do
          sum = sum + a[i]
     end
     return sum, sum/#a
end

<!--NeedCopy-->

Llamadas a funciones

Una llamada de función ejecuta el cuerpo de una función, suministra valores para sus parámetros y recibe resultados. La sintaxis de una llamada a función es nombre-función (expression1, expression2, etc.), donde los parámetros de función se establecen en las expresiones correspondientes. El número de expresiones y parámetros no tiene por qué ser el mismo. Si hay menos expresiones que parámetros, el resto de los parámetros se establece en cero. Por lo tanto, puede hacer que uno o más parámetros al final de la llamada sean opcionales, y su función puede comprobar si están especificados comprobando si no son nulo. Una forma común de hacerlo es con la operación OR:


function f(p1, p2) -- p2 is optional
     p2 = p2 or 0 -- if p2 is nil, set to a default of 0
     . . .
end

<!--NeedCopy-->

Si hay más expresiones que parámetros, se omiten los valores de expresión restantes.

Como se ha señalado anteriormente, las funciones pueden devolver varios valores. Estas devoluciones se pueden utilizar en una sentencia de asignación múltiple. Ejemplo:


local my_array = {1, 2, 3, 4}
local my_sum, my_ave = sum_and_average(my_array)

<!--NeedCopy-->

Funciones iterador y bucles for genéricos

Ahora que hemos introducido funciones, podemos hablar de bucles for genéricos. La sintaxis del bucle for genérico (con una variable) es:


for variable in iterator(parameter1, parameter2, and so on) do
     statements in the for loop body
end

<!--NeedCopy-->

Donde iterator () es una función con cero o más parámetros que proporcionan un valor para una variable en cada iteración del cuerpo del bucle. La función iterator realiza un seguimiento de dónde se encuentra en la iteración utilizando una técnica llamada cierre, de la que no tienes que preocuparte aquí. Señala el final de la iteración devolviendo nulo. Las funciones iteradoras pueden devolver más de un valor, para su uso en una asignación múltiple.

Escribir una función iteradora está fuera del alcance de este artículo, pero hay pocos iteradores integrados útiles que ilustren el concepto. Uno es el iterador pairs(), que recorre las entradas de una tabla y devuelve dos valores, la clave y el valor de la siguiente entrada.

Ejemplo:


local t = {k1 = "v1", k2 = "v2", k3 = "v3"}
local a = {} -- array to accumulate key-value pairs
local n = 0 -- number of key-value pairs
for key, value in pairs(t) do
     n = n + 1
     a[n] = key.. " = ".. Value -- add key-value pair to the array
end
local s = table.concat(a, ";") -- concatenate all key-value pairs into one string

<!--NeedCopy-->

Otro iterador útil es la función string.gmatch(), que se usa en este ejemplo de COMBINE_HEADERS().

Funciones