SlideShare una empresa de Scribd logo
1 de 127
Descargar para leer sin conexión
Introducción a la programación
funcional en JavaScript
Hola!
Soy Ricardo Pallás
https://github.com/RPallas92/congreso-web-2016
Índice
1. Introducción (primeros ejercicios y
conceptos)
2. Trabajando con arrays sin bucles
3. Teoría de Categorías
4. Ejercicio final (App web vídeos: React + FP)
5. Conclusiones
1.
Introducción
Primeros ejercicios
y conceptos:
Funciones puras
¿Qué es la
programación
funcional?
‘’ La programación funcional es un paradigma de
programación que se basa en el uso de funciones
modeladas como funciones matemáticas.
La esencia es que los programas son la
combinación de expresiones. Una expresión puede
ser un valor concreto, variables y también
funciones.
¿Qué es una
función?
‘’
Una función es una relación entre un conjunto de
posibles entradas y un conjunto de posibles
salidas.
La función en sí misma, representa la relación.
Gaviotas
Unir: unir dos bandadas de gaviotas en una sola
Engendrar: la bandada se multiplica por el número de
gaviotas que engendra cada una
var Bandada = function(n) { this.gaviotas = n }
Bandada.prototype.unir = function(otra) {
this.gaviotas += otra.gaviotas;
return this;
}
Bandada.prototype.engendrar = function(otra) {
this.gaviotas = this.gaviotas * otra.gaviotas;
return this;
}
var bandada1 = new Bandada(4);
var bandada2 = new Bandada(2);
var bandada3 = new Bandada(0);
var resultado = bandada1.unir(bandada3)
.engendrar(bandada2).unir(bandada1.engendrar(bandada2)).gaviotas;
//=> 32
var unir = function(bandada_x, bandada_y) { return bandada_x + bandada_y; };
var engendrar = function(bandada_x, bandada_y) { return bandada_x * bandada_y; };
var bandada_a = 4;
var bandada_b = 2;
var bandada_c = 0;
var result = unir(
engendrar(bandada_b, unir(bandada_a, bandada_c)), engendrar(bandada_a, bandada_b)
);
//=>16
var sumar = function(x, y) { return x + y; };
var multiplicar = function(x, y) { return x * y; };
var bandada_a = 4;
var bandada_b = 2;
var bandada_c = 0;
var result = sumar(
multiplicar(bandada_b, sumar(bandada_a, bandada_c)), multiplicar(bandada_a, bandada_b)
);
//=>16
// associative
sumar(sumar(x, y), z) === sumar(x, sumar(y, z));
// commutative
sumar(x, y) === sumar(y, x);
// identity
sumar(x, 0) === x;
// distributive
multiplicar(x, sumar(y,z)) === sumar(multiplicar(x, y), multiplicar(x, z));
Funciones puras
Una función pura es una función que, dada la
misma entrada, siempre devuelve la misma
salida y no tiene ningún efecto colateral.
¿Qué es la programación funcional,
otra vez?
En gran medida, programas con
funciones puras: funciones que
reciben valores de entrada,
devuelve valores de salida, y no
hacen de más.
El problema: los efectos colaterales
Una función pura: libre de efectos
colaterales
function add(x,y) {
return x + y;
}
Una función impura: corrupta (no
declara todo lo que hace realmente)
function add(x,y) {
var z = x + y;
console.log('result of the sum: ', z);
return z;
}
// pure
xs.slice(0,3)
//=> [1,2,3]
xs.slice(0,3)
//=> [1,2,3]
xs.slice(0,3)
//=> [1,2,3]
// impure
xs.splice(0,3)
//=> [1,2,3]
xs.splice(0,3)
//=> [4,5]
xs.splice(0,3)
//=> []
var xs = [1,2,3,4,5]
// impure
var minimum = 21;
var checkAge = function(age) {
return age >= minimum;
}
// pure
var checkAge = function(age) {
var minimum = 21;
return age >= minimum;
}
// impure
var greeting = function(name) {
console.log("hi, " + name + "!")
}
// pure
var greeting = function(name) {
return "hi, " + name + "!";
}
console.log(greeting("Jonas"))
‘’
Una función es una relación entre un conjunto de
posibles entradas y un conjunto de posibles
salidas.
La función en sí misma, representa la relación.
Recordatorio
Una entrada, una salida
...
(-2, -1)
(0 , 0 )
(2 , 1 )
(4 , 2 )
(8 , 4 )
...
Dominio Rango
… -2 0 2 4 8 ... … -1 0 1 2 4 ...
Una entrada, una salida
var toLowerCase = {"A":"a", "B": "b", "C": "c", "D": "d", "E": "e", "D": "d"}
toLowerCase["C"]
//=> "c"
var isPrime = {1: false, 2: true, 3: true, 4: false, 5: true, 6: false}
isPrime[3]
//=> true
¿Y si hay múltiples argumentos?
//+ add :: [Number, Number] -> Number
var add = function(numbers) {
return numbers[0] + numbers[1]
}
¿Y si hay múltiples argumentos?
//+ add :: ? -> Number
var add = function() {
return arguments[0] + arguments[1]
}
‘’
Función “curried”:
“Una función que devuelve una
nueva función hasta que recibe todos
sus argumentos”
Currying
Currying
//+ add :: Number -> Number -> Number
var add = curry(function(x, y) {
return x + y
})
Currying
add
//=> function(x,y) { return x + y }
add(2,3)
//=> 5
add(2)
//=> function(y) { return 2 + y }
Currying
//+ get :: String -> {String: a} -> a
var get = curry(function(prop, obj) {
return obj[prop];
})
var user = {id: 15, name: "Jorge Aznar", email: "jaznar@email.com"}
get('email', user)
//=> jaznar@email.com
//+ email :: {String: a} -> a
var email = get('email')
//=> function(obj){ return obj[‘email’] }
email(user)
//=> jaznar@email.com
Currying
//+ filter :: (a -> Bool) -> [a] -> [a]
var filter = curry(function(f, xs) {
return xs.filter(f);
})
//+ odds :: [a] -> [a]
var odds = filter(isOdd)
odds([1,2,3])
//=> [1, 3]
Currying
var emails = map(email)
var users = [jesus, jorge, ja, jbalbas]
emails(users)
//=> ["jesus@lopez.org", "jorge@aznar.net",
"ja@samitier.com", "jota@balbas.es"]
Currying
//+ goodArticles :: [Article] -> [Article]
var goodArticles = function(articles) {
return _.filter(articles, function(article){
return _.isDefined(article)
})
}
//+ goodArticles :: [Article] -> [Article]
var goodArticles = filter(isDefined)
Currying
//+ getChildren :: DOM -> [DOM]
var getChildren = function(el) {
return el.childNodes
}
//+ getALLChildren :: [DOM] -> [[DOM]]
var getAllChildren = function(els) {
return _.map(els, function(el) {
return getChildren(el)
})
}
var getChildren = get('childNodes')
var getAllChildren = map(getChildren)
Composición
La composición de funciones es aplicar una
función a los resultados de otra
Composición
//+ compose :: (b -> c) -> (a -> b) -> a -> c
var compose = curry(function(f, g, x) {
return f(g(x))
})
Composición
//+ head :: [a] -> a
var head = function(x) { return x[0] }
//+ last :: [a] -> a
var last = compose(head, reverse)
last(['Java', 'JavaScript', 'PHP'])
//=> PHP
Composición
//+ wordCount :: String -> Number
var wordCount = function(sentence) {
var count = split(' ', sentence)
return length(count)
}
//+ wordCount :: String -> Number
var wordCount = compose(length, split(' '))
wordCount("Soy una frase de 6 palabras")
//=> 6
Composición
'B' <- 'b' <- 'Congreso Web'
compose(toUpperCase, last)('Congreso Web')
Composición
// Ley asociativa
compose(f, compose(g, h)) == compose(compose(f, g), h)
Composición
compose(toUpperCase, compose(head, reverse))
// ó
compose(compose(toUpperCase, head), reverse)
Composición
//+ lastUpper :: [String] -> String
var lastUpper = compose(toUpperCase, head, reverse)
lastUpper(['Java', 'PHP', 'JavaScript'])
//=> 'JAVASCRIPT'
//+ lastUpper :: [String] -> String
var loudLastUpper = compose(exclaim, toUpperCase, head, reverse)
loudLastUpper(['Java', 'PHP', 'JAVASCRIPT'])
//=> 'JAVASCRIPT!'
Composición
? <- map(['JavaScript', 'Rust']) <- ['JavaScript', 'Rust'] <- ['Rust', 'JavaScript']
compose(toUpperCase, map, reverse)(['Rust', 'JavaScript'])
Composición
['JAVASCRIPT', 'RUST'] <- ['JavaScript', 'Rust'] <- ['Rust', 'JavaScript']
compose(map(toUpperCase), reverse)(['Rust', 'JavaScript'])
2.
Trabajando con
arrays
Sin bucles, con
funciones puras
Inciso: Trabajar con colecciones (sin
bucles)
La mayoría de las operaciones que hacemos se
pueden conseguir con 5 funciones:
▣ map
▣ filter
▣ reduce
▣ concatAll
▣ zip
Prácticamente, todos los bucles se pueden
sustituir por estas funciones.
Ejercicios
Vamos a practicar el uso de las 5 funciones
https://github.com/RPallas92/congreso-web-2016
Directorio parte2
3.
Teoría de
Categorías
Primeros ejercicios
y conceptos:
Funciones puras
Teoría de Categorías
Es una rama abstracta de las matemáticas que
formaliza conceptos de diferentes ramas como
teoría de conjuntos, teoría de tipos, teoría de
grupos, lógica y más.
Principalmente, se trabaja con objetos,
morfismos y transformaciones. (Similitud con la
programación)
Categoría
Es una colección con los siguientes
componentes:
▣ Una colección de objetos
▣ Una colección de morfismos
▣ Una noción de composición de los morfismos
▣ Un morfismo en concreto, llamado identidad
Categoría
▣ La Teoría de Categorías es suficientemente
abstracta para modelar muchas cosas, pero
vamos a centrarnos en tipos y funciones
Categoría
Una colección de objetos:
▣ Los objetos serán tipos de datos. String,
Boolean, Number, Object.
▣ Boolean como el conjunto [true, false]
▣ Number como el conjunto de todos los
posibles valores numéricos
Categoría
Una colección de morfismos:
▣ Los morfismos serán las funciones normales
que escribimos diariamente.
Categoría
Una noción de composición de los morfismos:
▣ Nuestra función compose, presentada
anteriormente
▣ Que compose cumpla la ley asociativa no es
casualidad.
▣ Cualquier composición en la Teoría de
Categorías debe cumplirla
Categoría: Compsición
Categoría
Un morfismo concreto llamado identidad:
▣ Nueva función id
▣ Recibe una entrada, y la devuelve, nada más
var id = function(x) {
return x;
};
Almacena un valor, será utilizada más adelante
Identidad
// identity
compose(id, f) == compose(f, id) == f;
// true
▣ Esta propiedad se cumple para todas las
funciones unarias.
▣ Es como la identidad en los números
Identidad
// identity
compose(id, f) == compose(f, id) == f;
// true
▣ Esta propiedad se cumple para todas las
funciones unarias.
▣ Es como la identidad en los números
Nulls
Callbacks
Errors
Side effects
Objetos
▣ Contenedores/Wrappers para valores
▣ No tienen métodos
▣ No tienen propiedades
▣ Seguramente, no crees los tuyos propios
Objetos
var Container = function(val) {
this.val = val;
}
//+ Container :: a -> Container(a)
Container.of = function(x) {
return new Container(x);
};
Container.of(3)
//=> Container {val: 3}
Objetos
capitalize("flamethrower")
//=> "Flamethrower"
capitalize(Container.of("flamethrower"))
//=> [object Object]
Objetos
//+ map :: (a -> b) -> Container(a) -> Container(b)
Container.prototype.map = function(f) {
return Container.of(f(this.val));
}
Container.of("flamethrower").map(function(s){
return capitalize(s)
})
//=> Container(“Flamethrower”)
Objetos
//+ map :: (a -> b) -> Container(a) -> Container(b)
Container.prototype.map = function(f) {
return Container.of(f(this.val));
}
Container.of("flamethrower").map(capitalize)
//=> Container(“Flamethrower”)
Objetos
Container.of(3).map(add(1))
//=> Container(4)
[3].map(add(1))
//=> [4]
Objetos
Container.of([1,2,3]).map(reverse).map(first)
//=> Container(3)
Container.of("flamethrower").map(length).map(add(1))
//=> Container(13)
Objetos
//+ map :: Functor F => (a -> b) -> F a -> F b
var map = _.curry(function(f, obj) {
return obj.map(f)
})
Container.of(3).map(add(1)) // Container(4)
map(add(1), Container.of(3)) // Container(4)
Objetos
map(match(/cat/g), Container.of("catsup"))
//=> Container([“cat”])
map(compose(first, reverse),Container.of("dog"))
//=> Container(“g”)
‘’
“Un objeto o estructura
de datos que puede ser
mapeada”
▣ Funciones: map
FUNCTOR
Aquellos problemáticos null
//+ getElement :: String -> DOM
var getElement = document.querySelector
//+ getNameParts :: String -> [String]
var getNameParts = compose(split(' '), getText, getElement)
getNameParts('#full_name')
//=> ['José', 'Luis', 'Bárcenas', 'Gutiérrez']
Aquellos problemáticos null
//+ getElement :: String -> DOM
var getElement = document.querySelector
//+ getNameParts :: String -> [String]
var getNameParts = compose(split(' '), getText, getElement)
getNameParts('#fullname')
//=> BOOOOOOOOMM!!!!!!
Maybe
▣ Captura un null check
▣ Es posible que el valor no esté
▣ A veces tienen dos subclases: Just/Nothing
▣ En otros lenguajes se llama Option
Maybe
//+ map :: (a -> b) -> Maybe(a) -> Maybe(b)
var _Maybe.prototype.map = function(f) {
return this.val ? Maybe.of(f(this.val)) : Maybe.of(null);
}
map(capitalize, Maybe.of("flamethrower"))
//=> Maybe(“Flamethrower”)
Maybe
//+ map :: (a -> b) -> Maybe(a) -> Maybe(b)
var _Maybe.prototype.map = function(f) {
return this.val ? Maybe.of(f(this.val)) : Maybe.of(null);
}
map(capitalize, Maybe.of(null))
//=> Maybe(null)
Maybe
//+ firstMatch :: String -> String
var firstMatch = compose(first, match(/java/g))
firstMatch("python")
//=> BOOOM!!!
Maybe
//+ firstMatch :: String -> Maybe(String)
var firstMatch = compose(map(first), Maybe.of, match(/java/g))
firstMatch("python")
//=> Maybe(null)
Maybe
//+ firstMatch :: String -> Maybe(String)
var firstMatch = compose(map(first), Maybe.of, match(/java/g))
firstMatch("javascript")
//=> Maybe(“java”)
Either
▣ Utilizado para manejo de excepciones pura
▣ Es como Maybe, pero con un mensaje de
error embebido
▣ Tienen dos subclases: Left/Right
▣ Mapea la función sobre el Right, ignora el Left
Either
map(function(x) { return x + 1; }, Right.of(2))
//=> Right(3)
map(function(x) { return x + 1; }, Left.of(‘some message’))
//=> Left(‘some message’)
Either
//+ determineAge :: User -> Either(String, Number)
var determineAge = function(user){
return user.age ? Right.of(user.age) : Left.of("couldn’t get
age");
}
//+ yearOlder :: User -> Either(String, Number)
var yearOlder = compose(map(add(1)), determineAge)
yearOlder({age: 22})
//=> Right(23)
var jordiHurtado = {age: null}
yearOlder(jordiHurtado)
//=> Left("couldn’t get age")
IO
▣ Utilizado para lazy computation
▣ Utilizado para manejar los efectos colaterales
▣ Para ejectuar la operación, se debe llamar a
runIO
▣ map añade la función a una lista de
operaciones a ejecutar
IO
//+ email_io :: IO(String)
var email_io = new IO(function(){ return $("#email").val() })
//+ msg_io :: IO(String)
var msg_io = map(concat("Bienvenido "), email_io)
msg_io.unsafePerformIO()
//=> ”Bienvenido jbalbas@email.net”
unsafePerfomIO()
IO
//+ getBgColor :: JSON -> Color
var getBgColor = compose(get("background-color"), JSON.parse)
//+ bgPref :: _ -> IO(Color)
var bgPref = compose(map(getBgColor), Store.get("preferences"))
//+ app :: _ -> IO(Color)
var app = bgPref()
//=> IO()
app.unsafePerformIO()
//=> #efefef
IO
//+ email_io :: _ -> IO(String)
var email_io = new IO(function(){ return $("#email").val() }
//+ getValue :: String -> IO(String)
var getValue = function(sel){
return new IO(function(){ return $(sel).val() });
}
Task / Future
▣ Se utiliza para operaciones asíncronas
▣ Representa un valor en el tiempo
▣ Para ejecutar la operación, se debe llamar a
fork
▣ Fork recibe una función como valor
▣ Se llama a la función con el resultado del Task
una vez que lo tiene
Task / Future
//+ makeHtml :: Post -> HTML
var makeHtml = function(post){ return "<div>"+post.title+"</div>"};
//+ page_f :: Future(Html)
var page_f = map(makeHtml, http.get('/posts/2'))
page_f.fork(
function(err) { throw(err) },
function(page){ $('#container').html(page) }
)
Pointed Functors
▣ Es un Functor con un método of
▣ Of :: a -> F a
▣ Permite poner valores en un contexto mínimo
que retiene el valor (o contexto puro)
▣ También llamado pure
Pointed Functors
▣ Es un Functor con un método of
▣ Of :: a -> F a
▣ Permite poner valores en un contexto mínimo
que retiene el valor (o contexto puro)
▣ También llamado pure
Pointed Functors
Container.of(2)
// Container(2)
Maybe.of(reverse)
// Maybe(reverse)
Future.of(match(/dubstep/))
// Future(match(/dubstep/))
IO.of('hack')
// IO(function(){ return 'hack'})
Task / Future
//+ lineCount :: String -> Number
var lineCount = compose(length, split(/n/))
//+ fileLineCount :: String -> Future(Number)
var fileLineCount = compose(map(lineCount), readFile)
fileLineCount("mydoc.txt").fork(log, log)
//=> 34
Leyes de los functores
// identity
map(id) == id
// composition
compose(map(f), map(g)) == map(compose(f, g))
Pregunta
Haz una llamada a una api con una id, y obtén un
post (puede existir o no)
Respuesta
Future(Maybe(Post))
Mónadas
▣ Patrón de diseño utilizado para describir
computaciones como series de pasos (o
computaciones anidadas)
▣ Utilizadas para gestionar los efectos
colaterales
▣ O para controlar la complejidad
Funciones:
▣ join
▣ chain
Mónadas
▣ join :: M M a -> M a
▣ chain :: (a -> M b) -> M a -> M b
Una mónada es un Pointed Functor añadiendo
los métodos join y chain
Mónadas
join(Container.of(Container.of(2)))
//=> Container(2)
Mónadas
//+ getTrackingId :: Order -> Maybe(TrackingId)
var getTrackingId = compose(Maybe.of, get("tracking_id"))
//+ findOrder :: Number -> Maybe(Order)
var findOrder = compose(Maybe.of, Api.findOrder)
//+ getOrderTracking :: Number -> Maybe(Maybe(TrackingId))
var getOrderTracking = compose(map(getTrackingId), findOrder)
//+ renderPage :: Number -> Maybe(Maybe(Html))
var renderPage = compose(map(map(renderTemplate)), getOrderTracking)
Mónadas
//+ getTrackingId :: Order -> Maybe(TrackingId)
var getTrackingId = compose(Maybe.of, get("tracking_id"))
//+ findOrder :: Number -> Maybe(Order)
var findOrder = compose(Maybe.of, Api.findOrder)
//+ getOrderTracking :: Number -> Maybe(TrackingId)
var getOrderTracking = compose(join, map(getTrackingId), findOrder)
//+ renderPage :: Number -> Maybe(Html)
var renderPage = compose(map(renderTemplate), getOrderTracking)
Mónadas
//+ :: setSearchInput :: String -> IO(_)
var setSearchInput = function(x) { return new IO(function() { ("#input").val(x); }) }
//+ :: searchTerm :: IO(String)
var searchTerm = new IO(function() { getParam("term", location.search) })
//+ :: initSearchForm :: IO(IO(_))
var initSearchForm = map(setSearchInput, searchTerm)
initSearchForm.unsafePerformIO().unsafePerformIO();
Mónadas
//+ :: setSearchInput :: String -> IO(_)
var setSearchInput = function(x) { return new IO(function() { ("#input").val(x); }) }
//+ :: searchTerm :: IO(String)
var searchTerm = new IO(function() { getParam("term", location.search) })
//+ :: initSearchForm :: IO(IO(_))
var initSearchForm = map(setSearchInput, searchTerm)
join(initSearchForm).unsafePerformIO();
Mónadas
//+ sendToServer :: Params -> Future(Response)
var sendToServer = httpGet('/upload')
//+ uploadFromFile :: String -> Future(Response)
var uploadFromFile = compose(join, map(sendToServer), readFile)
uploadFromFile("/tmp/my_file.txt").fork(logErr, alertSuccess)
Mónadas
//+ sendToServer :: Params -> Future(Response)
var sendToServer = httpGet('/upload')
//+ uploadFromFile :: String -> Future(Response)
var uploadFromFile = compose(join, map(sendToServer), join, map(readFile), askUser)
uploadFromFile('what file?').fork(logErr, alertSuccess)
Mónadas
//+ chain :: (a -> M b) -> M a -> M b
var chain = function(f) {
return compose(join, map(f))
}
// también llamado flatMap
Mónadas
//+ sendToServer :: Params -> Future(Response)
var sendToServer = httpGet('/upload')
//+ uploadFromFile :: String -> Future(Response)
var uploadFromFile = compose(chain(sendToServer), chain(readFile), askUser)
uploadFromFile('what file?').fork(logErr, alertSuccess)
Functores aplicativos
▣ Ejecutar computaciones completas en un
contexto
▣ Permite aplicar un functor a otro
Funciones:
▣ ap
▣ liftA2
▣ liftA3
▣ lifA..N
Functores aplicativos
add(Container.of(2), Container.of(3));
//NaN
var container_of_add_2 = map(add, Container.of(2));
// Container(add(2))
Functores aplicativos
map(add(1), Container(2))
//=> Container(3)
add(Container.of(2), Container.of(3));
//NaN
map(add, Container(2))
//=> Container(add(2))
Functores aplicativos
▣ ap :: A (a -> b) -> A a -> A b
▣ Un functor aplicativo es un Pointed Functor
con un método ap
Functores aplicativos
Container.of(f).ap(Container(x))
//=> Container(f(x))
Container.of(f).ap(Container(x)).ap(Container(y))
//=> Container(f(x, y))
Functores aplicativos
Container.of(add).ap(Container(1)).ap(Container(3))
//=> Container(4)
Functores aplicativos
Maybe.of(add).ap(Maybe(1)).ap(Maybe(3))
//=> Maybe(4)
Maybe.of(add).ap(Maybe(1)).ap(Maybe(null))
//=> Maybe(null)
Functores aplicativos
var loadPage = _.curry(function(products, reviews){
render(products.zip(reviews)
})
Future.of(loadPage)
.ap(Api.get('/products'))
.ap(Api.get('/reviews'))
Functores aplicativos
var getVal = compose(Maybe, get('value'), document.querySelector)
var save = _.curry(function(email, pass){ return User(email, pass) })
Maybe.of(save).ap(getVal('#email')).ap(getVal('#password'))
//=> Maybe(user)
Functores aplicativos
var getVal = compose(Maybe, pluck('value'), document.querySelector)
var save = _.curry(function(email, pass){ return User(email, pass) })
liftA2(save, getVal('#email'), getVal('#password'))
//=> Maybe(user)
Fantasy Land
https://github.com/fantasyland/fantasy-land
4.
Ejercicio final
Aplicación de
ejemplo
Aplicación buscador de vídeos
Youtube
▣ Vista: React
▣ Manipulación de datos: Ramda
▣ Maybe: folktale/data.maybe
▣ Either: folktale/data.either
▣ Task: folktale/data.task
React
▣ Biblioteca para crear interfaces
de usuario en JavaScript
▣ Simple
▣ Declarativa
▣ Modular: componentes
reusables
▣ Utiliza la composición de los
componentes para crear nuevos
▣
https://facebook.github.io/react
Ramda
▣ Biblioteca para programación
funcional práctica en JavaScript
▣ Similar a lodash o undescore
▣ Todas las funciones están curried
▣ Parámetros de las funciones
ordenados para favorecer el curry
▣ Trabaja bien con implementaciones
Mónadas, functores, etc.
http://ramdajs.com
Folktale
▣ Suite de bibliotecas para programación
funcional genérica en JavaScript
▣ Utilizaremos su implementación de
□ Maybe
□ Either
□ Task (Future)
http://folktalejs.org
App vídeos YouTube
▣ Permite buscar vídeos “al vuelo”
▣ Muestra los vídeos como un grid
▣ Al hacer clic sobre uno, se abre su
página de YouTube
App vídeos YouTube
App vídeos YouTube
▣ Permite buscar vídeos “al vuelo”
▣ Muestra los vídeos como un grid
▣ Al hacer clic sobre uno, se abre su
página de YouTube
5.
Conclusiones
Conclusiones
▣ Crear funciones pequeñas (Divide and
conquer (and reuse))
▣ Composición de esas funciones
▣ Utilizar funciones puras
▣ Tener aislada la parte impura del
programa
▣ Estilo declarativo vs imperativo
¡Gracias!
¿Preguntas?
@pallasr
https://github.com/MostlyAdequate/mostly-
adequate-guide

Más contenido relacionado

La actualidad más candente

La actualidad más candente (19)

Php funciones en detalle
Php   funciones en detallePhp   funciones en detalle
Php funciones en detalle
 
Programando con Python
Programando con PythonProgramando con Python
Programando con Python
 
Funciones en php
Funciones en phpFunciones en php
Funciones en php
 
Hechos en clase
Hechos en claseHechos en clase
Hechos en clase
 
3152
31523152
3152
 
Ejercicios con Python parte 05
Ejercicios con Python parte 05Ejercicios con Python parte 05
Ejercicios con Python parte 05
 
Las funciones en JavaScript para la programación orientada a objetos
Las funciones en JavaScript para la programación orientada a objetosLas funciones en JavaScript para la programación orientada a objetos
Las funciones en JavaScript para la programación orientada a objetos
 
Arreglos en C++
Arreglos en C++Arreglos en C++
Arreglos en C++
 
1.2. kotlin (1)
1.2. kotlin (1)1.2. kotlin (1)
1.2. kotlin (1)
 
Package logica jo
Package logica joPackage logica jo
Package logica jo
 
Interpolaion c++
Interpolaion c++Interpolaion c++
Interpolaion c++
 
Ejercicios en Netbeans
Ejercicios en NetbeansEjercicios en Netbeans
Ejercicios en Netbeans
 
Curso Drupal. Creacion de modulos en Drupal
Curso Drupal. Creacion de modulos en DrupalCurso Drupal. Creacion de modulos en Drupal
Curso Drupal. Creacion de modulos en Drupal
 
7
77
7
 
05. Creando e implementando objetos y métodos
05. Creando e implementando objetos y métodos05. Creando e implementando objetos y métodos
05. Creando e implementando objetos y métodos
 
Ejercicios Python parte 4
Ejercicios Python parte 4Ejercicios Python parte 4
Ejercicios Python parte 4
 
Funcionesenlenguaje c
Funcionesenlenguaje cFuncionesenlenguaje c
Funcionesenlenguaje c
 
Twig, el nuevo motor de plantillas de Drupal 8
Twig, el nuevo motor de plantillas de Drupal 8Twig, el nuevo motor de plantillas de Drupal 8
Twig, el nuevo motor de plantillas de Drupal 8
 
Guia para examen java
Guia para examen javaGuia para examen java
Guia para examen java
 

Destacado

Siete problemas que ya han resuelto los ecommerce de referencia
Siete problemas que ya han resuelto los ecommerce de referenciaSiete problemas que ya han resuelto los ecommerce de referencia
Siete problemas que ya han resuelto los ecommerce de referenciaSemmantica
 
Cómo configurar el seo de tu drupal
Cómo configurar el seo de tu drupal  Cómo configurar el seo de tu drupal
Cómo configurar el seo de tu drupal Hiberus Tecnologia
 
Inciación a Drupal 8
Inciación a Drupal 8Inciación a Drupal 8
Inciación a Drupal 8Julian Valero
 
Taller SEO para Prestashop Congreso Web 16
Taller SEO para Prestashop Congreso Web 16Taller SEO para Prestashop Congreso Web 16
Taller SEO para Prestashop Congreso Web 16Victor Berroya
 
¿Cómo diseñar una estrategia SEO?
¿Cómo diseñar una estrategia SEO?¿Cómo diseñar una estrategia SEO?
¿Cómo diseñar una estrategia SEO?Lakil Essady
 
Taller Email Marketing por Javier Mayor en CW16
Taller Email Marketing por Javier Mayor en CW16Taller Email Marketing por Javier Mayor en CW16
Taller Email Marketing por Javier Mayor en CW16Hiberus Tecnologia
 
"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16
"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16
"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16Inma Ferragud
 
Redes sociales profesionales: estrategias para pymes y negocios B2B
Redes sociales profesionales: estrategias para pymes y negocios B2BRedes sociales profesionales: estrategias para pymes y negocios B2B
Redes sociales profesionales: estrategias para pymes y negocios B2BMaría Lázaro
 
Aprende a medir tu ecommerce con GTM
Aprende a medir tu ecommerce con GTMAprende a medir tu ecommerce con GTM
Aprende a medir tu ecommerce con GTMCarlos Rabadán
 
Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?
Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?
Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?MOV Marketing
 
SEO para E-COMMERCE por Natzir y Dani Pinillos
SEO para E-COMMERCE por Natzir y Dani PinillosSEO para E-COMMERCE por Natzir y Dani Pinillos
SEO para E-COMMERCE por Natzir y Dani PinillosNatzir Turrado
 
Wordpress para Bloggers: De cero a héroe
Wordpress para Bloggers: De cero a héroeWordpress para Bloggers: De cero a héroe
Wordpress para Bloggers: De cero a héroemisstechin
 
CW15-Charla-Clausura-CalvoConBarba
CW15-Charla-Clausura-CalvoConBarbaCW15-Charla-Clausura-CalvoConBarba
CW15-Charla-Clausura-CalvoConBarbaLucas Aisa
 
Lisandro Caravaca en Congreso Web Zaragoza 2015
Lisandro Caravaca en Congreso Web Zaragoza 2015Lisandro Caravaca en Congreso Web Zaragoza 2015
Lisandro Caravaca en Congreso Web Zaragoza 2015Lisandro Caravaca
 
CRM y Big Data: el nuevo cliente vitaminado
CRM y Big Data: el nuevo cliente vitaminadoCRM y Big Data: el nuevo cliente vitaminado
CRM y Big Data: el nuevo cliente vitaminadoAndres Karp
 
El Futuro del SEO y cómo llegar a él en el presente
El Futuro del SEO y cómo llegar a él en el presenteEl Futuro del SEO y cómo llegar a él en el presente
El Futuro del SEO y cómo llegar a él en el presenteFernando Angulo
 
Encuentra contenidos como un PRO. Congreso Web 2015 #CW15
Encuentra contenidos como un PRO. Congreso Web 2015 #CW15Encuentra contenidos como un PRO. Congreso Web 2015 #CW15
Encuentra contenidos como un PRO. Congreso Web 2015 #CW15Javier Leiva Aguilera
 
7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...
7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...
7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...Semmantica
 

Destacado (20)

Siete problemas que ya han resuelto los ecommerce de referencia
Siete problemas que ya han resuelto los ecommerce de referenciaSiete problemas que ya han resuelto los ecommerce de referencia
Siete problemas que ya han resuelto los ecommerce de referencia
 
Cómo configurar el seo de tu drupal
Cómo configurar el seo de tu drupal  Cómo configurar el seo de tu drupal
Cómo configurar el seo de tu drupal
 
Inciación a Drupal 8
Inciación a Drupal 8Inciación a Drupal 8
Inciación a Drupal 8
 
Marketing con video #cw16
Marketing con video #cw16Marketing con video #cw16
Marketing con video #cw16
 
Taller SEO para Prestashop Congreso Web 16
Taller SEO para Prestashop Congreso Web 16Taller SEO para Prestashop Congreso Web 16
Taller SEO para Prestashop Congreso Web 16
 
¿Cómo diseñar una estrategia SEO?
¿Cómo diseñar una estrategia SEO?¿Cómo diseñar una estrategia SEO?
¿Cómo diseñar una estrategia SEO?
 
Taller Email Marketing por Javier Mayor en CW16
Taller Email Marketing por Javier Mayor en CW16Taller Email Marketing por Javier Mayor en CW16
Taller Email Marketing por Javier Mayor en CW16
 
"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16
"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16
"Hackeando el algoritmo: innovación en redes sociales". Presentación del #CW16
 
Redes sociales profesionales: estrategias para pymes y negocios B2B
Redes sociales profesionales: estrategias para pymes y negocios B2BRedes sociales profesionales: estrategias para pymes y negocios B2B
Redes sociales profesionales: estrategias para pymes y negocios B2B
 
Aprende a medir tu ecommerce con GTM
Aprende a medir tu ecommerce con GTMAprende a medir tu ecommerce con GTM
Aprende a medir tu ecommerce con GTM
 
Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?
Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?
Piratas, Corsarios y Bucaneros SEO ¿con quién compites por el TOP10 de Google?
 
SEO para E-COMMERCE por Natzir y Dani Pinillos
SEO para E-COMMERCE por Natzir y Dani PinillosSEO para E-COMMERCE por Natzir y Dani Pinillos
SEO para E-COMMERCE por Natzir y Dani Pinillos
 
Seo basado en Analítica web
Seo basado en Analítica webSeo basado en Analítica web
Seo basado en Analítica web
 
Wordpress para Bloggers: De cero a héroe
Wordpress para Bloggers: De cero a héroeWordpress para Bloggers: De cero a héroe
Wordpress para Bloggers: De cero a héroe
 
CW15-Charla-Clausura-CalvoConBarba
CW15-Charla-Clausura-CalvoConBarbaCW15-Charla-Clausura-CalvoConBarba
CW15-Charla-Clausura-CalvoConBarba
 
Lisandro Caravaca en Congreso Web Zaragoza 2015
Lisandro Caravaca en Congreso Web Zaragoza 2015Lisandro Caravaca en Congreso Web Zaragoza 2015
Lisandro Caravaca en Congreso Web Zaragoza 2015
 
CRM y Big Data: el nuevo cliente vitaminado
CRM y Big Data: el nuevo cliente vitaminadoCRM y Big Data: el nuevo cliente vitaminado
CRM y Big Data: el nuevo cliente vitaminado
 
El Futuro del SEO y cómo llegar a él en el presente
El Futuro del SEO y cómo llegar a él en el presenteEl Futuro del SEO y cómo llegar a él en el presente
El Futuro del SEO y cómo llegar a él en el presente
 
Encuentra contenidos como un PRO. Congreso Web 2015 #CW15
Encuentra contenidos como un PRO. Congreso Web 2015 #CW15Encuentra contenidos como un PRO. Congreso Web 2015 #CW15
Encuentra contenidos como un PRO. Congreso Web 2015 #CW15
 
7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...
7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...
7 implementaciones avanzadas de Google Analytics que no aprovechas en tu nego...
 

Similar a Charla congreso web introducción programación funcional en JavaScript

Similar a Charla congreso web introducción programación funcional en JavaScript (20)

11 Funciones
11 Funciones11 Funciones
11 Funciones
 
Capítulo 6 funciones y procedimiento
Capítulo 6 funciones y procedimientoCapítulo 6 funciones y procedimiento
Capítulo 6 funciones y procedimiento
 
Funciones en C
Funciones en CFunciones en C
Funciones en C
 
FUNCIONES LENGUAJE C
FUNCIONES LENGUAJE CFUNCIONES LENGUAJE C
FUNCIONES LENGUAJE C
 
07 funciones
07 funciones07 funciones
07 funciones
 
Módulo 4 (sin estilo)
Módulo 4 (sin estilo)Módulo 4 (sin estilo)
Módulo 4 (sin estilo)
 
C ++
C ++C ++
C ++
 
El lenguaje C++ (1).ppt
El lenguaje C++ (1).pptEl lenguaje C++ (1).ppt
El lenguaje C++ (1).ppt
 
El lenguaje C++.ppt
El lenguaje C++.pptEl lenguaje C++.ppt
El lenguaje C++.ppt
 
Módulo 4
Módulo 4Módulo 4
Módulo 4
 
Módulo 4
Módulo 4Módulo 4
Módulo 4
 
Funciones en Lenguaje C
Funciones en Lenguaje CFunciones en Lenguaje C
Funciones en Lenguaje C
 
C# calculadora
C# calculadoraC# calculadora
C# calculadora
 
Unidad2
Unidad2Unidad2
Unidad2
 
Operaciones Básicas
Operaciones BásicasOperaciones Básicas
Operaciones Básicas
 
Lenguaje de programacion C++ 2
Lenguaje de programacion C++ 2Lenguaje de programacion C++ 2
Lenguaje de programacion C++ 2
 
Lenguajesdeprogramacion c nivel1-unidad2
Lenguajesdeprogramacion c nivel1-unidad2Lenguajesdeprogramacion c nivel1-unidad2
Lenguajesdeprogramacion c nivel1-unidad2
 
Operaciones Basicas C++
Operaciones Basicas C++Operaciones Basicas C++
Operaciones Basicas C++
 
Lenguajesdeprogramacion c nivel1-unidad2
Lenguajesdeprogramacion c nivel1-unidad2Lenguajesdeprogramacion c nivel1-unidad2
Lenguajesdeprogramacion c nivel1-unidad2
 
Lenguajes De Programacion C nivel1-unidad2
Lenguajes De Programacion C nivel1-unidad2Lenguajes De Programacion C nivel1-unidad2
Lenguajes De Programacion C nivel1-unidad2
 

Último

Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)ssuser563c56
 
CENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdf
CENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdfCENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdf
CENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdfpaola110264
 
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdfPresentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdfMIGUELANGELCONDORIMA4
 
Manual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfManual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfedsonzav8
 
Seleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSeleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSaulSantiago25
 
Introducción a los sistemas neumaticos.ppt
Introducción a los sistemas neumaticos.pptIntroducción a los sistemas neumaticos.ppt
Introducción a los sistemas neumaticos.pptEduardoCorado
 
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdfReporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdfMikkaelNicolae
 
AMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptx
AMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptxAMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptx
AMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptxLuisvila35
 
Curso intensivo de soldadura electrónica en pdf
Curso intensivo de soldadura electrónica  en pdfCurso intensivo de soldadura electrónica  en pdf
Curso intensivo de soldadura electrónica en pdfFernandaGarca788912
 
Presentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdfPresentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdfMirthaFernandez12
 
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONALCHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONALKATHIAMILAGRITOSSANC
 
clases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfclases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfDanielaVelasquez553560
 
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdfAnthonyTiclia
 
Magnetismo y electromagnetismo principios
Magnetismo y electromagnetismo principiosMagnetismo y electromagnetismo principios
Magnetismo y electromagnetismo principiosMarceloQuisbert6
 
Fe_C_Tratamientos termicos_uap _3_.ppt
Fe_C_Tratamientos termicos_uap   _3_.pptFe_C_Tratamientos termicos_uap   _3_.ppt
Fe_C_Tratamientos termicos_uap _3_.pptVitobailon
 
Una estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTUna estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTFundación YOD YOD
 
Normas para los aceros basados en ASTM y AISI
Normas para los aceros basados en ASTM y AISINormas para los aceros basados en ASTM y AISI
Normas para los aceros basados en ASTM y AISIfimumsnhoficial
 
sistema de construcción Drywall semana 7
sistema de construcción Drywall semana 7sistema de construcción Drywall semana 7
sistema de construcción Drywall semana 7luisanthonycarrascos
 
Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.ALEJANDROLEONGALICIA
 
Diapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuestaDiapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuestajeffsalazarpuente
 

Último (20)

Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
 
CENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdf
CENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdfCENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdf
CENTROIDES Y MOMENTOS DE INERCIA DE AREAS PLANAS.pdf
 
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdfPresentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
 
Manual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfManual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdf
 
Seleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSeleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusibles
 
Introducción a los sistemas neumaticos.ppt
Introducción a los sistemas neumaticos.pptIntroducción a los sistemas neumaticos.ppt
Introducción a los sistemas neumaticos.ppt
 
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdfReporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdf
 
AMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptx
AMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptxAMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptx
AMBIENTES SEDIMENTARIOS GEOLOGIA TIPOS .pptx
 
Curso intensivo de soldadura electrónica en pdf
Curso intensivo de soldadura electrónica  en pdfCurso intensivo de soldadura electrónica  en pdf
Curso intensivo de soldadura electrónica en pdf
 
Presentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdfPresentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdf
 
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONALCHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
 
clases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfclases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdf
 
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
 
Magnetismo y electromagnetismo principios
Magnetismo y electromagnetismo principiosMagnetismo y electromagnetismo principios
Magnetismo y electromagnetismo principios
 
Fe_C_Tratamientos termicos_uap _3_.ppt
Fe_C_Tratamientos termicos_uap   _3_.pptFe_C_Tratamientos termicos_uap   _3_.ppt
Fe_C_Tratamientos termicos_uap _3_.ppt
 
Una estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTUna estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NIST
 
Normas para los aceros basados en ASTM y AISI
Normas para los aceros basados en ASTM y AISINormas para los aceros basados en ASTM y AISI
Normas para los aceros basados en ASTM y AISI
 
sistema de construcción Drywall semana 7
sistema de construcción Drywall semana 7sistema de construcción Drywall semana 7
sistema de construcción Drywall semana 7
 
Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.
 
Diapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuestaDiapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuesta
 

Charla congreso web introducción programación funcional en JavaScript

  • 1. Introducción a la programación funcional en JavaScript
  • 3. Índice 1. Introducción (primeros ejercicios y conceptos) 2. Trabajando con arrays sin bucles 3. Teoría de Categorías 4. Ejercicio final (App web vídeos: React + FP) 5. Conclusiones
  • 6. ‘’ La programación funcional es un paradigma de programación que se basa en el uso de funciones modeladas como funciones matemáticas. La esencia es que los programas son la combinación de expresiones. Una expresión puede ser un valor concreto, variables y también funciones.
  • 8. ‘’ Una función es una relación entre un conjunto de posibles entradas y un conjunto de posibles salidas. La función en sí misma, representa la relación.
  • 9. Gaviotas Unir: unir dos bandadas de gaviotas en una sola Engendrar: la bandada se multiplica por el número de gaviotas que engendra cada una
  • 10. var Bandada = function(n) { this.gaviotas = n } Bandada.prototype.unir = function(otra) { this.gaviotas += otra.gaviotas; return this; } Bandada.prototype.engendrar = function(otra) { this.gaviotas = this.gaviotas * otra.gaviotas; return this; } var bandada1 = new Bandada(4); var bandada2 = new Bandada(2); var bandada3 = new Bandada(0); var resultado = bandada1.unir(bandada3) .engendrar(bandada2).unir(bandada1.engendrar(bandada2)).gaviotas; //=> 32
  • 11. var unir = function(bandada_x, bandada_y) { return bandada_x + bandada_y; }; var engendrar = function(bandada_x, bandada_y) { return bandada_x * bandada_y; }; var bandada_a = 4; var bandada_b = 2; var bandada_c = 0; var result = unir( engendrar(bandada_b, unir(bandada_a, bandada_c)), engendrar(bandada_a, bandada_b) ); //=>16
  • 12. var sumar = function(x, y) { return x + y; }; var multiplicar = function(x, y) { return x * y; }; var bandada_a = 4; var bandada_b = 2; var bandada_c = 0; var result = sumar( multiplicar(bandada_b, sumar(bandada_a, bandada_c)), multiplicar(bandada_a, bandada_b) ); //=>16
  • 13. // associative sumar(sumar(x, y), z) === sumar(x, sumar(y, z)); // commutative sumar(x, y) === sumar(y, x); // identity sumar(x, 0) === x; // distributive multiplicar(x, sumar(y,z)) === sumar(multiplicar(x, y), multiplicar(x, z));
  • 14. Funciones puras Una función pura es una función que, dada la misma entrada, siempre devuelve la misma salida y no tiene ningún efecto colateral.
  • 15. ¿Qué es la programación funcional, otra vez? En gran medida, programas con funciones puras: funciones que reciben valores de entrada, devuelve valores de salida, y no hacen de más.
  • 16. El problema: los efectos colaterales
  • 17. Una función pura: libre de efectos colaterales function add(x,y) { return x + y; }
  • 18. Una función impura: corrupta (no declara todo lo que hace realmente) function add(x,y) { var z = x + y; console.log('result of the sum: ', z); return z; }
  • 19. // pure xs.slice(0,3) //=> [1,2,3] xs.slice(0,3) //=> [1,2,3] xs.slice(0,3) //=> [1,2,3] // impure xs.splice(0,3) //=> [1,2,3] xs.splice(0,3) //=> [4,5] xs.splice(0,3) //=> [] var xs = [1,2,3,4,5]
  • 20. // impure var minimum = 21; var checkAge = function(age) { return age >= minimum; } // pure var checkAge = function(age) { var minimum = 21; return age >= minimum; }
  • 21. // impure var greeting = function(name) { console.log("hi, " + name + "!") } // pure var greeting = function(name) { return "hi, " + name + "!"; } console.log(greeting("Jonas"))
  • 22. ‘’ Una función es una relación entre un conjunto de posibles entradas y un conjunto de posibles salidas. La función en sí misma, representa la relación. Recordatorio
  • 23. Una entrada, una salida ... (-2, -1) (0 , 0 ) (2 , 1 ) (4 , 2 ) (8 , 4 ) ... Dominio Rango … -2 0 2 4 8 ... … -1 0 1 2 4 ...
  • 24. Una entrada, una salida var toLowerCase = {"A":"a", "B": "b", "C": "c", "D": "d", "E": "e", "D": "d"} toLowerCase["C"] //=> "c" var isPrime = {1: false, 2: true, 3: true, 4: false, 5: true, 6: false} isPrime[3] //=> true
  • 25. ¿Y si hay múltiples argumentos? //+ add :: [Number, Number] -> Number var add = function(numbers) { return numbers[0] + numbers[1] }
  • 26. ¿Y si hay múltiples argumentos? //+ add :: ? -> Number var add = function() { return arguments[0] + arguments[1] }
  • 27. ‘’ Función “curried”: “Una función que devuelve una nueva función hasta que recibe todos sus argumentos” Currying
  • 28. Currying //+ add :: Number -> Number -> Number var add = curry(function(x, y) { return x + y })
  • 29. Currying add //=> function(x,y) { return x + y } add(2,3) //=> 5 add(2) //=> function(y) { return 2 + y }
  • 30. Currying //+ get :: String -> {String: a} -> a var get = curry(function(prop, obj) { return obj[prop]; }) var user = {id: 15, name: "Jorge Aznar", email: "jaznar@email.com"} get('email', user) //=> jaznar@email.com //+ email :: {String: a} -> a var email = get('email') //=> function(obj){ return obj[‘email’] } email(user) //=> jaznar@email.com
  • 31. Currying //+ filter :: (a -> Bool) -> [a] -> [a] var filter = curry(function(f, xs) { return xs.filter(f); }) //+ odds :: [a] -> [a] var odds = filter(isOdd) odds([1,2,3]) //=> [1, 3]
  • 32. Currying var emails = map(email) var users = [jesus, jorge, ja, jbalbas] emails(users) //=> ["jesus@lopez.org", "jorge@aznar.net", "ja@samitier.com", "jota@balbas.es"]
  • 33. Currying //+ goodArticles :: [Article] -> [Article] var goodArticles = function(articles) { return _.filter(articles, function(article){ return _.isDefined(article) }) } //+ goodArticles :: [Article] -> [Article] var goodArticles = filter(isDefined)
  • 34. Currying //+ getChildren :: DOM -> [DOM] var getChildren = function(el) { return el.childNodes } //+ getALLChildren :: [DOM] -> [[DOM]] var getAllChildren = function(els) { return _.map(els, function(el) { return getChildren(el) }) } var getChildren = get('childNodes') var getAllChildren = map(getChildren)
  • 35. Composición La composición de funciones es aplicar una función a los resultados de otra
  • 36. Composición //+ compose :: (b -> c) -> (a -> b) -> a -> c var compose = curry(function(f, g, x) { return f(g(x)) })
  • 37. Composición //+ head :: [a] -> a var head = function(x) { return x[0] } //+ last :: [a] -> a var last = compose(head, reverse) last(['Java', 'JavaScript', 'PHP']) //=> PHP
  • 38. Composición //+ wordCount :: String -> Number var wordCount = function(sentence) { var count = split(' ', sentence) return length(count) } //+ wordCount :: String -> Number var wordCount = compose(length, split(' ')) wordCount("Soy una frase de 6 palabras") //=> 6
  • 39. Composición 'B' <- 'b' <- 'Congreso Web' compose(toUpperCase, last)('Congreso Web')
  • 40. Composición // Ley asociativa compose(f, compose(g, h)) == compose(compose(f, g), h)
  • 41. Composición compose(toUpperCase, compose(head, reverse)) // ó compose(compose(toUpperCase, head), reverse)
  • 42. Composición //+ lastUpper :: [String] -> String var lastUpper = compose(toUpperCase, head, reverse) lastUpper(['Java', 'PHP', 'JavaScript']) //=> 'JAVASCRIPT' //+ lastUpper :: [String] -> String var loudLastUpper = compose(exclaim, toUpperCase, head, reverse) loudLastUpper(['Java', 'PHP', 'JAVASCRIPT']) //=> 'JAVASCRIPT!'
  • 43. Composición ? <- map(['JavaScript', 'Rust']) <- ['JavaScript', 'Rust'] <- ['Rust', 'JavaScript'] compose(toUpperCase, map, reverse)(['Rust', 'JavaScript'])
  • 44. Composición ['JAVASCRIPT', 'RUST'] <- ['JavaScript', 'Rust'] <- ['Rust', 'JavaScript'] compose(map(toUpperCase), reverse)(['Rust', 'JavaScript'])
  • 46. Inciso: Trabajar con colecciones (sin bucles) La mayoría de las operaciones que hacemos se pueden conseguir con 5 funciones: ▣ map ▣ filter ▣ reduce ▣ concatAll ▣ zip Prácticamente, todos los bucles se pueden sustituir por estas funciones.
  • 47. Ejercicios Vamos a practicar el uso de las 5 funciones https://github.com/RPallas92/congreso-web-2016 Directorio parte2
  • 49. Teoría de Categorías Es una rama abstracta de las matemáticas que formaliza conceptos de diferentes ramas como teoría de conjuntos, teoría de tipos, teoría de grupos, lógica y más. Principalmente, se trabaja con objetos, morfismos y transformaciones. (Similitud con la programación)
  • 50. Categoría Es una colección con los siguientes componentes: ▣ Una colección de objetos ▣ Una colección de morfismos ▣ Una noción de composición de los morfismos ▣ Un morfismo en concreto, llamado identidad
  • 51. Categoría ▣ La Teoría de Categorías es suficientemente abstracta para modelar muchas cosas, pero vamos a centrarnos en tipos y funciones
  • 52. Categoría Una colección de objetos: ▣ Los objetos serán tipos de datos. String, Boolean, Number, Object. ▣ Boolean como el conjunto [true, false] ▣ Number como el conjunto de todos los posibles valores numéricos
  • 53. Categoría Una colección de morfismos: ▣ Los morfismos serán las funciones normales que escribimos diariamente.
  • 54. Categoría Una noción de composición de los morfismos: ▣ Nuestra función compose, presentada anteriormente ▣ Que compose cumpla la ley asociativa no es casualidad. ▣ Cualquier composición en la Teoría de Categorías debe cumplirla
  • 56. Categoría Un morfismo concreto llamado identidad: ▣ Nueva función id ▣ Recibe una entrada, y la devuelve, nada más var id = function(x) { return x; }; Almacena un valor, será utilizada más adelante
  • 57. Identidad // identity compose(id, f) == compose(f, id) == f; // true ▣ Esta propiedad se cumple para todas las funciones unarias. ▣ Es como la identidad en los números
  • 58. Identidad // identity compose(id, f) == compose(f, id) == f; // true ▣ Esta propiedad se cumple para todas las funciones unarias. ▣ Es como la identidad en los números
  • 60. Objetos ▣ Contenedores/Wrappers para valores ▣ No tienen métodos ▣ No tienen propiedades ▣ Seguramente, no crees los tuyos propios
  • 61. Objetos var Container = function(val) { this.val = val; } //+ Container :: a -> Container(a) Container.of = function(x) { return new Container(x); }; Container.of(3) //=> Container {val: 3}
  • 63. Objetos //+ map :: (a -> b) -> Container(a) -> Container(b) Container.prototype.map = function(f) { return Container.of(f(this.val)); } Container.of("flamethrower").map(function(s){ return capitalize(s) }) //=> Container(“Flamethrower”)
  • 64. Objetos //+ map :: (a -> b) -> Container(a) -> Container(b) Container.prototype.map = function(f) { return Container.of(f(this.val)); } Container.of("flamethrower").map(capitalize) //=> Container(“Flamethrower”)
  • 67. Objetos //+ map :: Functor F => (a -> b) -> F a -> F b var map = _.curry(function(f, obj) { return obj.map(f) }) Container.of(3).map(add(1)) // Container(4) map(add(1), Container.of(3)) // Container(4)
  • 69. ‘’ “Un objeto o estructura de datos que puede ser mapeada” ▣ Funciones: map FUNCTOR
  • 70. Aquellos problemáticos null //+ getElement :: String -> DOM var getElement = document.querySelector //+ getNameParts :: String -> [String] var getNameParts = compose(split(' '), getText, getElement) getNameParts('#full_name') //=> ['José', 'Luis', 'Bárcenas', 'Gutiérrez']
  • 71. Aquellos problemáticos null //+ getElement :: String -> DOM var getElement = document.querySelector //+ getNameParts :: String -> [String] var getNameParts = compose(split(' '), getText, getElement) getNameParts('#fullname') //=> BOOOOOOOOMM!!!!!!
  • 72. Maybe ▣ Captura un null check ▣ Es posible que el valor no esté ▣ A veces tienen dos subclases: Just/Nothing ▣ En otros lenguajes se llama Option
  • 73. Maybe //+ map :: (a -> b) -> Maybe(a) -> Maybe(b) var _Maybe.prototype.map = function(f) { return this.val ? Maybe.of(f(this.val)) : Maybe.of(null); } map(capitalize, Maybe.of("flamethrower")) //=> Maybe(“Flamethrower”)
  • 74. Maybe //+ map :: (a -> b) -> Maybe(a) -> Maybe(b) var _Maybe.prototype.map = function(f) { return this.val ? Maybe.of(f(this.val)) : Maybe.of(null); } map(capitalize, Maybe.of(null)) //=> Maybe(null)
  • 75. Maybe //+ firstMatch :: String -> String var firstMatch = compose(first, match(/java/g)) firstMatch("python") //=> BOOOM!!!
  • 76. Maybe //+ firstMatch :: String -> Maybe(String) var firstMatch = compose(map(first), Maybe.of, match(/java/g)) firstMatch("python") //=> Maybe(null)
  • 77. Maybe //+ firstMatch :: String -> Maybe(String) var firstMatch = compose(map(first), Maybe.of, match(/java/g)) firstMatch("javascript") //=> Maybe(“java”)
  • 78. Either ▣ Utilizado para manejo de excepciones pura ▣ Es como Maybe, pero con un mensaje de error embebido ▣ Tienen dos subclases: Left/Right ▣ Mapea la función sobre el Right, ignora el Left
  • 79. Either map(function(x) { return x + 1; }, Right.of(2)) //=> Right(3) map(function(x) { return x + 1; }, Left.of(‘some message’)) //=> Left(‘some message’)
  • 80. Either //+ determineAge :: User -> Either(String, Number) var determineAge = function(user){ return user.age ? Right.of(user.age) : Left.of("couldn’t get age"); } //+ yearOlder :: User -> Either(String, Number) var yearOlder = compose(map(add(1)), determineAge) yearOlder({age: 22}) //=> Right(23) var jordiHurtado = {age: null} yearOlder(jordiHurtado) //=> Left("couldn’t get age")
  • 81. IO ▣ Utilizado para lazy computation ▣ Utilizado para manejar los efectos colaterales ▣ Para ejectuar la operación, se debe llamar a runIO ▣ map añade la función a una lista de operaciones a ejecutar
  • 82. IO //+ email_io :: IO(String) var email_io = new IO(function(){ return $("#email").val() }) //+ msg_io :: IO(String) var msg_io = map(concat("Bienvenido "), email_io) msg_io.unsafePerformIO() //=> ”Bienvenido jbalbas@email.net”
  • 84. IO //+ getBgColor :: JSON -> Color var getBgColor = compose(get("background-color"), JSON.parse) //+ bgPref :: _ -> IO(Color) var bgPref = compose(map(getBgColor), Store.get("preferences")) //+ app :: _ -> IO(Color) var app = bgPref() //=> IO() app.unsafePerformIO() //=> #efefef
  • 85. IO //+ email_io :: _ -> IO(String) var email_io = new IO(function(){ return $("#email").val() } //+ getValue :: String -> IO(String) var getValue = function(sel){ return new IO(function(){ return $(sel).val() }); }
  • 86. Task / Future ▣ Se utiliza para operaciones asíncronas ▣ Representa un valor en el tiempo ▣ Para ejecutar la operación, se debe llamar a fork ▣ Fork recibe una función como valor ▣ Se llama a la función con el resultado del Task una vez que lo tiene
  • 87. Task / Future //+ makeHtml :: Post -> HTML var makeHtml = function(post){ return "<div>"+post.title+"</div>"}; //+ page_f :: Future(Html) var page_f = map(makeHtml, http.get('/posts/2')) page_f.fork( function(err) { throw(err) }, function(page){ $('#container').html(page) } )
  • 88. Pointed Functors ▣ Es un Functor con un método of ▣ Of :: a -> F a ▣ Permite poner valores en un contexto mínimo que retiene el valor (o contexto puro) ▣ También llamado pure
  • 89. Pointed Functors ▣ Es un Functor con un método of ▣ Of :: a -> F a ▣ Permite poner valores en un contexto mínimo que retiene el valor (o contexto puro) ▣ También llamado pure
  • 90. Pointed Functors Container.of(2) // Container(2) Maybe.of(reverse) // Maybe(reverse) Future.of(match(/dubstep/)) // Future(match(/dubstep/)) IO.of('hack') // IO(function(){ return 'hack'})
  • 91. Task / Future //+ lineCount :: String -> Number var lineCount = compose(length, split(/n/)) //+ fileLineCount :: String -> Future(Number) var fileLineCount = compose(map(lineCount), readFile) fileLineCount("mydoc.txt").fork(log, log) //=> 34
  • 92. Leyes de los functores // identity map(id) == id // composition compose(map(f), map(g)) == map(compose(f, g))
  • 93. Pregunta Haz una llamada a una api con una id, y obtén un post (puede existir o no)
  • 95. Mónadas ▣ Patrón de diseño utilizado para describir computaciones como series de pasos (o computaciones anidadas) ▣ Utilizadas para gestionar los efectos colaterales ▣ O para controlar la complejidad Funciones: ▣ join ▣ chain
  • 96. Mónadas ▣ join :: M M a -> M a ▣ chain :: (a -> M b) -> M a -> M b Una mónada es un Pointed Functor añadiendo los métodos join y chain
  • 98. Mónadas //+ getTrackingId :: Order -> Maybe(TrackingId) var getTrackingId = compose(Maybe.of, get("tracking_id")) //+ findOrder :: Number -> Maybe(Order) var findOrder = compose(Maybe.of, Api.findOrder) //+ getOrderTracking :: Number -> Maybe(Maybe(TrackingId)) var getOrderTracking = compose(map(getTrackingId), findOrder) //+ renderPage :: Number -> Maybe(Maybe(Html)) var renderPage = compose(map(map(renderTemplate)), getOrderTracking)
  • 99. Mónadas //+ getTrackingId :: Order -> Maybe(TrackingId) var getTrackingId = compose(Maybe.of, get("tracking_id")) //+ findOrder :: Number -> Maybe(Order) var findOrder = compose(Maybe.of, Api.findOrder) //+ getOrderTracking :: Number -> Maybe(TrackingId) var getOrderTracking = compose(join, map(getTrackingId), findOrder) //+ renderPage :: Number -> Maybe(Html) var renderPage = compose(map(renderTemplate), getOrderTracking)
  • 100. Mónadas //+ :: setSearchInput :: String -> IO(_) var setSearchInput = function(x) { return new IO(function() { ("#input").val(x); }) } //+ :: searchTerm :: IO(String) var searchTerm = new IO(function() { getParam("term", location.search) }) //+ :: initSearchForm :: IO(IO(_)) var initSearchForm = map(setSearchInput, searchTerm) initSearchForm.unsafePerformIO().unsafePerformIO();
  • 101. Mónadas //+ :: setSearchInput :: String -> IO(_) var setSearchInput = function(x) { return new IO(function() { ("#input").val(x); }) } //+ :: searchTerm :: IO(String) var searchTerm = new IO(function() { getParam("term", location.search) }) //+ :: initSearchForm :: IO(IO(_)) var initSearchForm = map(setSearchInput, searchTerm) join(initSearchForm).unsafePerformIO();
  • 102. Mónadas //+ sendToServer :: Params -> Future(Response) var sendToServer = httpGet('/upload') //+ uploadFromFile :: String -> Future(Response) var uploadFromFile = compose(join, map(sendToServer), readFile) uploadFromFile("/tmp/my_file.txt").fork(logErr, alertSuccess)
  • 103. Mónadas //+ sendToServer :: Params -> Future(Response) var sendToServer = httpGet('/upload') //+ uploadFromFile :: String -> Future(Response) var uploadFromFile = compose(join, map(sendToServer), join, map(readFile), askUser) uploadFromFile('what file?').fork(logErr, alertSuccess)
  • 104. Mónadas //+ chain :: (a -> M b) -> M a -> M b var chain = function(f) { return compose(join, map(f)) } // también llamado flatMap
  • 105. Mónadas //+ sendToServer :: Params -> Future(Response) var sendToServer = httpGet('/upload') //+ uploadFromFile :: String -> Future(Response) var uploadFromFile = compose(chain(sendToServer), chain(readFile), askUser) uploadFromFile('what file?').fork(logErr, alertSuccess)
  • 106. Functores aplicativos ▣ Ejecutar computaciones completas en un contexto ▣ Permite aplicar un functor a otro Funciones: ▣ ap ▣ liftA2 ▣ liftA3 ▣ lifA..N
  • 107. Functores aplicativos add(Container.of(2), Container.of(3)); //NaN var container_of_add_2 = map(add, Container.of(2)); // Container(add(2))
  • 108. Functores aplicativos map(add(1), Container(2)) //=> Container(3) add(Container.of(2), Container.of(3)); //NaN map(add, Container(2)) //=> Container(add(2))
  • 109. Functores aplicativos ▣ ap :: A (a -> b) -> A a -> A b ▣ Un functor aplicativo es un Pointed Functor con un método ap
  • 113. Functores aplicativos var loadPage = _.curry(function(products, reviews){ render(products.zip(reviews) }) Future.of(loadPage) .ap(Api.get('/products')) .ap(Api.get('/reviews'))
  • 114. Functores aplicativos var getVal = compose(Maybe, get('value'), document.querySelector) var save = _.curry(function(email, pass){ return User(email, pass) }) Maybe.of(save).ap(getVal('#email')).ap(getVal('#password')) //=> Maybe(user)
  • 115. Functores aplicativos var getVal = compose(Maybe, pluck('value'), document.querySelector) var save = _.curry(function(email, pass){ return User(email, pass) }) liftA2(save, getVal('#email'), getVal('#password')) //=> Maybe(user)
  • 118. Aplicación buscador de vídeos Youtube ▣ Vista: React ▣ Manipulación de datos: Ramda ▣ Maybe: folktale/data.maybe ▣ Either: folktale/data.either ▣ Task: folktale/data.task
  • 119. React ▣ Biblioteca para crear interfaces de usuario en JavaScript ▣ Simple ▣ Declarativa ▣ Modular: componentes reusables ▣ Utiliza la composición de los componentes para crear nuevos ▣ https://facebook.github.io/react
  • 120. Ramda ▣ Biblioteca para programación funcional práctica en JavaScript ▣ Similar a lodash o undescore ▣ Todas las funciones están curried ▣ Parámetros de las funciones ordenados para favorecer el curry ▣ Trabaja bien con implementaciones Mónadas, functores, etc. http://ramdajs.com
  • 121. Folktale ▣ Suite de bibliotecas para programación funcional genérica en JavaScript ▣ Utilizaremos su implementación de □ Maybe □ Either □ Task (Future) http://folktalejs.org
  • 122. App vídeos YouTube ▣ Permite buscar vídeos “al vuelo” ▣ Muestra los vídeos como un grid ▣ Al hacer clic sobre uno, se abre su página de YouTube
  • 124. App vídeos YouTube ▣ Permite buscar vídeos “al vuelo” ▣ Muestra los vídeos como un grid ▣ Al hacer clic sobre uno, se abre su página de YouTube
  • 126. Conclusiones ▣ Crear funciones pequeñas (Divide and conquer (and reuse)) ▣ Composición de esas funciones ▣ Utilizar funciones puras ▣ Tener aislada la parte impura del programa ▣ Estilo declarativo vs imperativo