Hola! aquí me tienen nuevamente aportando con esta tercera entrega de mi tutorial =D.
Esta vez veremos otro tipo de variable, las de tipo function (función).
Estas pueden ser declaradas de varias formas, como por ejemplo:
function funcion1([argumentos]) BLOQUE end funcion2 = function ([argumentos]) BLOQUE end variable = {true,2,function ([argumentos]) BLOQUE end}
En este ejemplo, al tratarse de funciones cortas he ubicado todo en una sola línea, pero también se puede hacer tranquilamente:
function funcion1([argumentos]) BLOQUE end
Y así para el resto...
Ahora, como se puede observar, he declarado tres variables de tipo function de tres formas distintas:
La primera escribiendo la palabra function seguido del nombre de la variable (funcion1 en nuestro caso) y argumentos opcionales (todo lo que escriba entre "[" y "]" significa que puede ir o no) entre paréntesis, luego el bloque y por último para indicar que termina la declaración de la función, escribimos la palabra end.
Las dos primeras son del mismo tipo, de tal manera que al llamar a las funciones de esta forma: funcion1([argumentos])
y funcion2([argumentos])
es totalmente válido.
El tercer ejemplo, es una variación declarando una función como uno de los elementos de un arreglo, luego para llamar a la función, se usaría variable[3]([argumentos])
, también se pueden usar nombres de variables como se explicó en la anterior entrega.
Bien, también habrán visto alguna vez funciones con este formato: modulo.funcion([argumentos])
, pues para crear funciones de ese tipo primero se crea el modulo como arreglo, el cual contendra las funciones, de esta forma:
modulo = {} modulo.funcion = function ([argumentos]) BLOQUE end
o también se puede definir como:
function modulo.funcion ([argumentos]) BLOQUE end
En este caso tenemos que la tabla modulo, tiene la función y con esto ya podemos llamar a la función
modulo.funcion([argumentos])
Ahora, ¿por qué se usa a veces un punto y a veces dos puntos?
Bien, como vemos, modulo es una tabla, que puede contener funciones así como otras cosas vistas anteriormente.
Si ejecutamos la funcion con un punto ".", se ejecutará como estamos acostumbrados a que lo haga con los argumentos que le pasemos, pero si en lugar de un punto "." utilizamos dos puntos ":", el primer argumento de la función será la tabla modulo en sí. Esto quedará más claro con un ejemplo:
personaje = { x = 20, y = 20 } personaje.ancho = 20 personaje.alto = 50 function personaje.muevederecha(personaje, pixeles) personaje.x = personaje.x + pixeles end
Aquí vemos como utilizamos la tabla personaje como primer argumento y la función es creada usando un punto ".", pero si cambiamos el nombre personaje ya no nos funcionaría, porque buscará personaje... Entonces, ¿cómo podemos hacer que se ejecute sobre sí mismo?
Para eso usamos los dos puntos ":", o con un punto "." y la palabra "self", pero por comodidad usaremos los dos puntos ":" y nos ahorraremos el uso de self como primer argumento ;).
Usando el ejemplo anterior, quedaría así:
function personaje:muevederecha(pixeles) self.x = self.x + pixeles end
Hemos cambiado personaje (que es el nombre de la tabla) por self (que indica que usaremos la misma tabla como argumento), de tal manera que se hace más como de utilizar, ya que podremos hacer personaje:muevederecha(20)
y al ejecutarse, personaje.x tomará el valor de 40 (20 + 20).
Bueno, espero me sigan hasta ahí, ahora veremos los dos tipos de funciones que hay:
La primera es un tipo de función que no retorna valor alguno, estas sirven más que nada, para simplificar procesos, es decir, si tenemos una parte de código que se repite varias veces en nuestro programa, podemos poner ese trozo de código en una función y luego llamamos a la función, como ejemplo pondré una función sencilla:
function mostrar_suma(a,b) print(a+b) -- la función print es genérica de lua, en los luaplayers para PSP se usan funciones diferentes dependiendo del luaplayer end
Esa función toma los argumentos a y b (nótese que van separados por una coma) y luego muestra como resultado la suma, quiere decir que al hacer mostrar_suma(2,3)
mostrará 5.
Otro ejemplo sería:
function hello() print("Hello world!") end
Esa función no necesita de argumentos, y al hacer hello()
mostrará el mensaje "Hello world!"
El otro tipo de función retorna un valor, esto puede ser también con o sin argumentos, dependiendo de lo que esté programado dentro de esa función.
function suma(a,b,c) return a+b+c end
Esta es una función que retorna el valor de la suma de sus tres argumentos a, b y c, luego el return hará que la función tome el valor de lo que está luego de dicha palabra, de tal manera que si se hace:
resultado = suma(2,3,1)
El valor almacenado en resultado, será 6
Otro ejemplo, pero esta vez sin argumentos:
function mensaje() return "Hola mundo!" end
mensaje()
tomará el valor de lo que se escriba luego del return dentro de esta función, es decir, si se hace un print(mensaje())
, imprimirá el mensaje "Hola mundo!"
Noten que las funciones mostrar_suma()
y hello()
no tienen un valor de retorno (return), por eso al hacer:
variable = mostrar_suma() variable2 = hello()
variable y variable2 serían de tipo nil (nulo), ya que no hay dato que podamos almacenar, además sería lo mismo que hacer
mostrar_suma() hello()
Nota: Para las funciones que usen argumentos, se les puede pasar más argumentos que la cantidad que necesitan, pero es innecesario ya que no hace nada con esos valores.
En cambio si se le pasan menos argumentos de los que necesitan, dará error, ya que en el código interno de la función habrán valores de tipo nil y no podrá realizar el código, salvo el caso de que el código interno use sus argumentos como valores booleanos (lo veremos más adelante en estructuras de control, sobre todo las condicionales).
Bien, como he dicho en la nota de arriba, si no le pasamos los argumentos que necesita la función, dará error de que faltan parámetros. Pero… y si queremos hacer una función que tenga 1, 2, 3 o ningún parámetro?
La solución sería usar argumentos variables que en Lua se los define con tres puntos "..."
Veamos un ejemplo:
function sumatotal(...) a, b, c = ... res = 0 if a then res = res + a end if b then res = res + b end if c then res = res + c end return res end
En esta función especificamos que queremos tres argumentos opcionales a, b y c y los llenamos con los parámetros recibidos mediante los tres puntos "..." de tal manera que las variables pueden ser nil o un valor, dependiendo si se ha pasado el argumento o no.
Aquí también vemos como se usan las variables como valores booleanos, me explico:
Si las variables existen (no son nil y tampoco son false) hará la suma entre res y dicha variable (esto ya lo tendrán más claro en la entrega "Estructuras de control"), de tal manera que si se hace variable = sumatotal(3,nil,4)
, variable tendría el valor de 7.
Veamos otro ejemplo:
function sumatotal(...) lista_args = {...} local res = 0 for i = 1, #lista_args do if lista_args[i] then res = res + lista_args[i] end return res end
En esta función se ha hecho algo similar que la anterior, pero esta vez creando una lista con los argumentos recibidos y se ha hecho un for para ir sumando. En esta función al hacer variable = sumatotal(3,nil,4)
, variable será 3
¿Cómo?, pues recordemos que el operando de longitud "#" cuenta los elementos hasta encontrar un índice vacío (nil), en este caso el segundo argumento, así que hay que tener cuidado sobre elegir una estructura u otra.
Saludos!
Tutoriales realizados con la ayuda y asesoramiento de DeViaNTe
Cualquier duda o sugerencia, comenten =)
PSP FAT [5.00 M33-6] [6.60 ME] [Hard Moded] / Nintendo Wii [4.1U] [cIOS Hermes] [D2X cIOS] / iPhone 3G [4.2.1] [BB 05.13.04] [redsn0w] / iPod Touch 4 [6.1] [evasi0n]
07/05/10: Tuve el placer de llamarle con todo derecho "N00B" a molotovi xDDD
Recuerda: Sé el intérprete -_-
=)
Gracias DeViaNTe por recordarme esos detalles que se me pasaban por alto.
Recomiendo leer de nuevo todo el post, ya que se han añadido varias cosas de importancia.
Saludos!
PSP FAT [5.00 M33-6] [6.60 ME] [Hard Moded] / Nintendo Wii [4.1U] [cIOS Hermes] [D2X cIOS] / iPhone 3G [4.2.1] [BB 05.13.04] [redsn0w] / iPod Touch 4 [6.1] [evasi0n]
07/05/10: Tuve el placer de llamarle con todo derecho "N00B" a molotovi xDDD
Recuerda: Sé el intérprete -_-
añadido de lo "basico" a lo "chungo"
Saludos, gente, vamos a completar el tuto de las funciones con todo lo que conozco yo, si alguien mas sabe algo, que lo deje escrito tb, a ver si conseguimos un super tutorial.
Como bien dice chimecho, hay varias maneras de definir funciones, y las ha representado muy bien. Pero, como se crean las funciones tipo modulo.funcion( argumentos ) ?
Bien, en primer lugar, modulo seria una tabla, de manera que:
modulo = { };
modulo.funcion = function (args) BLOQUE end;
Pero tambien se puede definir como:
function modulo.funcion (args) BLOQUE end
En este caso tenemos que la tabla modulo, tiene la funcion esta. Por que se usa a veces un punto, y a veces dos puntos? Bien, como vemos, el modulo es una tabla, que puede contener funciones asi como otras cosas vistas anteriormente.
Si ejecutamos la funcion con un punto, pues se ejecutara como estamos acostumbrados a que lo haga. Pero, si lo ejecutamos con dos puntos... el primer argumento de la funcion, sera la tabla modulo en si.
Vamos a aprofundizar con ejemplos:
personaje = { x = 0, y = 20 }
personaje.ancho = 20;
personaje.alto = 50;
function personaje.muevederecha(personaje, pixeles) personaje.x = personaje.x + pixeles end
Pero... vemos que utilizamos la misma tabla personaje como primer parametro, y la funcion es creada usando un punto (.) pero si cambiamos el nombre a personaje... ya no nos funcionaria, pq buscara personaje... como podemos hacer que se ejecute sobre si mismo? Con los dos puntitos. O con un puntito y el uso de "self". Pero por comodidad usaremos los dos puntos, que nos ahorramos poner self como primer parametro.
Quedaria asi:
function personaje:muevederecha(pixeles) self.x = self.x + pixeles end
Vale, ha variado un rato largo, pero ahora es mas comodo de utilizar.
Pues podremos hacer personaje:muevederecha(20); y personaje.x tomara el valor de 40 (20 + 20).
---------------------------------
Otro punto y a parte, son las funciones con argumentos variables, como bien dice chimecho si especificamos los argumentos al inicio, en la cabecera de la funcion, y no se los pasamos, nos dara error de que faltan parametros. Pero... y si queremos hacer una funcion que tenga 1, 2, 3 o ningun parametro?
Solucion: los argumentos variables o varargs. En lua se typifican con tres puntos (...)
Veamos un ejemplo de una funcion:
function sumatotal(...)
a, b, c = ...
local res = 0;
if a then res = res + a end
if b then res = res + b end
if c then res = res + c end
return res;
end
function sumatotal(...)
lista_args = {...}
local res = 0;
for i = 1, #lista_args do
if lista_args[i] then res = res + lista_args[i];
end
return res;
end
Aqui he puesto dos distintos metodos de uso de los argumentos variables, en el primero, especificamos que queremos tres argumentos opcionales, a , b y c, y los llenamos con los parametros recibidos (...) . a, b, o c seran nil o un valor, depende si se ha pasado argumento o no.
En la siguiente funcion, se ha hecho algo parecido, pero se ha creado una lista con los argumentos recibidos, y se ha hecho recorrido for para ir sumando.
El caso es que en estos ejemplos, el primero, aceptaria a = 3; b = nil; c = 4; y daria 7, pero en el segundo, si pasamos a=3; b = nil; c = 4; el resultado sera 3 (como?) (Recordemos que en los for el operando de longitud de una tabla mira hasta encontrar un indice vacio, en este caso el segundo parametro, asi que tener cuidadin como elegir una estructura o otra segun vuestras funciones)
nota: Se que esta explicacion es algo tocha y pesada, pero chimecho seguro que la apaña y explica mejor cuando actualize el post xD
Actualmente desarrollando nuestra web y UXCode : http://www.gcrew.es
Bien
eso es todo chime sigue asi ;)
Muy buena esta entrega ^^
Muy buena esta entrega ^^ funciones ^^ Sigue asi chime un saludo