44
Introducción a Clo Introducción a Clo j j ure ure Una intro a Clojure y por qué usar programación funcional Una intro a Clojure y por qué usar programación funcional Denis Fuenzalida – Junio de 2013 Denis Fuenzalida – Junio de 2013 [email protected] [email protected]

Introducción a Clojure

Embed Size (px)

DESCRIPTION

Una introducción a Clojure y por qué usar programación funcional. Mi experiencia al conocer Clojure luego de haber sido desarrollador de aplicaciones con Java, Grails y Rails.

Citation preview

Page 1: Introducción a Clojure

Introducción a CloIntroducción a Clo jj ureureUna intro a Clojure y por qué usar programación funcionalUna intro a Clojure y por qué usar programación funcional

Denis Fuenzalida – Junio de 2013Denis Fuenzalida – Junio de [email protected]@gmail.com

Page 2: Introducción a Clojure
Page 3: Introducción a Clojure

““ Martin Fowler hace la siguiente Martin Fowler hace la siguiente obser vación: obser vación:

El verdadero legado de Java será El verdadero legado de Java será la plataforma, no el lenguaje. . .la plataforma, no el lenguaje. . .

Page 4: Introducción a Clojure

. . .ahora mismo, hay más de 200 . . .ahora mismo, hay más de 200 lenguajes que corren sobre la JVM lenguajes que corren sobre la JVM

y y es inevitable que uno de ellos es inevitable que uno de ellos l legue a superar a Javallegue a superar a Java como la como la

mejor forma de programar la JVM.”mejor forma de programar la JVM.”

– – Neal Ford en “Neal Ford en “Java.nextJava.next””http://nealford.com/pub.htmlhttp://nealford.com/pub.html

Page 5: Introducción a Clojure

# db/seeds.rb# db/seeds.rb

User.find_each(&User.find_each(&:destroy:destroy))User.create(User.create(emailemail: : '[email protected]''[email protected]', , passwordpassword: : 'l33t''l33t'))User.find_each(&:User.find_each(&:reset_authentication_token!reset_authentication_token!))

// ApprovalService.groovy// ApprovalService.groovy

approvers.findAll{ it.userId == approval.userId }.each{approvers.findAll{ it.userId == approval.userId }.each{ it.removable = it.removable = falsefalse}}

Page 6: Introducción a Clojure

var var objobj = { = { "flammable""flammable": : "inflammable""inflammable",, "duh""duh": : "no duh""no duh"};};

$$.each( obj, .each( obj, functionfunction( ( keykey, , valuevalue ) { ) { alert( key + alert( key + ": "": " + value ); + value );});});

Page 7: Introducción a Clojure

““ Vale la pena aprender Lisp por Vale la pena aprender Lisp por la la profunda experiencia de profunda experiencia de i luminacióniluminación que obtendrás que obtendrás cuando finalmente lo entiendas. . .cuando finalmente lo entiendas. . .

Page 8: Introducción a Clojure

. . .esa experiencia te hará un mejor . . .esa experiencia te hará un mejor por programador el resto de tus por programador el resto de tus

días, incluso si en realidad nunca días, incluso si en realidad nunca lo uti l izas mucho.” lo uti l izas mucho.”

– – Eric S. Raymond en “Eric S. Raymond en “Como convertirse en HackerComo convertirse en Hacker””http://www.catb.org/esr/faqs/hacker-howto.htmlhttp://www.catb.org/esr/faqs/hacker-howto.html

Page 9: Introducción a Clojure

http://paulgraham.es/ensayos/la-venganza-de-los-nerds.htmlhttp://paulgraham.es/ensayos/la-venganza-de-los-nerds.html

Page 10: Introducción a Clojure

http://mitpress.mit.edu/sicp/http://mitpress.mit.edu/sicp/

https://github.com/sarabander/sicp-pdfhttps://github.com/sarabander/sicp-pdf

Page 11: Introducción a Clojure

http://xkcd.com/297/http://xkcd.com/297/

Page 12: Introducción a Clojure

• • Un Lisp, para programación funcionalUn Lisp, para programación funcional• • Simbiótico con una plataforma probadaSimbiótico con una plataforma probada• • Diseñado para programación concurrenteDiseñado para programación concurrente

