<script src="Slidy/slidy.js"
charset="utf-8" type="text/javascript"></script>
<style type="text/css">
- <!-- your custom style rules -->
- </style>
+ .Comment { color: #00ffff; font-weight: bold; }
+ .Constant { color: #ff40ff; font-weight: bold; }
+ .Statement { color: #009000; font-weight: bold; }
+ .Identifier { color: #8080ff; font-weight: bold; }
+ pre.source { font-family: monospace; color: #000000; background-color: #f9f9f9; }
+ .Special { color: #ff6060; font-weight: bold; }
+ .PreProc { color: #8080ff; font-weight: bold; }
+ .Type { color: #2e8b57; font-weight: bold; }
+ </style>
</head>
<body>
<div class="background">
</div>
<div class="slide cover">
- <br clear="all" />
- <h1> <img src="clojure-icon.gif" alt="Clojure logo" style="align: center; width: 6%; height: 10%" /> Clojure</h1>
- <p><a href="http://slack.codemaniacs.com">Jorge 'slack' Gorbe</a></p>
- <p><a href="mailto:slack@codemaniacs.com">slack@codemaniacs.com</a></p>
+ <br clear="all" />
+ <h1>
+ <img src="clojure-icon.gif" alt="Clojure logo" style="align: center; width: 6%; height: 10%" />
+ Clojure
+ </h1>
+ <p><a href="http://slack.codemaniacs.com">Jorge 'slack' Gorbe</a></p>
+ <p><a href="mailto:slack@codemaniacs.com">slack@codemaniacs.com</a></p>
</div>
+ <div class="slide">
+ <h1>C++ mola, ¿por qué no te gusta?</h1>
+ <ul>
+ <li>Montones de cosas que se intentan resolver en otros lenguajes:
+ <ul>
+ <li>No hay tipo string (y mejor no hablamos de Unicode)</li>
+ <li>No hay sistema de módulos (inclusion de cabeceras via preprocesador)</li>
+ <li>etc</li>
+ </ul>
+ </li>
+ <li>Pero si fuera sólo por esas cosas estaría usando C#
+ <ul>
+ <li>...es más, gran parte de lo que voy a contar sobre programación
+ funcional está entrando poco a poco en C# y encima VS 2010 va a soportar
+ F# (una especie de Ocaml.NET) de serie...</li>
+ </ul>
+ </li>
+ <li>Boilerplate</li></ul>
+ <p>"In computer programming, boilerplate is the term used to describe
+ sections of code that have to be included in many places with little or no
+ alteration. It is more often used when referring to languages which are
+ considered verbose, i.e. the programmer must write a lot of code to do
+ minimal jobs."</p>
+ <p><a href="http://en.wikipedia.org/wiki/Boilerplate_%28text%29#Boilerplate_code">
+ http://en.wikipedia.org/wiki/Boilerplate_%28text%29#Boilerplate_code</a>
+ </p>
+ </div>
+
+ <div class="slide">
+ <h1>C++ mola, ¿por qué no te gusta?</h1>
+ <ul>
+ <li>No hay funciones anónimas => es incómodo usar funciones de orden superior</li>
+ <li>Ejemplo: comprobar si todos los elementos de una colección son iguales a 0
+ <ul class="incremental">
+ <li>A piñón, repetición de código, error-prone, etc (ejemplo con C++0x):
+<pre>bool iguales=true;
+for (auto i=c.begin(); i!=c.end(); ++i) {
+ if (*i != 0) iguales=false;
+}</pre></li>
+ <li><i>Boilerplate</i> a montones si se usan functores (y este ejemplo
+ ni siquiera compilaría tal cual :P)
+<pre>// funcion definida en alguna parte
+bool es_distinto_de_0(T i) { return (i != 0); }
+
+// Y luego en el código...
+bool iguales = (c.end() == std::find_if(c.begin(), c.end(), es_distinto_de_0));
+</pre>
+ </li>
+ <li>Usando funciones anónimas en Clojure
+ <pre>(def iguales (every? #(= 0 %1) c))</pre>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+
+ <div class="slide">
+ <h1>C++ mola, ¿por qué no te gusta?</h1>
+ <ul>
+ <li>Falta un buen sistema de macros</li>
+ <li>Esta carencia se combate tradicionalmente a base de patrones de diseño</li>
+ <li>Algunos los consideran señal de madurez, otros los consideran una señal de alarma:<br />
+ <br />
+ <div class="hbox" style="align:center; height:25%">
+ "When I see patterns in my programs, I consider it a sign of trouble. The
+ shape of a program should reflect only the problem it needs to solve. Any
+ other regularity in the code is a sign, to me at least, that I'm using
+ abstractions that aren't powerful enough - often that I'm generating by
+ hand the expansions of some macro that I need to write."
+ <br />
+ -- Paul Graham
+ </div>
+ </li>
+ </ul>
+ </div>
+
+ <div class="slide">
+ <h1>C++ mola, ¿por qué no te gusta?</h1>
+ <ul class="incremental">
+ <li class="non-incremental">Falta un <b>buen</b> sistema de macros para extender el lenguaje</li>
+ <li>Si pensamos en metaprogramar, es MUY fácil acabar con una mezcla
+ ilegible de macros y templates</li>
+ <li>Quien no me crea, que se lea boost/foreach.hpp
+<pre style="font-size:70%">// 800 líneas (literalmente) de definiciones después...
+#define BOOST_FOREACH(VAR, COL) \
+ BOOST_FOREACH_PREAMBLE() \
+ if (boost::foreach_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else \
+ if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else \
+ if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_END(COL)) {} else \
+ for (bool _foreach_continue = true; \
+ _foreach_continue && !BOOST_FOREACH_DONE(COL); \
+ _foreach_continue ? BOOST_FOREACH_NEXT(COL) : (void)0) \
+ if (boost::foreach_detail_::set_false(_foreach_continue)) {} else \
+ for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true)
+#endif
+</pre>
+ </li>
+ </ul>
+ </div>
+
+
+ <div class="slide">
+ <h1>Es mas... ¿por qué creemos que la OOP es la panacea?</h1>
+ <p>Alexander Stepanov (coautor de la STL) dijo una vez:</p>
+ <ul class="incremental">
+ <li>I find OOP <b>technically unsound</b>. It attempts to decompose the world in
+ terms of interfaces that vary on a single type. To deal with the real
+ problems you need multisorted algebras - families of interfaces that span
+ multiple types.</li>
+ <li>I find OOP <b>philosophically unsound</b>. It claims that everything is an
+ object. Even if it is true it is not very interesting - saying that
+ everything is an object is saying nothing at all.</li>
+ </ul>
+ </div>
+
<div class="slide">
<h1>¿Qué es Clojure?</h1>
<p> Cuatro grandes ideas: </p>
<h1>Clojure corre en la JVM</h1>
<ul>
<li>Compila a <i>bytecode</i>
- <ul><li>Eficiente... relativamente ;-)</li></ul>
+ <ul>
+ <li>Eficiente... relativamente ;-)</li>
+ <li>Es tan rápido como Java si se utilizan type hints para evitar
+ usar la introspección en momentos críticos</li>
+ </ul>
</li>
<li>Los tipos básicos son los de Java
<ul><li>java.lang.String, java.lang.Integer...</li></ul>
<li>El código funcional puro es concurrente <i>per se</i>
<ul><li>No hay estado mutable, por lo tanto no hay condiciones de carrera</li></ul>
</li>
- <li>El acceso al estado mutable se puede controlar mediante transacciones o "agentes"</li>
+ <li>Primitivas novedosas para controlar el acceso al estado mutable:
+ <ul>
+ <li>Software Transactional Memory: implementa actualizaciones síncronas
+ transaccionales a referencias a objetos mutables.
+ </li>
+ <li>Agentes: guardan el acceso a una referencia y la actualizan de forma asíncrona
+ a medida que extraen mensajes de una cola.
+ <ul><li>(nombre desafortunado, nada que ver con IA!)</li></ul>
+ </li>
+ </ul>
+ </li>
</ul>
</div>
</ul>
</li>
<li>Cadenas: <code>"Hola, mundo"</code></li>
+ <li>Regex: <code>#"patron"</code> es un objeto de tipo java.util.regex.Pattern</li>
<li>Keywords: <code>:cosa</code></li>
<li>Símbolos: <code>cosa</code></li>
<li>Booleanos: <code>true</code>,<code>false</code></li>
</li>
<li>Vectores: <code>[1 2 3 4]</code>
<ul>
- <li>Acceso aleatorio:
- <ul><li><code>(def v [1 2 3 4])<br />(v 0) => 1</code></li></ul>
- </li>
+ <li>Acceso aleatorio: </li>
<li>Inserción eficiente al final. ¡Ojo! No son arrays</li>
</ul>
+ <pre>(def v [1 2 3 4])<br />(v 0) => 1</pre>
</li>
<li>Diccionarios: <code>{:a 1, :b 2}</code>
- <ul>
- <li><code>({:a 1, :b 2} :b) => 2</code></li>
- <li><code>({:a 1, :b 2} :x) => nil</code></li>
- </ul>
+ <pre>({:a 1, :b 2} :b) => 2
+({:a 1, :b 2} :x) => nil</pre>
</li>
<li>Conjuntos: <code>#{1 2 :a "blah"}</code> </li>
</ul>
<div class="slide">
<h1>Programas = Estructuras de datos</h1>
<ul>
- <li>Una lista no vacía se considera una llamada a una función, a una forma especial o a una macro</li>
+ <li>Una lista no vacía se considera una llamada a una función, a una forma especial o a una macro
+ <ul>
+ <li>Llamada a funcion: (func arg1 arg2 ... argn)</li>
+ </ul>
+ </li>
<li>Las formas especiales son excepciones a la norma de evaluación de funciones (primero argumentos, luego llamada)
<ul>
<li><code>(def name val)</code>: crea una variable global</li>
<div class="slide">
<h1>Entonces... ¿qué pinta tiene un programa?</h1>
- <font face="monospace">
- <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>ns</b></font> wordcount <font color="#ff6060"><b>(</b></font><font color="#ff00ff"><b>:gen-class</b></font><font color="#ff6060"><b>)</b></font><br />
- <font color="#ff6060"><b>(</b></font><font color="#ff00ff"><b>:use</b></font> clojure.contrib.str-utils<font color="#ff6060"><b>))</b></font><br />
- <br />
- <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>defn</b></font> num-lines <font color="#ff6060"><b>[</b></font>text<font color="#ff6060"><b>]</b></font> <font color="#ff6060"><b>(</b></font><font color="#009000"><b>count</b></font> <font color="#ff6060"><b>(</b></font>re-split <font color="#ff40ff"><b>#"\n"</b></font> text<font color="#ff6060"><b>)))</b></font><br />
- <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>defn</b></font> num-words <font color="#ff6060"><b>[</b></font>text<font color="#ff6060"><b>]</b></font> <font color="#ff6060"><b>(</b></font><font color="#009000"><b>count</b></font> <font color="#ff6060"><b>(</b></font>re-split <font color="#ff40ff"><b>#"\s+"</b></font> text<font color="#ff6060"><b>)))</b></font><br />
- <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>defn</b></font> num-characters <font color="#ff6060"><b>[</b></font>text<font color="#ff6060"><b>]</b></font> <font color="#ff6060"><b>(</b></font><font color="#009000"><b>count</b></font> text<font color="#ff6060"><b>))</b></font><br />
- <br />
- <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>defn</b></font> -main <font color="#ff6060"><b>[</b></font>file<font color="#ff6060"><b>]</b></font><br />
- <font color="#ff6060"><b>(</b></font><font color="#ff6060"><b>let</b></font> <font color="#ff6060"><b>[</b></font>text <font color="#ff6060"><b>(</b></font><font color="#009000"><b>slurp</b></font> file<font color="#ff6060"><b>)]</b></font><br />
- <font color="#ff6060"><b>(</b></font><font color="#009000"><b>println</b></font> <font color="#ff6060"><b>(</b></font><font color="#009000"><b>num</b></font>-lines text<font color="#ff6060"><b>)</b></font> <font color="#ff6060"><b>(</b></font><font color="#009000"><b>num</b></font>-words text<font color="#ff6060"><b>)</b></font> <font color="#ff6060"><b>(</b></font><font color="#009000"><b>num</b></font>-characters text<font color="#ff6060"><b>))))</b></font><br />
- <br />
- <br />
- </font>
-
- </div>
-
- <div class="slide">
- <h1>Cool stuff</h1>
- <p>Multimethods, macros, regexes, interop, seqs...</p>
- </div>
-
- <div class="slide">
- <h1>En busca del lenguaje de programación ideal</h1>
- <ul class="incremental">
- <li>"Hay dos clases de lenguajes: los que todos odian y los que nadie usa"</li>
- <li>Uso C++ :)</li>
- <li>Odio C++ :(</li>
- </ul>
- </div>
-
- <div class="slide">
- <h1>Pero... C++ mola, ¿por qué no te gusta?</h1>
- <ul>
- <li>No hay funciones anónimas</li>
- <li>Es incómodo usar funciones de orden superior (<i>boilerplate</i> a
- montones si se usan functores)</li>
- <li>Falta un <b>buen</b> sistema de macros</li>
- </ul>
- </div>
-
- <div class="slide">
- <h1>Patrones de diseño</h1>
- <p>La comunidad de seguidores de la OOP adora los patrones de diseño</p>
- <ul class="incremental">
- <li>Su uso se considera una señal de madurez</li>
- <li>Otros los consideran una señal de alarma:
- <div class="hbox" style="align:center; height:25%">
- "When I see patterns in my programs, I consider it a sign of trouble. The
- shape of a program should reflect only the problem it needs to solve. Any
- other regularity in the code is a sign, to me at least, that I'm using
- abstractions that aren't powerful enough - often that I'm generating by
- hand the expansions of some macro that I need to write."
- <br />
- -- Paul Graham
- </div>
+<pre class="source"><span class="Special">(</span><span class="PreProc">ns</span> wordcount <span class="Special">(</span><span class="Statement">:gen-class</span><span class="Special">)</span>
+ <span class="Special">(</span><span class="Statement">:use</span> clojure.contrib.<span class="Identifier">str</span>-utils<span class="Special">))</span>
+
+<span class="Special">(</span><span class="PreProc">defn</span> num-lines <span class="Special">[</span>text<span class="Special">]</span> <span class="Special">(</span><span class="Identifier">count</span> <span class="Special">(</span>re-split <span class="Constant">#"\n"</span> text<span class="Special">)))</span>
+<span class="Special">(</span><span class="PreProc">defn</span> num-words <span class="Special">[</span>text<span class="Special">]</span> <span class="Special">(</span><span class="Identifier">count</span> <span class="Special">(</span>re-split <span class="Constant">#"\s+"</span> text<span class="Special">)))</span>
+<span class="Special">(</span><span class="PreProc">defn</span> num-characters <span class="Special">[</span>text<span class="Special">]</span> <span class="Special">(</span><span class="Identifier">count</span> text<span class="Special">))</span>
+
+<span class="Special">(</span><span class="PreProc">defn</span> -main <span class="Special">[</span>file<span class="Special">]</span>
+ <span class="Special">(</span><span class="Special">let</span> <span class="Special">[</span>text <span class="Special">(</span><span class="Identifier">slurp</span> file<span class="Special">)]</span>
+ <span class="Special">(</span><span class="Identifier">println</span> <span class="Special">(</span>num-lines text<span class="Special">)</span> <span class="Special">(</span>num-words text<span class="Special">)</span> <span class="Special">(</span>num-characters text<span class="Special">))))</span></pre>
+
+ </div>
+
+ <div class="slide">
+ <h1>Macros: extendiendo Clojure</h1>
+ <ul>
+ <li>La forma especial <code>if</code> es muy sosa: <code>(if cond then-expr else-expr?)</code></li>
+ <li>¿Y si quiero un switch/case? Tenemos <code>cond</code></li>
+ </ul>
+<pre class="source"><span class="Special">(</span><span class="PreProc">defn</span> f <span class="Special">[</span>x<span class="Special">]</span>
+ <span class="Special">(</span><span class="Special">let</span> <span class="Special">[</span>resto <span class="Special">(</span><span class="Identifier">mod</span> x <span class="Constant">3</span><span class="Special">)]</span>
+ <span class="Special">(</span><span class="Statement">cond</span>
+ <span class="Special">(</span>= resto <span class="Constant">0</span><span class="Special">)</span> <span class="Constant">"cero"</span>
+ <span class="Special">(</span>= resto <span class="Constant">1</span><span class="Special">)</span> <span class="Constant">"uno"</span>
+ <span class="Special">(</span>= resto <span class="Constant">2</span><span class="Special">)</span> <span class="Constant">"dos"</span><span class="Special">)))</span></pre>
+
+ <ul class="incremental"><li><code>cond</code> es una macro :)</li></ul>
+ </div>
+
+ <div class="slide">
+ <h1>Macros: extendiendo Clojure</h1>
+ <ul class="outline">
+ <li>Definición de <i>cond</i> en los fuentes de <code>clojure.core:</code></li>
+ </ul>
+<pre><span class="Special">(</span><span class="PreProc">defmacro</span> <span class="Statement">cond</span>
+ <span class="Constant">"Takes a set of test/expr pairs. It evaluates each test one at a</span>
+ <span class="Constant"> time. If a test returns logical true, cond evaluates and returns</span>
+ <span class="Constant"> the value of the corresponding expr and doesn't evaluate any of</span>
+ <span class="Constant"> the other tests or exprs. (cond) returns nil."</span>
+ <span class="Special">[</span><span class="Special">&</span> clauses<span class="Special">]</span><span class="Comment"> ;argumentos variables, clauses es una lista</span>
+ <span class="Special">(</span><span class="Statement">when</span> clauses
+ <span class="Special">(</span><span class="Identifier">list</span> <span class="Special">'</span><span class="Special">if</span> <span class="Special">(</span><span class="Identifier">first</span> clauses<span class="Special">)</span>
+ <span class="Special">(</span><span class="Special">if</span> <span class="Special">(</span><span class="Identifier">next</span> clauses<span class="Special">)</span>
+ <span class="Special">(</span><span class="Identifier">second</span> clauses<span class="Special">)</span>
+ <span class="Special">(</span><span class="Statement">throw</span> <span class="Special">(</span>IllegalArgumentException.
+ <span class="Constant">"cond requires an even number of forms"</span><span class="Special">)))</span>
+ <span class="Special">(</span><span class="Identifier">cons</span> <span class="Special">'</span><span class="Statement">cond</span> <span class="Special">(</span><span class="Identifier">next</span> <span class="Special">(</span><span class="Identifier">next</span> clauses<span class="Special">))))))</span><span class="Comment"> ;definición recursiva</span>
+</pre>
+ <ul>
+ <li>Notas:
+ <ul>
+ <li><code>'if</code> es lo mismo que <code>(quote if)</code>,
+ es decir, el token if sin evaluar</li>
+ <li>Cadenas de documentación accesibles con <code>(doc mifuncion)</code></li>
+ </ul>
</li>
</ul>
- </div>
+ </div>
+
<div class="slide">
- <h1>Es mas... ¿por qué creemos que la OOP es la panacea?</h1>
- <p>Alexander Stepanov (coautor de la STL) dijo una vez:</p>
+ <h1>Lazy sequences</h1>
+ <ul>
+ <li>Clojure permite trabajar con secuencias que se evalúan de forma perezosa</li>
+ <li>Esto permite, por ejemplo, trabajar con secuencias infinitas
+<pre>user=> (def naturals (iterate inc 0))
+#'user/naturals
+user=> (take 10 naturals)
+(0 1 2 3 4 5 6 7 8 9)</pre>
+ </li>
+ <li>...sin evaluarlas mientras no haga falta...
+<pre>user=> (def zeros (cycle '(0)))
+#'user/zeros
+user=> (take 10 (interleave naturals zeros))
+(0 0 1 0 2 0 3 0 4 0)
+</pre>
+ </li>
+ <li>Hay muchas cosas seq-ables:
+ <ul><li>Listas, vectores, maps, colecciones Java, ficheros (por líneas), árboles XML,...</li></ul>
+ </li>
+ </ul>
+ </div>
+
+
+ <div class="slide">
+ <h1>Multimétodos</h1>
+ <ul>
+ <li>El polimorfismo estándar en la OOP realiza el <i>dispatch</i> de un método basándose
+ únicamente en el tipo en ejecución del objeto</li>
+ <li>Ejemplo típico:
+<pre style="font-size:70%;">struct Animal { virtual void encounter(Animal& other) = 0; }
+
+struct Lion : Animal {
+ void encounter(Animal& other) {
+ if (Lion* lion = dynamic_cast<Lion*>(&other)) { fight(); }
+ else if (Bunny* bunny = dynamic_cast<Bunny*>(&other)) { eat(); }
+ else { /* default handling here */ }
+ }
+}
+
+struct Bunny : Animal {
+ void encounter(Animal& other) {
+ if (Lion* lion = dynamic_cast<Lion*>(&other)) { run_away(); }
+ else if (Bunny* bunny = dynamic_cast<Bunny*>(&other)) { mate(); }
+ else { /* default collision handling here */ }
+ }
+}
+</pre>
+ </li>
+ </ul>
+ </div>
+
+ <div class="slide">
+ <h1>Multimétodos (II)</h1>
<ul class="incremental">
- <li>I find OOP <b>technically unsound</b>. It attempts to decompose the world in
- terms of interfaces that vary on a single type. To deal with the real
- problems you need multisorted algebras - families of interfaces that span
- multiple types.</li>
- <li>I find OOP <b>philosophically unsound</b>. It claims that everything is an
- object. Even if it is true it is not very interesting - saying that
- everything is an object is saying nothing at all.</li>
+ <li class="non-incremental">Solución con multimétodos:
+<pre>(defmulti encounter (fn [x y] [(:Species x) (:Species y)]))
+(defmethod encounter [:Bunny :Lion] [b l] :run-away)
+(defmethod encounter [:Lion :Bunny] [l b] :eat)
+(defmethod encounter [:Lion :Lion] [l1 l2] :fight)
+(defmethod encounter [:Bunny :Bunny] [b1 b2] :mate)
+(def b1 {:Species :Bunny :other :stuff})
+(def b2 {:Species :Bunny :other :stuff})
+(def l1 {:Species :Lion :other :stuff})
+(def l2 {:Species :Lion :other :stuff})
+
+
+(encounter b1 b2)
+-> :mate
+(encounter b1 l1)
+-> :run-away</pre>
+ </li>
+ <li>En Clojure el dispatch se hace según el resultado de una expresión
+ arbitraria, no sólo según los tipos implicados</li>
+ <li>...e internamente son macros :-D</li>
+ </ul>
+ </div>
+
+ <div class="slide">
+ <h1>Java interop</h1>
+ <ul>
+ <li>Creación de objetos Java: <code>(new Clase)</code> o simplemente <code>Clase.</code></li>
+ <li>Acceso a miembros: <code>(. clase miembro)</code>
+ <pre>(. "hola" toUpperCase)
+"HOLA"</pre>
+ </li>
+ <li>La macro .. encadena accesos:
+ <pre>(.. System getProperties (get "os.name"))
+"Linux"</pre></li>
+ <li>Las funciones de Clojure implementan los interfaces Runnable y Callable de Java
+ <pre>(.run (Thread. (fn [] (println "Hola"))))</pre></li>
+ </ul>
+ </div>
+
+ <div class="slide">
+ <h1>Java interop (II)</h1>
+ <ul>
+ <li>Se pueden generar nuevas clases Java desde Clojure:
+<pre class="source"><span class="Special">(</span><span class="Special">def</span> PrintElementHandler
+ <span class="Special">(</span><span class="PreProc">proxy</span> <span class="Special">[</span>DefaultHandler<span class="Special">]</span> <span class="Special">[]</span>
+ <span class="Special">(</span>startElement <span class="Special">[</span>uri localName qname attributes<span class="Special">]</span>
+ <span class="Special">(</span><span class="Identifier">println</span> <span class="Special">(</span><span class="Identifier">format</span> <span class="Constant">"Saw element: %s"</span> qname<span class="Special">)))))</span></pre>
+ ...es equivalente a...
+<pre class="source"><span class="Type">public</span> <span class="Type">class</span> SomeNewClass <span class="Type">extends</span> DefaultHandler {
+ <span class="Type">public</span> <span class="Type">void</span> startElement(String uri,
+ String localName,
+ String qName,
+ Attributes attributes) {
+ System.out.println(*stuff*);
+ }
+}</pre>
+ </li>
+ <li>Demasiados detalles para comentar aquí :(</li>
+ </ul>
+ </div>
+
+
+ <div class="slide">
+ <h1>Problemas</h1>
+ <ul>
+ <li>Pocas herramientas (aunque hay plugins para Eclipse y Netbeans en desarrollo)</li>
+ <li>Software poco maduro</li>
+ <li>Comunidad muy pequeña</li>
+ <li>La JVM no permite Tail Call Optimizations
+ <ul>
+ <li>la recursión consume pila, a menos que se utilice loop/recur (menos elegante)</li>
+ </ul>
+ </li>
</ul>
+
</div>
+
+ <div class="slide">
+ <h1>Conclusiones</h1>
+ <ul>
+ <li>El futuro va a ser cada vez más funcional (IMHO)</li>
+ <li>Lisp es una especie de "kit para diseñar lenguajes"</li>
+ <li>Clojure parece molar, y espero poder comprobarlo pronto en algún
+ proyecto personal</li>
+ </ul>
+ </div>
+
+ <div class="slide">
+ <h1>Fin</h1>
+ <ul>
+ <li>¿Preguntas, comentarios?</li>
+ </ul>
+ </div>
+
</body>
</html>