Functional SE PDF
Functional SE PDF
Functional SE PDF
1
λ ¿QUÉ ES UNA FUNCIÓN?
2
λ FUNCIONES PURAS
3
λ EFECTOS SECUNDARIOS
4
λ FUNCIONES DE ORDEN MAYOR
Ventajas:
• Pasar comportamientos (pasar
funciones como parámetros).
• Compartir medio de
comunicación(callbacks).
• Compartir lógica/reglas que se puedan
repetir a lo largo del proyecto.
5
λ FUNCIONES LAMBDA
Parámetro(s)
Return
Lambda
Ventajas: Desventajas:
• Una vez creadas las instancias de los • Por cada modificación se necesita una
objetos no se puede alterar. nueva instancia del dato.
• Facilita crear funciones puras • Requiere especial atención al diseño.
disminuyendo los efectos • Existen objetos mutables(pueden
secundarios. provenir de librerías de terceros o
• Facilita usar threads/concurrencia. datos externos)fuera de nuestro
alcance.
7
λ java.util.function: Function
Parámetro
Dato que devuelve
Nombre
Sintaxis:
Parámetro
9
λ java.util.function: Consumer y Supplier
10
λ Un Supplier es una interfaz que nos permite crear
funciones que no requieran saber la procedencia de
los datos, no recibe argumentos pero devuelve un
tipo de dato.
Dato que va a generar
Nombre Indica que no recibirá ningún dato
Nota: Los ejemplos de Supplier y Consumer generan y consumen datos del tipo
CLIArguments, enseguida se muestra la definición del objeto.
11
λ java.util.function: Operators y BiFunction
Los Operators son funciones simplificadas que nos
permiten ver fácilmente que hacen o sobre que
trabajan.
Return
Parámetros
Return
13
λ SAM y FunctionalInterface
SAM (Single Abstract Method) indica que tenemos
una interfaz con un solo método sin definir, con esto
SAM nos permite crear nuestras propias interfaces.
En Java 8 se agrego la etiqueta
@FunctionalInterface para indicar que nuestra
interfaz se usara como función.
14
λ Usando nuestra interfaz:
Definimos
nuestra función
15
λ Operador de Referencia
Java nos permite integrar programación funcional a
nuestros proyectos donde ya están definidas
nuestras clases, métodos, objetos, etc. Con esto
podemos hacer referencia a esos métodos desde
nuestras funciones a partir de un operador.
Para poder hacer referencia a otro método es necesario que nuestra función reciba el mismo
parámetro(tipo de dato) y genere el mismo resultado que el método al cual hacemos referencia.
16
λ Inferencia de tipos
En programación funcional con Java no es necesario
indicar explícitamente los tipos de datos que
recibirán nuestras funciones, esto sucede porque en
tiempo de compilación java corrobora, basado en la
definición de nuestra función que los datos que se
pasan a través de esta sean del tipo que
corresponden.
17
λ Comprendiendo la sintaxis de las funciones lambda
18
λ
En este ejemplo usamos una lambda dentro de una BiFunction,
esta es la sintaxis de una lambda cuando se requieren mas de un parámetro.
Hay ocasiones en las cuales nuestras lambdas ocupan mas de una línea,
nota que la sintaxis es de la sig. Forma () -> {}.
En una lambda sencilla no es necesario
indicar explícitamente el return, sin embargo en nuestro ejemplo
el cuerpo de nuestra lambda al ser mas grande java necesita tener de forma
explicita en donde tendrá el retorno.
20
λ Entendiendo la composición de funciones
En clases anteriores revisamos qué condiciones se cumplen para tener una
high order function, en donde estas requerían recibir como parámetro o
devolver como resultado una función o ambas, tener este tipo de funciones
nos permite generar composición de funciones, es decir, encadenar o asociar
nuestras lambdas y funciones.
2 compose()
1
3 andThen()
22
λ La clase Optional
Un problema bastante común en Java son los null, este tipo de datos indican que es un
valor desconocido y pude lanzar una excepción pues el objeto o variable puede no
estar definido o inicializado, o talvez un dato inexistente en una base de datos.
Podemos programar de forma manual una serie de validaciones cuando iteramos sobre
una colección, base de datos etc. para evitar este tipo de datos o podemos usar la
alternativa que Java nos ofrece, la clase Optional.
Como podrás notar Optional nos ofrece muchas formas de controlar los null,
si quieres conocer todos los métodos de esta clase te recomiendo que le des un vistazo
a la API de java 8 y revises la documentación de Optional, aquí te dejo el link:
https://docs.oracle.com/javase/8/docs/api/
24
λ Streams
Java en su versión 8 incluyo la clase Stream.
Stream es una especie de colección, pero se diferencia de estas ya que Stream es auto
iterable, es decir con Stream podemos tener datos ya definidos o podemos proveer una
manera de ir generando los datos que pasaran mediante este flujo.
Hay una aspecto de los Streams que debemos tener siempre en mente:
“Los Streams solo pueden ser consumidos una vez”
25
λ
La forma mas sencilla para generar un Stream es usando el método
of() en ejemplo generamos un Stream a partir de datos que ya conocemos.
26
λ Stream listeners
Habíamos revisado en el tema anterior que un aspecto importante a considerar
de los Streams es que solo pueden consumirse una vez, esto nos obliga a
almacenar un nuevo tipo de variable por cada operación, lo cual en apariencia
parece poco útil, sin embargo nosotros podemos explotar el verdadero potencial
de los Streams haciendo uso de un viejo amigo: chaining.
27
λ
En este ejemplo observamos lo fácil que es implementar
el chaining, es posible que al ser pocos métodos que implementamos
en nuestro Stream notemos poca diferencia respecto al ejemplo
anterior, !pero imagina que tengamos que usar 5 o 10 operaciones a nuestro
Stream, lo engorroso que seria crear una variable por cada método! Eso
le restaría legibilidad a nuestro código.
28
λ Stream de tipo específico y Paralelismo
Hasta ahora dentro de los Stream solo hemos trabajado con objetos pero esta
clase también nos permite trabajar sobre datos primitivos muchos de estos
Stream específicos ya vienen definidos en Java.
Valor inicial
Parámetro
En este ejemplo trabajamos sobre un Stream del tipo int
sobre el cual vamos a estar iterando.
29
λ Operaciones intermedias
Cuando trabajamos con Streams operamos con métodos que pueden devolver otro
dato del tipo Stream, cuando esto ocurre sabemos que es un método que realiza
una operación intermedia, esto es así porque un Stream esta diseñado para ser
eficiente para operar con datos pero no para ser usado por el usuario final, es decir
no puedes usar Streams en una API o si tus datos van a ser consumidos por un
servicio programado en otro lenguaje estos no pueden consumir Streams.
Este ejemplo toma un Predicate y filtra los elementos para obtener solo los pares
para generar un nuevo Stream.
30
λ Operaciones finales
Vimos en la clase pasada que las operaciones intermedias generan otro Stream,
para darle utilidad a los datos que operamos en un Stream es necesario contar con
operaciones finales estas operaciones nos generan un valor final después de iterar
los elementos del Stream.
32
λ Espero te sea útil.
33