Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introducción a Clojure

Introducción a Clojure

Una introducción a Clojure y por qué usar programación funcional

Denis Fuenzalida

June 25, 2013
Tweet

More Decks by Denis Fuenzalida

Other Decks in Programming

Transcript

  1. Introducción a Clo Introducción a Cloj jure 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]
  2. “ “Martin Fowler hace la siguiente Martin Fowler hace la

    siguiente observación: observación: El verdadero legado de Java será El verdadero legado de Java será la plataforma, no el lenguaje... la plataforma, no el lenguaje...
  3. ...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 llegue a superar a Java llegue 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.next Java.next” ” http://nealford.com/pub.html http://nealford.com/pub.html
  4. # db/seeds.rb # db/seeds.rb User.find_each(& User.find_each(&:destroy :destroy) ) User.create( User.create(email

    email: : '[email protected]' '[email protected]', , password password: : '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 = false false } }
  5. var var obj obj = { = { "flammable" "flammable":

    : "inflammable" "inflammable", , "duh" "duh": : "no duh" "no duh" }; }; $ $.each( obj, .each( obj, function function( ( key key, , value value ) { ) { alert( key + alert( key + ": " ": " + value ); + value ); }); });
  6. “ “Vale la pena aprender Lisp por Vale la pena

    aprender Lisp por la la profunda experiencia de profunda experiencia de iluminación iluminación que obtendrás que obtendrás cuando finalmente lo entiendas... cuando finalmente lo entiendas...
  7. ...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 utilizas mucho.” lo utilizas mucho.” – – Eric S. Raymond en “ Eric S. Raymond en “Como convertirse en Hacker Como convertirse en Hacker” ” http://www.catb.org/esr/faqs/hacker-howto.html http://www.catb.org/esr/faqs/hacker-howto.html
  8. • • Un Lisp, para programación funcional Un Lisp, para

    programación funcional • • Simbiótico con una plataforma probada Simbiótico con una plataforma probada • • Diseñado para programación concurrente Diseñado para programación concurrente … … pero no lo encontró, pero no lo encontró, así que lo hizo él mismo así que lo hizo él mismo http://clojure.org/ http://clojure.org/rationale rationale
  9. ;; 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 ( (def def colores colores #{ #{:blanco :azul :rojo :blanco :azul :rojo}) }) (colores (colores :rojo :rojo) ) ;= :rojo ;= :rojo (colores (colores :verde :verde) ) ;= nil ;= nil ( (def def numeros numeros { {:one :one "uno" "uno", , :two :two "dos" "dos" }) }) (numeros (numeros :two :two) ) ;= "dos" ;= "dos"
  10. $ clj $ clj Clojure 1.5.1 Clojure 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=> editores user=> editores [:vim :emacs :sublime] [:vim :emacs :sublime]
  11. 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; } } } }
  12. $ 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
  13. // Clase StringUtils de Apache Commons Lang v2.6 (2011) //

    Clase StringUtils de Apache Commons Lang v2.6 (2011) public class public class StringUtils { StringUtils { public static public static boolean isBlank(String str) { boolean isBlank(String str) { int int strLen strLen; ; if if (str == (str == null null || (strLen = str.length()) == 0) { || (strLen = str.length()) == 0) { return return true true; ; } } for for (int i = 0; i < strLen; i++) { (int i = 0; i < strLen; i++) { if if ((Character.isWhitespace(str.charAt(i)) == ((Character.isWhitespace(str.charAt(i)) == false false)){ )){ return return false false; ; } } } } return return true true; ; } } } }
  14. // Clase StringUtils de Apache Commons Lang v2.6 (2011) //

    Clase StringUtils de Apache Commons Lang v2.6 (2011) public class public class StringUtils { StringUtils { public static public static boolean isBlank(String str) { boolean isBlank(String str) { int int strLen strLen; ; if if (str == (str == null null || (strLen = str.length()) == 0) { || (strLen = str.length()) == 0) { return return true true; ; } } for for (int i = 0; i < strLen; i++) { (int i = 0; i < strLen; i++) { if if ((Character.isWhitespace(str.charAt(i)) == ((Character.isWhitespace(str.charAt(i)) == false false)){ )){ return return false false; ; } } } } return return true true; ; } } } } ;; Implementación en Clojure ;; Implementación en Clojure (defn blank? (defn blank? [str] [str] ( (every? every? #( #(Character/isWhitespace Character/isWhitespace %) str)) %) str))
  15. • • Una secuencia de 1000 números repartidos en 100

    Una secuencia de 1000 números repartidos en 100 vectores de 10 números cada uno vectores de 10 números cada uno • • 10 10 threads threads manipularán estos números manipularán estos números • • Cada thread selecciona 2 posiciones al azar entre dos Cada 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#Examples http://en.wikipedia.org/wiki/Clojure#Examples
  16. ( (defn defn run run [nvecs nitems nthreads niters] [nvecs

    nitems nthreads niters] ( (let let [vec-refs ( [vec-refs (vec vec ( (map map ( (comp comp ref vec) ref vec) ( (partition partition nitems ( nitems (range range (* nvecs nitems))))) (* nvecs nitems))))) swap #( swap #(let let [v1 ( [v1 (rand-int rand-int nvecs) nvecs) v2 ( v2 (rand-int rand-int nvecs) nvecs) i1 ( i1 (rand-int rand-int nitems) nitems) i2 ( i2 (rand-int rand-int nitems)] nitems)] ( (dosync dosync ( (let let [temp ( [temp (nth nth @(vec-refs v1) i1)] @(vec-refs v1) i1)] ( (alter alter (vec-refs v1) (vec-refs v1) assoc i1 ( assoc i1 (nth nth @(vec-refs v2) i2)) @(vec-refs v2) i2)) ( (alter alter (vec-refs v2) (vec-refs v2) assoc i2 temp)))) assoc i2 temp)))) report #( report #(do do ( (prn prn ( (map map deref vec-refs)) deref vec-refs)) ( (println println "Distinct:" "Distinct:" ( (count count ( (distinct distinct ( (apply apply concat ( concat (map map deref vec-refs))))))] deref vec-refs))))))] (report) (report) ( (dorun dorun ( (apply apply pcalls ( pcalls (repeat repeat nthreads #( nthreads #(dotimes dotimes [_ niters] (swap))))) [_ niters] (swap))))) (report))) (report))) (run 100 10 10 100000) (run 100 10 10 100000)
  17. $ 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: 1000 Distinct: 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: 1000 Distinct: 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.
  18. ;; project.clj (Leinengen.org) ;; project.clj (Leinengen.org) ( (defproject defproject 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.html http://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)
  19. • • 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 hoy Clojure tiene eso y más disponible hoy • Rápido como Java y soluciona problemas • Rápido como Java y soluciona problemas complejos complejos
  20. • • Cuando es práctico, se puede interoperar con Cuando

    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. • • ClojureScript ClojureScript, Datomic* y Pedestal* , Datomic* y Pedestal*
  21. $ clj $ clj Clojure 1.5.1 Clojure 1.5.1 user=> user=>

    ( (defn defn palin? palin? [x] (= ( [x] (= (apply apply str ( str (reverse reverse x)) x)) x)) x)) #'user/palin? #'user/palin? user=> user=>( (defn defn both-palin? [n] both-palin? [n] ( (and and (palin? ( (palin? (str str n)) n)) (palin? ( (palin? (Integer/toBinaryString Integer/toBinaryString n)))) n)))) #'user/both-palin? #'user/both-palin? user=> user=> ( (apply apply + ( + (filter filter both-palin? ( both-palin? (range range 1 1000000))) 1 1000000))) 872187 872187
  22. Créditos Créditos Fondo “Concrete Texture” por Ember Studio http://www.flickr.com/photos/emberstudio/7597659330/ Foto

    de Paul Graham por Niall Kennedy http://www.flickr.com/photos/niallkennedy/137275735/ Sasha Grey con el libro de SICP por Ayanami_Rei http://canv.as/p/1i1pr/reply/89490 Rick Hichey en el SF Clojure Users Group por Howard Lewis Ship http://www.flickr.com/photos/hlship/3603090614 Rich Hickey “State, you're doing it wrong” por Pedro Teixeira http://static.intelie.com.br/qconsp2010/presentation.html