Julia Language
Funciones de orden superior
Buscar..
Sintaxis
- foreach (f, xs)
- mapa (f, xs)
- filtro (f, xs)
- reducir (f, v0, xs)
- foldl (f, v0, xs)
- foldr (f, v0, xs)
Observaciones
Las funciones pueden aceptarse como parámetros y también pueden producirse como tipos de retorno. De hecho, las funciones pueden crearse dentro del cuerpo de otras funciones. Estas funciones internas son conocidas como cierres .
Funciones como argumentos
Las funciones son objetos en julia. Como cualquier otro objeto, se pueden pasar como argumentos a otras funciones. Las funciones que aceptan funciones se conocen como funciones de orden superior .
Por ejemplo, podemos implementar un equivalente de la función foreach
la biblioteca estándar tomando una función f
como primer parámetro.
function myforeach(f, xs)
for x in xs
f(x)
end
end
Podemos probar que esta función funciona como esperamos:
julia> myforeach(println, ["a", "b", "c"])
a
b
c
Al tomar una función como primer parámetro, en lugar de un parámetro posterior, podemos usar la sintaxis de bloque do de Julia. La sintaxis del bloque do es solo una forma conveniente de pasar una función anónima como el primer argumento a una función.
julia> myforeach([1, 2, 3]) do x
println(x^x)
end
1
4
27
Nuestra implementación de myforeach
anterior es aproximadamente equivalente a la función foreach
incorporada. También existen muchas otras funciones incorporadas de orden superior.
Las funciones de orden superior son bastante poderosas. A veces, cuando se trabaja con funciones de orden superior, las operaciones exactas que se realizan pierden importancia y los programas pueden volverse bastante abstractos. Los combinadores son ejemplos de sistemas de funciones altamente abstractas de orden superior.
Mapa, filtro y reducción
Dos de las funciones de orden superior más fundamentales incluidas en la biblioteca estándar son map
y filter
. Estas funciones son genéricas y pueden operar en cualquier iterable . En particular, son muy adecuados para los cálculos en matrices .
Supongamos que tenemos un conjunto de datos de escuelas. Cada escuela enseña una materia en particular, tiene un número de clases y un número promedio de estudiantes por clase. Podemos modelar una escuela con el siguiente tipo inmutable :
immutable School
subject::Symbol
nclasses::Int
nstudents::Int # average no. of students per class
end
Nuestro conjunto de datos de escuelas será un Vector{School}
:
dataset = [School(:math, 3, 30), School(:math, 5, 20), School(:science, 10, 5)]
Supongamos que deseamos encontrar la cantidad de estudiantes en total inscritos en un programa de matemáticas. Para ello, requerimos varios pasos:
- debemos restringir el conjunto de datos solo a las escuelas que enseñan matemáticas (
filter
) - debemos calcular el número de estudiantes en cada escuela (
map
) - y debemos reducir esa lista de números de estudiantes a un solo valor, la suma (
reduce
)
Una solución ingenua (que no tiene el mejor rendimiento) sería simplemente usar esas tres funciones de orden superior directamente.
function nmath(data)
maths = filter(x -> x.subject === :math, data)
students = map(x -> x.nclasses * x.nstudents, maths)
reduce(+, 0, students)
end
y verificamos que hay 190 estudiantes de matemáticas en nuestro conjunto de datos:
julia> nmath(dataset)
190
Existen funciones para combinar estas funciones y así mejorar el rendimiento. Por ejemplo, podríamos haber utilizado la función mapreduce
para realizar el mapeo y la reducción en un solo paso, lo que ahorraría tiempo y memoria.
La reduce
solo es significativa para operaciones asociativas como +
, pero en ocasiones es útil realizar una reducción con una operación no asociativa. Las funciones de orden superior foldl
y foldr
se proporcionan para forzar un orden de reducción particular.