Un paradigma de programación es una propuesta tecnológica adoptada por una comunidad de programadores y desarrolladores cuyo núcleo central es incuestionable en cuanto que únicamente trata de resolver uno o varios problemas claramente delimitados; la resolución de estos problemas debe suponer consecuentemente un avance significativo en al menos un parámetro que afecte a la ingeniería de software. Un paradigma de programación representa un enfoque particular o filosofía para diseñar soluciones. Los paradigmas difieren unos de otros, en los conceptos y la forma de abstraer los elementos involucrados en un problema, así como en los pasos que integran su solución del problema, en otras palabras, el cómputo. Tiene una estrecha relación con la formalización de determinados lenguajes en su momento de definición. Es un estilo de programación empleado. Un paradigma de programación está delimitado en el tiempo en cuanto a aceptación y uso, porque nuevos paradigmas aportan nuevas o mejores soluciones que la sustituyen parcial o totalmente. Wikipedia
Paradigmas principales
- Programación imperativa o por procedimientos
- Extendida en C, BASIC o Pascal.
- La programación imperativa es la más usada y la más antigua
- Se basa en dar instrucciones al ordenador de como hacer las cosas en forma de algoritmos.
- Programación orientada a objetos (POO/OOP)
- Extendida en C++, C#, Java, Python...
- Está basada en el imperativo, pero encapsula elementos denominados objetos que incluyen tanto variables como funciones
- Programación dirigida por eventos
- Tanto la estructura como la ejecución de los programas van determinados por los sucesos que ocurran en el sistema, definidos por el usuario o que ellos mismos provoquen.
- Programación funcional
- Basada en la definición los predicados
- Es de corte más matemático
- Extendida en Python, Haskell, etc...
- Programación reactiva
- Este paradigma se basa en la declaración de una serie de objetos emisores de eventos asíncronos y otra serie de objetos que se "suscriben" a los primeros (es decir, quedan a la escucha de la emisión de eventos de estos) y reaccionan a los valores que reciben.
- Es muy común usar la librería Rx de Microsoft (Reactive Extensions)
- Programación multiparadigma
- Es el uso de dos o más paradigmas dentro de un programa.
Otros paradigmas
- Programación declarativa
- Lenguaje específico del dominio (DSL): SQL
- Programación con restricciones
- Programación lógica
- Programación dinámica
- Etc...
La programación basada en prototipos es un estilo de programación orientada a objetos en la que las clases no están presentes y la reutilización de comportamiento (conocido como herencia en lenguajes basados en clases) se lleva a cabo a través de un proceso de decoración de objetos existentes que sirven de prototipos. Este modelo también se conoce como programación sin clases, orientada a prototipos o basada en ejemplos. Mozilla developer network
Terminología
- Clase
- Define las características del Objeto.
- Objeto
- Una instancia de una Clase.
- Propiedad
- Una característica del Objeto, como el color.
- Método
- Una capacidad del Objeto, como caminar.
- Constructor
- Es un método llamado en el momento de la creación de instancias.
- Herencia
- Una Clase puede heredar características de otra Clase.
- Encapsulamiento
- Una Clase sólo define las características del Objeto, un Método sólo define cómo se ejecuta el Método.
- Abstracción
- La conjunción de herencia compleja, métodos, propiedades que un objeto debe ser capaz de simular en un modelo de la realidad.
- Polimorfismo
- Diferentes Clases podrían definir el mismo método o propiedad.
Recursos
- A Simple Explanation of OOP
- Chapter 3: What is Object-Oriented Programming?
- JavaScript OOP: A beginners guide
- Introducción a la POO en Javascript moderno: las nuevas clases en ES6
- MDN | Introducción a JavaScript orientado a objetos
- MDN | Object-oriented JavaScript for beginners
- Goodbye, Object Oriented Programming
- Why Object Oriented Programming is Awesome
- The Little Guide for OOP in JS
- Usando Clases en JavaScript
Entendiendo los objetos
/*
[Objeto]{
[ Propiedad = Variables (no funciónes) ]
[ Método = Solo funciónes ]
}
*/
Constructor de Objetos
var coche = function (parametros) {
/* Codigo*/
};
Propiedades del Objeto
var coche = function (marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad
this.color = color;
this.tipo = tipo;
};
Asignación en el Constructor
var coche = function (marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
this.detalles = function(){
console.log("Tu coche es un "+this.marca+" "+this.modelo+" con "+this.antiguedad+" años, clase "+this.tipo+" y color "+this.color);
}
};
var miCoche = new coche ("Seat", "Panda", 20, "azul", "turismo");
miCoche.detalles();
Extensión del prototipo
var coche = function (marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
};
coche.prototype.detalles = function(){
console.log("Tu coche es un "+this.marca+" "+this.modelo+" con "+this.antiguedad+" años, clase "+this.tipo+" y color "+this.color);
}
var miCoche = new coche ("Seat", "Panda", 20, "azul", "turismo");
miCoche.detalles();
Vinculación Externa
var coche = function (marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
this.detalles = dameDetalles;
};
function dameDetalles(){
console.log("Tu coche es un "+this.marca+" "+this.modelo+" con "+this.antiguedad+" años, clase "+this.tipo+" y color "+this.color);
}
var miCoche = new coche ("Seat", "Panda", 20, "azul", "turismo");
miCoche.detalles();
Herencia (simplificada)
var perro = function () {
this.patas = 4;
this.ojos = 2;
};
var pastorAleman = function () {
this.colorLengua = "negra";
this.colorOjos = "marrón";
this.capacidadTrabajo = true;
this.especialidad = "Pastoreo";
};
pastorAleman.prototype = new perro();
var miPerro = new pastorAleman();
console.log("Número patas: "+miPerro.patas+"\n Número ojos: "+miPerro.ojos+"\n Color Lengua: "+miPerro.colorLengua+"\n Color ojos: "+miPerro.colorOjos+"\n Capacidad de trabajo: "+miPerro.capacidadTrabajo+"\n Especialidad: "+miPerro.especialidad);
Herencia clásica
var coche = function (marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
this.detalles = dameDetalles;
};
var furgon = function (taraMinima, cargaUtil, volumenCarga) {
this.taraMinima = taraMinima;
this.cargaUtil = cargaUtil;
this.volumenCarga = volumenCarga;
this.detallesTecnicos = detallesTecnicos;
};
function dameDetalles(){
console.log("Tu coche es un "+this.marca+" "+this.modelo+" con "+this.antiguedad+" años, clase "+this.tipo+" y color "+this.color);
}
function detallesTecnicos(){
console.warn("Tu coche tiene una Tara mínima de "+this.taraMinima+". Carga útil de "+this.cargaUtil+" y un volumen de carga de "+this.volumenCarga+"m3");
}
var miPickup = new coche ("Land Rover", "Santana Aníbal", 35, "Marrón tierra", "4x4");
miPickup.prototype = new furgon (1200, 768, 4.5);
miPickup.detalles();
miPickup.prototype.detallesTecnicos();
Métodos y atributos privados y públicos
var cocheEmpresa = function (marca, modelo, antiguedad, color, tipo) {
// públicas
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
// privadas
var ITVPasada = true;
var ITVfrecuencia = "Cada año";
var seguroEnRegla = true;
var companySeguros = "SegurExpress";
var tipoSeguro = "a terceros";
// Público
this.dameDetalles = function () {
console.log("Tu coche es un "+marca+" "+modelo+" con "+antiguedad+" años, clase "+tipo+" y color "+color);
}
// Privadas
function datosPrivados() {
if (ITVPasada && seguroEnRegla)
console.info("INFO: Todo en Regla, tienes que pasar la ITV "+ITVfrecuencia+". Tienes un seguro "+tipoSeguro+" con "+companySeguros);
else{
console.error("ALERTA! El coche no puede usarse. El seguro o la ITV no esta en regla.");
}
}
datosPrivados();
this.dameDetalles();
};
var miCoche = new cocheEmpresa ("Audi", "S8", 2, "negro", "Berlina");
var miCoche2 = new cocheEmpresa ("Audi", "S4", 2, "Rojo", "Compacto");
Datos opcionales
var cocheEmpresa = function (marca, modelo, antiguedad, color) {
this.marca = marca || "Seat";
this.modelo = modelo || "Ibiza";
this.antiguedad = antiguedad || 6;
this.color = color || "Azul Corporativo";
this.dameDetalles = function () {
console.log("Tu coche es un "+this.marca+" "+this.modelo+" con "+this.antiguedad+" años y color "+this.color);
}
this.dameDetalles();
};
var miCoche = new cocheEmpresa ("Audi", "S8", 2, "negro", "Berlina");
var miCoche2 = new cocheEmpresa ();
var otroCoche = new cocheEmpresa ("Seat", "Leon");
Reutilizando el contexto común
// Creamos un ID
var contador = 0;
var cocheEmpresa = function (marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
this.id = contador++;
var ITVPasada = true;
var ITVfrecuencia = "Cada año";
var seguroEnRegla = true;
var companySeguros = "SegurExpress";
var tipoSeguro = "a terceros";
this.dameDetalles = function () {
console.log("Tu coche es un "+marca+" "+modelo+" con "+antiguedad+" años, clase "+tipo+" y color "+color);
}
function datosPrivados() {
if (ITVPasada && seguroEnRegla)
console.info("INFO: Todo en Regla, tienes que pasar la ITV "+ITVfrecuencia+". Tienes un seguro "+tipoSeguro+" con "+companySeguros);
else{
console.error("ALERTA! El coche no puede usarse. El seguro o la ITV no esta en regla.");
}
}
function identificador(){
console.warn("Recuerda! Tu coche esta identificado como coche numero "+contador);
}
datosPrivados();
this.dameDetalles();
identificador();
};
var miCoche = new cocheEmpresa ("Audi", "S8", 2, "negro", "Berlina");
var otroCoche = new cocheEmpresa ("Audi", "A8", 5, "gris", "Berlina");
var miCoche2 = new cocheEmpresa ("Seat", "Ibiza", 9, "rojo", "Utilitario");
console.info("Total de coches de empresa hasta el momento "+contador);
var coche = {
marca: "Seat",
modelo: "Panda",
antiguedad: 20,
color: "azul",
tipo: "turismo"
};
var clonCoche = Object.create(coche);
console.log(clonCoche.marca+" "+clonCoche.modelo);
Object.prototype.isPrototypeOf()
console.log(coche.isPrototypeOf(clonCoche));
function arbol (nombre) {
this.nombre = nombre;
}
var miArbol = new arbol( "Pino" );
console.log( "miArbol.constructor es " + miArbol.constructor );
function Perro(nombre, criadero, color, sexo) {
this.nombre=nombre;
this.criadero=criadero;
this.color=color;
this.sexo=sexo;
}
var elPerro = new Perro("Gabby","Laboratorio","chocolate","femenino");
elPerro.toString();
Perro.prototype.toString = function perroToString() {
var retorno = "Perro " + this.nombre + " es " + this.sexo + " " + this.color + " " + this.criadero;
return retorno;
};
elPerro.toString();
Definición de Clases
class coche{
constructor(marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
}
detalles() {
console.log(`Tu coche es un ${this.marca} ${this.modelo} con ${this.antiguedad} años, clase ${this.tipo} y color ${this.color}`);
}
}
let miCoche = new coche ("Seat", "Panda", 20, "azul", "turismo");
miCoche.detalles();
/* ECMA 5
var coche = function (marca, modelo, antiguedad, color, tipo) {
// Propiedades
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
// Metodos
this.detalles = function(){
console.log("Tu coche es un "+this.marca+" "+this.modelo+" con "+this.antiguedad+" años, clase "+this.tipo+" y color "+this.color);
}
};
var miCoche = new coche ("Seat", "Panda", 20, "azul", "turismo");
miCoche.detalles();
*/
Extensión de clases
class perro {
constructor(nombre) {
this.patas = 4;
this.ojos = 2;
this.nombre = nombre;
}
ladrar() {
console.log(`${this.nombre} esta ladrando!`);
};
}
class pastorAleman extends perro {
constructor(nombre) {
super('pastorAleman');
this.colorLengua = "negra";
this.colorOjos = "marrón";
this.capacidadTrabajo = true;
this.especialidad = "Pastoreo";
}
informacion() {
console.log(`Nombre: ${this.nombre}
Número patas: ${this.patas}
Número ojos: ${this.ojos}
Color ojos: ${this.colorOjos}
Color Lengua: ${this.colorLengua}
Capacidad de trabajo: ${this.capacidadTrabajo}
Especialidad: ${this.especialidad}`);
}
}
let miPerro = new pastorAleman('Golden');
miPerro.informacion();
miPerro.ladrar();
/* ECMA 5
var perro = function (nombre) {
this.patas = 4;
this.ojos = 2;
this.nombre = nombre;
this.ladrar = function(){
console.log(this.nombre + " esta ladrando!");
}
};
var pastorAleman = function () {
this.colorLengua = "negra";
this.colorOjos = "marrón";
this.capacidadTrabajo = true;
this.especialidad = "Pastoreo";
this.informacion = function(){
console.log("Nombre: "+this.nombre+"\nNúmero patas: "+this.patas+"\nNúmero ojos: "+this.ojos+"\nColor Lengua: "+this.colorLengua+"\nColor ojos: "+this.colorOjos+"\nCapacidad de trabajo: "+this.capacidadTrabajo+"\nEspecialidad: "+this.especialidad);
}
};
pastorAleman.prototype = new perro("Golden");
var miPerro = new pastorAleman();
miPerro.informacion();
miPerro.ladrar();
*/
Métodos Estáticos
class coche{
static info (edad){
console.info(`Tienes ${edad} años ${ edad >= 18 ? "y puedes conduccir": "y ... ¡Sorpresa! No puedes conduccir."}`);
}
constructor(marca, modelo, antiguedad, color, tipo) {
this.marca = marca;
this.modelo = modelo;
this.antiguedad = antiguedad;
this.color = color;
this.tipo = tipo;
}
detalles() {
console.log(`Tu coche es un ${this.marca} ${this.modelo} con ${this.antiguedad} años, clase ${this.tipo} y color ${this.color}`);
}
}
coche.info(50);
coche.info(8);
let miCoche = new coche ("Seat", "Panda", 20, "azul", "turismo");
miCoche.detalles();
Getters/Setters
class Rectangle {
constructor (width, height) {
this._width = width
this._height = height
}
set width (width) { this._width = width }
get width () { return this._width }
set height (height) { this._height = height }
get height () { return this._height }
get area () { return this._width * this._height }
}
var r = new Rectangle(50, 20)
r.area === 1000
/* ECMA5
var Rectangle = function (width, height) {
this._width = width;
this._height = height;
};
Rectangle.prototype = {
set width (width) { this._width = width; },
get width () { return this._width; },
set height (height) { this._height = height; },
get height () { return this._height; },
get area () { return this._width * this._height; }
};
var r = new Rectangle(50, 20);
r.area === 1000;
*/
Getters/Setters con arrays tipados
// ES6 class equivalent to the following C structure:
// struct Example { unsigned long id; char username[16]; float amountDue }
class Example {
constructor (buffer = new ArrayBuffer(24)) {
this.buffer = buffer
}
set buffer (buffer) {
this._buffer = buffer
this._id = new Uint32Array (this._buffer, 0, 1)
this._username = new Uint8Array (this._buffer, 4, 16)
this._amountDue = new Float32Array(this._buffer, 20, 1)
}
get buffer () { return this._buffer }
set id (v) { this._id[0] = v }
get id () { return this._id[0] }
set username (v) { this._username[0] = v }
get username () { return this._username[0] }
set amountDue (v) { this._amountDue[0] = v }
get amountDue () { return this._amountDue[0] }
}
let example = new Example()
example.id = 7
example.username = "John Doe"
example.amountDue = 42.0
Usando Weakmap
class ClearableWeakMap {
constructor(init) {
this._wm = new WeakMap(init)
}
clear() {
this._wm = new WeakMap
}
delete(k) {
return this._wm.delete(k)
}
get(k) {
return this._wm.get(k)
}
has(k) {
return this._wm.has(k)
}
set(k, v) {
this._wm.set(k, v)
return this
}
}
En ciencias de la computación, la programación funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa, que enfatiza los cambios de estado mediante la mutación de variables.1 La programación funcional tiene sus raíces en el cálculo lambda, un sistema formal desarrollado en los años 1930 para investigar la definición de función, la aplicación de las funciones y la recursión. Muchos lenguajes de programación funcionales pueden ser vistos como elaboraciones del cálculo lambda. Wikipedia
/* Objetivo: Reducir a una dimension, filtrar, modificar, ordenar...
- Punto de partida: [[5,8], [3], [4,2,6,1], [7,9]];
- REDUCIR a una dimension
- FILTRAR los < 5
- MAPEAR los elementos * 10
- ORDENAR de mayor a menor
- Resultado Final: [40,30,20,10]
*/
const matrix = [[5,8], [3], [4,2,6,1], [7,9]];
const lista = matrix;
.reduce((a,b) => a.concat(b))
.filter(item => item < 5)
.map(item => item * 10)
.sort((a,b) => b - a);
console.log("lista:", lista);
Lenguajes que lo implementan
Conceptos básicos y jerga
- Transparencia referencial
- Efectos colaterales
- Recursividad
- Funciones puras
- Funciones de orden superior
- Funciones de primera clase
- Evaluación estricta frente a la no estricta
- Sistemas de tipos
- muchos más...
Ventajas
- El código es más conciso y expresivo
- El estado sea inmutable, evita muchos errores (sin efectos colaterales)
- Ideado para sistemas concurrentes (paralelos)
- Entrada y salida; Las funciones reciben parámetros y devuelven un resultado.
- Las funciones puras son muy previsibles y testeables
- Código infinitamente más expresivo
- Proceso de depuración simplificado
- Fomenta mucho la descomposición de las tareas complejas
- Hacemos uso de composiciones partiendo de fragmentos pequeños y especializados
- Métodos encadenados, tuplas y currificación
Desventajas
- Falta soporte nativo (tuplas, curry, etc...)
- Es un paradigma menos extendido
- Propensión a los errores, ya que JS no es estrcito con el pardaigma funcional
- El tipado debil puede ser preocupante
- Se acerca mucho a las matemáticas
- Gestión de recursos
- Necesidad de realizar una gran cantidad de abstracciones ad hoc
Recursos Clave
- JavaScript Functional Programming Cookbook (ES6)
- Programación Funcional En JavaScript con Javier Velez
- La programación funcional | That CS guy
- el.abismo = de[null] | Serie de Programación funcional
Más Recursos
- xgrommx/awesome-functional-programming
- stoeffel/awesome-fp-js
- Ebook | Functional Programming in JavaScript: How to improve your JavaScript programs using functional techniques
- El resurgir de la programación funcional
- Aterrizando en la programación funcional
- Scala.js deja de ser un experimento, no es sólo un compilador de Scala a JavaScript
- Anjana Vakil: Learning Functional Programming with JavaScript - JSUnconf
- Programación funcional pura en JavaScript - JSDayES 2016
- Functional programming in JavaScript en Fun Fun Function
- Introducción a programación funcional en JavaScript—Parte 1
- Introducción a la programación funcional en JavaScript
- Qué es la programación funcional y por qué deberías usarla
- ¿Qué es la programación funcional?
- So You Want to be a Functional Programmer (Part 1)
- Here’s Why Mapping a Constructed Array in JavaScript Doesn’t Work
- Functional programming paradigms in modern JavaScript: Partial Application
- Pros and cons of functional programming
- Demystifying functional programming (in a real company)
- Two Years of Functional Programming in JavaScript: Lessons Learned
- Coding Tip: Try to Code Without If-statements
- Javascript and Functional Programming: An Introduction
- How Immutable Data Structures (E.g. Immutable.js) are Optimized
- Make your code easier to read with Functional Programming
- Diferencias entre la programación funcional y La programación imperativa (C#)
- ¿Qué Es La Programación Funcional?
- dwyl/learn-elm
- dwyl/learn-elixir
- JavaScript promises are just like monads and I can explain both in less than 2 minutes
La Programación Funcional se refiere a la evaluación declarativa de funciones puras para crear programas inmutables y así evitar efectos secundarios que son observados externamente. El abismo de null
Programación declarativa
- Nos centramos en describir lo que hacer
- Evitamos especificar el flujo y los cambios de estado
- Sistema de cajas negras
// Imperativa (COMO hacerlo)
var lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let i = 0; i < lista.length; i++) {
lista[i] = lista[i]*lista[i];
}
console.log("Lista:", lista) // [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
// Declarativa (QUE hacer)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(num => num*num);
// [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Funciones puras (Pure Functions)
- Mantine las modificaciones en su
scope
- Solo toma los argumentos como entrada de información
- No modifica el contexto externo, por lo que se retorna la información directamente
- Transparencia referencial
- Inmutabilidad
// Función Impura
let numero = 1;
const incremento = () => numero += 1;
incremento(); // 2
//Función Pura
const incremento = n => n + 1;
incremento(1); // 2
// Función Impura
window.nombre = 'Ulises'
const saludos = () => `Hola, ${window.nombre}`
saludos() // 'Hola, Ulises'
//Función Pura
const saludos = (nombre) => `Hola, ${nombre}`
saludos('Ulises') // 'Hola, Ulises'
- modificar el valor de un argumento
- manipulación del DOM, BOM, Cookies, etc...
- Excepciones y gestión de errores
- APIs del navegador
Funciones de Orden Superior (Higher-order functions - HOF)
- Funcion que toma una funcion como argumento
- La función puede o no retornar una funcion
const sumador = (x, y) => x + y;
const calcular = (fn, x, y) => fn(x, y);
calcular(sumador, 1, 2); // 3
// Filtrado (Filter)
let coches = [
{id: 'X0001', kilometros: 60000},
{id: 'X0002', kilometros: 40000},
{id: 'X0003', kilometros: 90000}
];
const estaViejo = coche => coche.kilometros >= 60000;
coches.filter(estaViejo);
// [{id: "X0001", kilometros: 60000},{id: "X0003", kilometros: 90000}]
Recursividad (Recursion)
- Evitaremos el uso de bucles
- Utilizaremos funciones que se llaman a si mismas para generar una estructura similar al bucle
const cuentaAtras = numero => {
console.log(numero)
numero < 1 ? numero : cuentaAtras(numero - 1)
}
cuentaAtras(5);
const factorial = (num) => {
return num <= 0 ? 1 : num * factorial(num - 1)
}
factorial(5); //120
Composición funcional (Compose)
- Juntamos dos funciones para retornar una función nueva
const compositor = (f,g) => x => f(g(x));
const convMayusculas = x => x.toUpperCase();
const contador = x => `${x} [${x.length}]`;
const exclamar = x => `${x}!!!`
const textoContado = compositor(contador, convMayusculas);
const textoContadoExclamado = compositor(exclamar, compositor(contador, convMayusculas));
const textoExclamadoContado = compositor(contador, compositor(exclamar, convMayusculas));
textoContado("Lorem Ipsum"); // "LOREM IPSUM [11]"
textoContadoExclamado("Lorem Ipsum"); // "LOREM IPSUM [11]!!!"
textoExclamadoContado("Lorem Ipsum"); // "LOREM IPSUM!!! [14]"
Currificación (Currying)
La currificación es una técnica muy usada en programación funcional. Poder convertir funciones de varios parámetros en una sucesión de funciones con un único parámetro hace que consigamos sistemas más modulares y flexibles, lo que a la larga hará que mantengamos mejor nuestras aplicaciones y reutilicemos componentes. El abismo de null
const suma = (a, b) => a + b
const cumaCurrificada = (a) => (b) => a + b
cumaCurrificada(40)(2) // 42.
const sumaSegunda = cumaCurrificada(2) // (b) => 2 + b
sumaSegunda(10) // 12
Aridad
En el análisis matemático, la aridad de un operador matemático o de una función es el número de argumentos necesarios para que dicho operador o función se pueda calcular. Wikipedia
- Operación nularia significa aridad cero.
- Operación unaria o relación unaria significa aridad uno.
- Operación binaria o relación binaria significa aridad dos.
- Operación ternaria o relación ternaria significa aridad tres.
- La función variádica tiene una aridad indefinida, acepta una cantidad de argumentos variable.
function fun2 (arg1, arg2) {
//...
}
function fun3 (arg1, arg2, arg3) {
//...
}
console.log(fun2.length) // 2 -> Binaria
console.log(fun2.length) // 3 -> Ternaria
Aplicación parcial (Partial Application)
Aplicar parcialmente una funcion, significa crear una nueva funcion rellenando previamente alguno de los argumentos de la funcion original. idcmardelplata/functional-programming-jargon
En cualquier punto dado de un programa, la parte del codigo que aun esta por ejecutarse se conoce como continuación. idcmardelplata/functional-programming-jargon
Una funcion es idempotente si al volver a aplicarla sobre su resultado, no produce resultados diferentes. idcmardelplata/functional-programming-jargon
Y mucho más...
- Aridad
- Auto Currying
- Efectos secundarios
- Idempotente
- Estilo de punto libre o programación tacita
- Predicado
- Contratos
- Funciones guardas
- Categorías
- Valor
- Constante
- Functor
- Functor apuntado
- Elevar (lift)
- Transparencia referencial
- Razonamiento equacional
- Lambda
- Cálculo Lambda
- Evaluación Perezosa
- Monoide
- Mónada
- Co-mónada
- Functor Aplicativo
- Morfismo
- Setoide
- Semigrupo
- Plegable
- Traversable
- Signatura de tipos
- Tipos de unión
- Tipos de producto
- Opcional
“La programación reactiva es programación con flujos de datos asíncronos”
La Programación reactiva o Rx, es un estilo de microarquitectura y paradigma que implica el enrutamiento inteligente y el consumo de eventos, todos combinados, para cambiar el comportamiento de una aplicación bit.es
Los Sistemas Reactivos son:
- Responsivos: El sistema responde a tiempo en la medida de lo posible.
- Resilientes: El sistema permanece responsivo frente a fallos.
- Elásticos: El sistema se mantiene responsivo bajo variaciones en la carga de trabajo.
- Orientados a Mensajes: Los Sistemas Reactivos confían en el intercambio de mensajes asíncrono para establecer fronteras entre componentes, lo que asegura bajo acoplamiento, aislamiento y transparencia de ubicación.
Recursos Destacados
- The introduction to Reactive Programming you've been missing
- Slides | REACTIVE PROGRAMMING by jonalvarezz
- FCC | A quick introduction to Functional Reactive Programming (FRP)
Recursos
- Programación reactiva, qué es y por qué ahora
- El paradigma de la programación reactiva: claves para entenderla
- La programación reactiva
- ¿Qué es la Programación Reactiva? Una introducción
Una API para la programación asíncrona con flujos observables (RxJS es como Lodash para eventos)
RxJS es una librería para crear programas asincrónicos y basados en eventos mediante el uso de secuencias observables. Proporciona un tipo de núcleo (core type), el “Observable”, tipos de satélites (satellite types) “Observer, Schedulers, Subjects” y operadores inspirados en Array#extras “map, filter, reduce, every, etc” para permitir el manejo de eventos asíncronos como colecciones. Jorge Cano
Recursos Destacados
- reactivex | Web oficial
- ReactiveX/rxjs
- rxjs | Web Oficial
- En mi local funciona | Programación Reactiva con RxJs
- 30 días con RxJS
Recursos
- RxJS in Action
- RxJS: Reactive Extensions For JavaScript
- RxJS - What and Why?
- reactivex.io
- Reactive Programming RX JS Introduction
- Introducción a la Programación Reactiva: Rx
- Programación Reactiva, uso de la librería RxJs
- Programación Reactiva con RxJs
- RxJS y la programación reactiva
- Programación Reactiva (RX)
Observable
Los Observables son las secuencias de datos. Observable empaqueta los datos que se pueden pasar de un hilo a otro. Básicamente emiten los datos periódicamente o solo una vez en su ciclo de vida en función de sus configuraciones. Bit.es
Observador (Observer)
Los observadores consumen la secuencia de datos emitida por el observable. Bit.es
Subscription
Representa la ejecución de un Observable, es principalmente útil para cancelar la ejecución. Jorge Cano
Operators
Son funciones puras que permiten un estilo de “programación funcional” de tratar con colecciones con operaciones como mapa, filtro, concat, flatMap, etc. Jorge Cano
Subjects
Es el equivalente a un
EventEmitter
, y la única forma de multi-difundir un valor o evento a varios observers. Jorge Cano
Schedulers
Son el componente que le indican a los observables y observadores, en qué hilo deben ejecutarse. Bit.es
Sin Reactividad
// @see: https://rxjs-dev.firebaseapp.com/guide/overview
const button = document.querySelector('button');
button.addEventListener('click', () => console.log('Clicked!'));
Con Rxjs
// @see: https://rxjs-dev.firebaseapp.com/guide/overview
const { fromEvent } = rxjs;
const button = document.querySelector('button');
fromEvent(button, 'click')
.subscribe(() => console.log('Clicked!'));
Funciones Puras (Purity)
// @see: https://rxjs-dev.firebaseapp.com/guide/overview
// --- Sin RxJS
var count = 0;
var button = document.querySelector('button');
button.addEventListener('click', () => console.log(`Clicked ${++count} times`));
// --- Con RxJS
const { fromEvent } = rxjs;
const { scan } = rxjs.operators;
const button = document.querySelector('button');
fromEvent(button, 'click').pipe(
scan(count => count + 1, 0)
)
.subscribe(count => console.log(`Clicked ${count} times`));
Control de Flujos (Flow)
// @see: https://rxjs-dev.firebaseapp.com/guide/overview
// --- Sin RxJS
var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', () => {
if (Date.now() - lastClick >= rate) {
console.log(`Clicked ${++count} times`);
lastClick = Date.now();
}
});
// --- Con RxJS
const { fromEvent } = rxjs;
const { throttleTime, scan } = rxjs.operators;
const button = document.querySelector('button');
fromEvent(button, 'click').pipe(
throttleTime(1000),
scan(count => count + 1, 0)
)
.subscribe(count => console.log(`Clicked ${count} times`));
Transformación de Valores (Values)
// @see: https://rxjs-dev.firebaseapp.com/guide/overview
// --- Sin RxJS
let count = 0;
const rate = 1000;
let lastClick = Date.now() - rate;
const button = document.querySelector('button');
button.addEventListener('click', (event) => {
if (Date.now() - lastClick >= rate) {
count += event.clientX;
console.log(count)
lastClick = Date.now();
}
});
// --- Con RxJS
const { fromEvent } = rxjs;
const { throttleTime, map, scan } = rxjs.operators;
const button = document.querySelector('button');
fromEvent(button, 'click').pipe(
throttleTime(1000),
map(event => event.clientX),
scan((count, clientX) => count + clientX, 0)
)
.subscribe(count => console.log(count));
¡Recuerda!
- Nunca vayas en contra de al naturaleza de JavaScript
- Abraza que JS es un lenguaje multiparadigma
- Crea scripts híbridos donde podamos mezclar lo mejor de cada paradigma