5 Funciones
5.1 Creación de funciones
Una función asocia un nombre a un bloque de código de manera que cada vez que se invoca a la función se ejecuta el bloque de código asociado.
Para crear una función se utiliza la siguiente sintaxis
function
nombre(
parámetros)
bloque de código
end
La indentación del bloque de código no es necesaria pero es una buena práctica.
Para invocar una función basta con escribir su nombre y pasarle entre paréntesis los valores de los parámetros (argumentos) separados por comas.
5.1.1 Ejemplo de creación de funciones
> function saludo() # Función sin parámetros
juliaprintln("¡Bienvenido!")
end
function with 1 method)
saludo (generic
> saludo()
julia
¡Bienvenido!
> typeof(saludo)
juliatypeof(saludo) (singleton type of function saludo, subtype of Function)
5.2 Parámetros y argumentos de una función
Una función puede recibir valores cuando se invoca a través de unas variables conocidas como parámetros que se definen entre paréntesis y separados por comas en la declaración de la función. En el cuerpo de la función se pueden usar estos parámetros como si fuesen variables.
Los valores que se pasan a la función en una llamada o invocación concreta de ella se conocen como argumentos y se asocian a los parámetros de la declaración de la función.
> function calificacion(nota) # Función con un parámetro
juliaif nota < 5
println("Suspenso")
else
println("Aprobado")
end
end
function with 1 method)
calificacion (generic
> calificacion(7)
julia Aprobado
5.2.1 Paso de argumentos a una función
Los argumentos se pueden pasar de dos formas:
- Argumentos posicionales: Se asocian a los parámetros de la función en el mismo orden que aparecen en la definición de la función.
- Argumentos nominales: Se indica explícitamente el nombre del parámetro al que se asocia un argumento de la forma
parametro = argumento
.
Cuando una función tiente parámetros posicionales y como nominales, los posicionales deben indicarse primero y los nominales después, separando ambos tipos de parámetros por punto y coma ;
.
5.2.2 Ejemplo de paso de argumentos a una función
> function saludo(nombre, apellidos; ciudad)
juliaprintln("¡Hola $nombre $apellidos, bienvenido a $(ciudad)!")
end
function with 1 method)
saludo (generic
> saludo("Alfredo", "Sánchez", ciudad = "Madrid")
julia
¡Hola Alfredo Sánchez, bienvenido a Madrid!
> saludo("Alfredo", ciudad = "Madrid", "Sánchez")
julia ¡Hola Alfredo Sánchez, bienvenido a Madrid!
5.2.3 Argumentos por defecto
En la definición de una función se puede asignar a cada parámetro un argumento por defecto, de manera que si se invoca la función sin proporcionar ningún argumento para ese parámetro, se utiliza el argumento por defecto.
El valor por defecto de un parámetro se indica con la siguiente sintaxis parámetro = valor
.
> function saludo(nombre, apellidos, ciudad = "Madrid")
juliaprintln("¡Hola $nombre $apellidos, bienvenido a $(ciudad)!")
end
function with 2 methods)
saludo (generic
> saludo("Alfredo", "Sánchez")
julia
¡Hola Alfredo Sánchez, bienvenido a Madrid!
> saludo("Pepito", "Grillo", "Barcelona")
julia ¡Hola Pepito Grillo, bienvenido a Barcelona!
5.2.4 Funciones con un número variable de argumentos
Julia permite definir funciones que pueden llamarse con un número variable de argumentos. Para que una función pueda recibir un número variable de argumentos hay que poner tres puntos suspensivos ...
al final de último parámetro posicional.
Cuando se llame a la función los argumentos se irán asociando a los parámetros posicionales en orden y el último parámetro se asociará a una tupla con el resto de argumentos en la llamada.
> function media(x...)
juliaprintln("Media de ", x)
sum(x) / length(x)
end
function with 1 method)
media (generic
> media(1, 2, 3, 4)
julia1, 2, 3, 4)
Media de (2.5
5.2.5 Parámetros con tipo
Aunque Julia es un lenguaje de tipado dinámico también permite fijar el tipo de los parámetros de una una función. Esto permite definir diferentes variantes (métodos) de una misma función dependiendo del tipo de los argumentos, así como detectar errores cuando se llama a la función con argumentos de distinto tipo.
Para indicar el tipo de los parámetros de una función se utiliza la sintaxis parametro::tipo
.
Conviene no restringir demasiado el tipo de los parámetros de una función. Se debe elegir el tipo más general en la jerarquía de tipos para el que tiene sentido la función.
5.2.6 Ejemplo de parámetros con tipo
> function sumar(x::Number, y::Number)
julia+ y
x end
function with 1 method)
sumar (generic
> function sumar(x::String, y::String)
julia* y
x end
function with 2 methods)
sumar (generic
> sumar(1, 2)
julia3
> sumar(1.5, 2.5)
julia4.0
> sumar("Hola", "Julia")
julia"HolaJulia"
5.2.7 Paso de argumentos por asignación
En Julia los argumentos se pasan a una función por asignación, es decir, se asignan a los parámetros de la función como si fuesen variables locales. De este modo, cuando los argumentos son objetos mutables (arrays, diccionarios, etc.) se pasa al parámetro una referencia al objeto, de manera que cualquier cambio que se haga en la función mediante el parámetro asociado afectará al objeto original y serán visibles fuera de ella.
> function matricular(curso, asignatura)
juliapush!(curso, asignatura)
end
function with 1 method)
matricular (generic
> primer_curso = [];
julia
> matricular(primer_curso, "Álgebra Lineal");
julia
> matricular(primer_curso, "Programación");
julia
> primer_curso
julia2-element Vector{Any}:
"Álgebra Lineal"
"Programación"
5.2.8 Ámbito de los parámetros de una función
Los parámetros y las variables declaradas dentro de una función son de ámbito local, mientras que las variable definidas fuera de funciones son de ámbito ámbito global.
Tanto los parámetros como las variables del ámbito local de una función sólo están accesibles durante la ejecución de la función. Es decir, cuando termina la ejecución de la función estas variables desaparecen y no son accesibles desde fuera de la función.
Si en el ámbito local de una función existe una variable que también existe en el ámbito global, durante la ejecución de la función la variable global queda eclipsada por la variable local y no es accesible hasta que finaliza la ejecución de la función.
5.2.9 Ejemplo del ámbito de los parámetros de una función
> lenguaje = "Python";
julia
> function saludo(nombre)
julia= "Julia"
lenguaje println("¡Hola $(nombre), bienvenido a $(lenguaje)!")
end
function with 3 methods)
saludo (generic
> saludo("Alf")
julia
¡Hola Alf, bienvenido a Julia!
> lenguaje
julia"Python"
> nombre
julia: UndefVarError: nombre not defined ERROR
5.3 Retorno de una función
Una función devuelve siempre el valor de la última expresión evaluada en su cuerpo. Sin embargo, puede devolverse cualquier otro valor indicándolo detrás de la palabra reservada return
. Cuando el flujo de ejecución de la función alcanza esta palabra, la ejecución de la función termina y se devuelve el valor que la acompaña.
Si una función no devuelve ningún valor se puede escribir la palabra return
sin nada más.
Cuando se desea devolver más de un valor se puede pueden indicar separados por comas y la función devolverá la tupla formada por esos valores.
5.3.1 Ejemplo de retorno de una función
> function area_triangulo(base, altura)
juliareturn base * altura / 2 # Devuelve un valor
end
function with 1 method)
area_triangulo (generic
> area_triangulo(3, 4)
julia6.0
> function area_perimetro_circulo(r)
juliareturn π * r ^ 2, 2π * r # Devuelve dos valores
end
function with 1 method)
area_perimetro_circulo (generic
> area_perimetro_circulo(1)
julia3.141592653589793, 6.283185307179586) (
5.4 Funciones compactas
Cuando el cuerpo de una función es una única expresión se puede definir la función de forma mucho más compacta de la siguiente manera:
nombre(
parametros)
=
expresión
El valor que devuelve la función es el resultado de evaluar la expresión.
Esta forma de definir funciones es muy habitual para funciones matemáticas.
> area_triangulo(b, a) = b * a / 2
juliafunction with 1 method)
area_triangulo (generic
> area_triangulo(3, 4)
julia6.0
> valor_absoluto(x) = x < 0 ? -x : x
juliafunction with 1 method)
valor_absoluto (generic
> valor_absoluto(-1)
julia1
5.5 Funciones como objetos
En Julia las funciones son objetos como el resto de tipos de datos, de manera que es posible asignar una función a una variable y luego utilizar la variable para hacer la llamada a la función, pasar una función como argumento de otra función, o que una función devuelva otra función.
> suma(x, y) = x + y
juliafunction with 1 method)
suma (generic
> adicion = suma
juliafunction with 1 method)
suma (generic
> adicion(1, 2)
julia3
> calculadora(operador, x, y) = operador(x, y)
juliafunction with 1 method)
calculadora (generic
> calculadora(suma, 1, 2)
julia3
5.6 Funciones anónimas
Julia permite también definir funciones sin nombre. Para ello se utiliza la siguiente sintaxis.
(
parametros)
->
expresión
El principal uso de las funciones anónimas es para pasarlas como argumentos de otras funciones.
> calculadora(operador, x, y) = operador(x, y)
uliafunction with 1 method)
calculadora (generic
> calculadora((x, y) -> x + y, 1, 2)
julia3
> calculadora((x, y) -> x - y, 1, 2)
julia-1
5.7 Funciones asociadas a operadores
En Julia los operadores tienen asociadas funciones que son llamadas por el intérprete cuando se evalúa una expresión con operadores.
> +(1, 2, 3) # Equivalente a 1 + 2 + 3
julia6
> ∑ = +
julia+ (generic function with 208 methods)
> ∑(1, 2, 3)
julia6
5.8 Funciones recursivas
Una función recursiva es una función que en su cuerpo contiene alguna llama a si misma.
La recursión es una práctica común en la mayoría de los lenguajes de programación ya que permite resolver las tareas recursivas de manera más natural.
Para garantizar el final de una función recursiva, las sucesivas llamadas tienen que reducir el grado de complejidad del problema, hasta que este pueda resolverse directamente sin necesidad de volver a llamar a la función.
La recursión es una técnica que suele ser poco eficiente computacionalmente y conviene evitarla siempre que sea posible.
5.8.1 Ejemplo de funciones recursivas
> function factorial(n::Integer)
juliaif n <= 1
return 1
else
return n * factorial(n-1)
end
end
function with 1 method)
factorial (generic
> factorial(4)
julia24
> fib(n::Integer) = n ≤ 2 ? 1 : fib(n - 1) + fib(n - 2)
juliafunction with 1 method)
fib (generic
> fib(10)
julia55