… … pero no lo encontró, pero no lo encontró, así que lo hizo él mismoasí que lo hizo él mismo

http://clojure.org/http://clojure.org/rationalerationale

Page 13: Introducción a Clojure

;; Esta linea es un comentario;; Esta linea es un comentario

(+ 1 2 3)(+ 1 2 3);= 6;= 6

(+ (* 2 3 4) 100)(+ (* 2 3 4) 100);= 124;= 124

((defdef colorescolores #{ #{:blanco :azul :rojo:blanco :azul :rojo})})(colores (colores :rojo:rojo));= :rojo;= :rojo(colores (colores :verde:verde));= nil;= nil

((defdef numerosnumeros { {:one:one "uno""uno", , :two:two "dos""dos" }) })(numeros (numeros :two:two));= "dos";= "dos"

Page 14: Introducción a Clojure

$ clj$ cljClojure 1.5.1Clojure 1.5.1

user=> (def editores [:vim :emacs :sublime])user=> (def editores [:vim :emacs :sublime])#'user/editores#'user/editores

user=> (reverse editores)user=> (reverse editores)(:sublime :emacs :vim)(:sublime :emacs :vim)

user=> (assoc editores 0 "notepad")user=> (assoc editores 0 "notepad")["notepad" :emacs :sublime]["notepad" :emacs :sublime]

user=> editoresuser=> editores[:vim :emacs :sublime][:vim :emacs :sublime]

Page 15: Introducción a Clojure
Page 16: Introducción a Clojure

public class Person {public class Person { private String name;private String name; private Integer age;private Integer age;

public Person() { }public Person() { }

public String getName() { return name; }public String getName() { return name; } public Integer getAge() { return age; }public Integer getAge() { return age; }

public void setName(String name) {public void setName(String name) { this.name = name;this.name = name; }}

public void setAge(Integer age) {public void setAge(Integer age) { this.age = age;this.age = age; }}}}

Page 17: Introducción a Clojure

$ psql myrailsapp_dev$ psql myrailsapp_dev

myrailsapp_dev=# \d projects;myrailsapp_dev=# \d projects;

Table "public.projects"Table "public.projects"

Column | Type Column | Type ------------+-----------------------------------------+----------------------------- id | integer id | integer user_id | integer user_id | integer enabled | boolean enabled | boolean created_at | timestamp without time zone created_at | timestamp without time zone updated_at | timestamp without time zone updated_at | timestamp without time zone

Page 18: Introducción a Clojure

““ Place oriented programming”Place oriented programming”

Page 19: Introducción a Clojure

Programación funcionalProgramación funcional

Page 20: Introducción a Clojure

// Clase StringUtils de Apache Commons Lang v2.6 (2011)// Clase StringUtils de Apache Commons Lang v2.6 (2011)

public classpublic class StringUtils { StringUtils { public staticpublic static boolean isBlank(String str) { boolean isBlank(String str) { int int strLenstrLen;; ifif (str == (str == nullnull || (strLen = str.length()) == 0) { || (strLen = str.length()) == 0) { returnreturn truetrue;; }}

forfor (int i = 0; i < strLen; i++) { (int i = 0; i < strLen; i++) { ifif ((Character.isWhitespace(str.charAt(i)) == ((Character.isWhitespace(str.charAt(i)) == falsefalse)){)){ returnreturn falsefalse;; }} }} returnreturn truetrue;; }}}}

Page 21: Introducción a Clojure

// Clase StringUtils de Apache Commons Lang v2.6 (2011)// Clase StringUtils de Apache Commons Lang v2.6 (2011)

public classpublic class StringUtils { StringUtils { public staticpublic static boolean isBlank(String str) { boolean isBlank(String str) { int int strLenstrLen;; ifif (str == (str == nullnull || (strLen = str.length()) == 0) { || (strLen = str.length()) == 0) { returnreturn truetrue;; }}

forfor (int i = 0; i < strLen; i++) { (int i = 0; i < strLen; i++) { ifif ((Character.isWhitespace(str.charAt(i)) == ((Character.isWhitespace(str.charAt(i)) == falsefalse)){)){ returnreturn falsefalse;; }} }} returnreturn truetrue;; }}}}

;; Implementación en Clojure;; Implementación en Clojure

(defn blank? (defn blank? [str][str] ((every?every? #(#(Character/isWhitespace Character/isWhitespace %) str))%) str))

Page 22: Introducción a Clojure

Programación concurrenteProgramación concurrente

Page 23: Introducción a Clojure

• • Una secuencia de 1000 números repartidos en 100Una secuencia de 1000 números repartidos en 100 vectores de 10 números cada uno vectores de 10 números cada uno

• • 10 10 threadsthreads manipularán estos números manipularán estos números

• • Cada thread selecciona 2 posiciones al azar entre dosCada thread selecciona 2 posiciones al azar entre dos vectores elegidos al azar e intercambia los valores vectores elegidos al azar e intercambia los valores

• • Correr 100.000 iteraciones y ver si ocurren Correr 100.000 iteraciones y ver si ocurren inconsistencias (faltan números, deadlocks...) inconsistencias (faltan números, deadlocks...)

http://en.wikipedia.org/wiki/Clojure#Exampleshttp://en.wikipedia.org/wiki/Clojure#Examples

Page 24: Introducción a Clojure

((defndefn runrun [nvecs nitems nthreads niters] [nvecs nitems nthreads niters] ((letlet [vec-refs ( [vec-refs (vecvec ((mapmap ( (compcomp ref vec) ref vec) ((partitionpartition nitems ( nitems (rangerange (* nvecs nitems))))) (* nvecs nitems))))) swap #(swap #(letlet [v1 ( [v1 (rand-intrand-int nvecs) nvecs) v2 (v2 (rand-intrand-int nvecs) nvecs) i1 (i1 (rand-intrand-int nitems) nitems) i2 (i2 (rand-intrand-int nitems)] nitems)] ((dosyncdosync ((letlet [temp ( [temp (nthnth @(vec-refs v1) i1)] @(vec-refs v1) i1)] ((alteralter (vec-refs v1) (vec-refs v1) assoc i1 (assoc i1 (nthnth @(vec-refs v2) i2)) @(vec-refs v2) i2)) ((alteralter (vec-refs v2) (vec-refs v2) assoc i2 temp))))assoc i2 temp)))) report #(report #(dodo ((prnprn ( (map map deref vec-refs))deref vec-refs)) ((printlnprintln "Distinct:""Distinct:" ((countcount ( (distinctdistinct ((applyapply concat ( concat (mapmap deref vec-refs))))))] deref vec-refs))))))] (report)(report) ((dorundorun ( (apply apply pcalls (pcalls (repeatrepeat nthreads #(nthreads #(dotimesdotimes [_ niters] (swap))))) [_ niters] (swap))))) (report)))(report))) (run 100 10 10 100000)(run 100 10 10 100000)

Page 25: Introducción a Clojure

$ clj concurrente.clj$ clj concurrente.clj ([0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 ([0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] [20 21 22 23 24 25 26 27 28 29] [30 31 32 18 19] [20 21 22 23 24 25 26 27 28 29] [30 31 32 33 34 35 ...33 34 35 .........Distinct: 1000Distinct: 1000

([125 332 171 310 471 980 617 816 282 353]...([125 332 171 310 471 980 617 816 282 353]......[275 947 628 757 650 41 837 676 231 233])...[275 947 628 757 650 41 837 676 231 233])

Distinct: 1000Distinct: 1000

Todos los cambios en los vectores ocurren en transacciones que Todos los cambios en los vectores ocurren en transacciones que usan el sistema de memoria transaccional de Clojure, y por eso usan el sistema de memoria transaccional de Clojure, y por eso después de 100.000 iteraciones, no se pierde ningún número.después de 100.000 iteraciones, no se pierde ningún número.

Page 26: Introducción a Clojure

Simbiosis con JavaSimbiosis con Javay projectosy projectos

Page 27: Introducción a Clojure

;; project.clj (Leinengen.org);; project.clj (Leinengen.org)

((defprojectdefproject lotjm-s3-upload lotjm-s3-upload "0.0.1" "0.0.1" :description:description "A tool to upload files to S3""A tool to upload files to S3" :url:url "http://example.com/FIXME""http://example.com/FIXME" :license:license {:name {:name "Eclipse Public License""Eclipse Public License" :url :url ""http://eclipse.org/legal/epl-v10.htmlhttp://eclipse.org/legal/epl-v10.html""}}

:dependencies:dependencies [[org.clojure/clojure [[org.clojure/clojure "1.4.0""1.4.0"]] [org.clojure/java.jdbc [org.clojure/java.jdbc "0.2.3""0.2.3"]] [mysql/mysql-connector-java [mysql/mysql-connector-java "5.1.6""5.1.6"]] [net.java.dev.jets3t/jets3t [net.java.dev.jets3t/jets3t "0.9.0""0.9.0"]]]]

:main:main lotjm-s3-upload.core) lotjm-s3-upload.core)

Page 28: Introducción a Clojure

Plan de Dominación Mundial:Plan de Dominación Mundial:

ClojureS criptClojureS cript(demo)(demo)

Page 29: Introducción a Clojure

https://github.com/swannodette/chamberedhttps://github.com/swannodette/chambered

Page 30: Introducción a Clojure

https://github.com/dfuenzalida/todo-cljshttps://github.com/dfuenzalida/todo-cljs

Page 31: Introducción a Clojure

ConclusiónConclusión

Page 32: Introducción a Clojure

• • Python, Groovy y Ruby tienen elementos Python, Groovy y Ruby tienen elementos funcionales, Java 8 incluirá lambdas funcionales, Java 8 incluirá lambdas → → Clojure tiene eso y más disponible hoyClojure tiene eso y más disponible hoy

• Rápido como Java y soluciona problemas • Rápido como Java y soluciona problemas complejos complejos

Page 33: Introducción a Clojure

• • Cuando es práctico, se puede interoperar conCuando es práctico, se puede interoperar con todo el ecosistema de Java y sus librerías todo el ecosistema de Java y sus librerías

• Corre donde corra Java: apps de escritorio, • Corre donde corra Java: apps de escritorio, Tomcat, AWS, Heroku, Google App Engine, etc. Tomcat, AWS, Heroku, Google App Engine, etc.

• • ClojureScriptClojureScript, Datomic* y Pedestal*, Datomic* y Pedestal*

Page 34: Introducción a Clojure

Como aprender ClojureComo aprender Clojure

Page 35: Introducción a Clojure
Page 36: Introducción a Clojure
Page 37: Introducción a Clojure
Page 38: Introducción a Clojure
Page 39: Introducción a Clojure

$ clj$ cljClojure 1.5.1Clojure 1.5.1

user=> user=> ((defndefn palin?palin? [x] (= ( [x] (= (applyapply str ( str (reversereverse x)) x)) x)) x))

#'user/palin?#'user/palin?

user=>user=>((defndefn both-palin? [n] both-palin? [n] ((andand (palin? ((palin? (strstr n)) n)) (palin? ((palin? (Integer/toBinaryStringInteger/toBinaryString n)))) n))))

#'user/both-palin?#'user/both-palin?

user=> user=> ((applyapply + ( + (filterfilter both-palin? ( both-palin? (rangerange 1 1000000))) 1 1000000))) 872187872187

Page 40: Introducción a Clojure
Page 41: Introducción a Clojure
Page 42: Introducción a Clojure
Page 43: Introducción a Clojure

FinFin

Page 44: Introducción a Clojure

CréditosCréditosFondo “Concrete Texture” por Ember Studiohttp://www.flickr.com/photos/emberstudio/7597659330/

Foto de Paul Graham por Niall Kennedyhttp://www.flickr.com/photos/niallkennedy/137275735/

Sasha Grey con el libro de SICP por Ayanami_Reihttp://canv.as/p/1i1pr/reply/89490

Rick Hichey en el SF Clojure Users Group por Howard Lewis Shiphttp://www.flickr.com/photos/hlship/3603090614

Rich Hickey “State, you're doing it wrong” por Pedro Teixeirahttp://static.intelie.com.br/qconsp2010/presentation.html