Release Candidate 1 :)
authorslack <slack@codemaniacs.com>
Thu, 10 Dec 2009 04:43:49 +0000 (05:43 +0100)
committerslack <slack@codemaniacs.com>
Thu, 10 Dec 2009 04:43:49 +0000 (05:43 +0100)
clojure-slides.xhtml

index 9ced9ae951fa341fa66178857a6ee15152c97a78..d02dfdb888423b6ae019341231eb50d1dc38867b 100755 (executable)
   <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 =&gt; 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 &amp;&amp; !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) &nbsp;&nbsp;=&gt; 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) &nbsp;&nbsp;=&gt; 1</pre>
       </li>
       <li>Diccionarios: <code>{:a 1, :b 2}</code>
-      <ul>
-        <li><code>({:a 1, :b 2} :b) &nbsp;&nbsp;=&gt; 2</code></li>
-        <li><code>({:a 1, :b 2} :x) &nbsp;&nbsp;=&gt; nil</code></li>
-      </ul>
+        <pre>({:a 1, :b 2} :b) &nbsp;&nbsp;=&gt; 2
+({:a 1, :b 2} :x) &nbsp;&nbsp;=&gt; 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>&nbsp;wordcount <font color="#ff6060"><b>(</b></font><font color="#ff00ff"><b>:gen-class</b></font><font color="#ff6060"><b>)</b></font><br />
-               &nbsp;&nbsp;<font color="#ff6060"><b>(</b></font><font color="#ff00ff"><b>:use</b></font>&nbsp;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>&nbsp;num-lines <font color="#ff6060"><b>[</b></font>text<font color="#ff6060"><b>]</b></font>&nbsp;<font color="#ff6060"><b>(</b></font><font color="#009000"><b>count</b></font>&nbsp;<font color="#ff6060"><b>(</b></font>re-split <font color="#ff40ff"><b>#&quot;\n&quot;</b></font>&nbsp;text<font color="#ff6060"><b>)))</b></font><br />
-               <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>defn</b></font>&nbsp;num-words <font color="#ff6060"><b>[</b></font>text<font color="#ff6060"><b>]</b></font>&nbsp;<font color="#ff6060"><b>(</b></font><font color="#009000"><b>count</b></font>&nbsp;<font color="#ff6060"><b>(</b></font>re-split <font color="#ff40ff"><b>#&quot;\s+&quot;</b></font>&nbsp;text<font color="#ff6060"><b>)))</b></font><br />
-               <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>defn</b></font>&nbsp;num-characters <font color="#ff6060"><b>[</b></font>text<font color="#ff6060"><b>]</b></font>&nbsp;<font color="#ff6060"><b>(</b></font><font color="#009000"><b>count</b></font>&nbsp;text<font color="#ff6060"><b>))</b></font><br />
-               <br />
-               <font color="#ff6060"><b>(</b></font><font color="#8080ff"><b>defn</b></font>&nbsp;-main <font color="#ff6060"><b>[</b></font>file<font color="#ff6060"><b>]</b></font><br />
-               &nbsp;&nbsp;<font color="#ff6060"><b>(</b></font><font color="#ff6060"><b>let</b></font>&nbsp;<font color="#ff6060"><b>[</b></font>text <font color="#ff6060"><b>(</b></font><font color="#009000"><b>slurp</b></font>&nbsp;file<font color="#ff6060"><b>)]</b></font><br />
-               &nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff6060"><b>(</b></font><font color="#009000"><b>println</b></font>&nbsp;<font color="#ff6060"><b>(</b></font><font color="#009000"><b>num</b></font>-lines text<font color="#ff6060"><b>)</b></font>&nbsp;<font color="#ff6060"><b>(</b></font><font color="#009000"><b>num</b></font>-words text<font color="#ff6060"><b>)</b></font>&nbsp;<font color="#ff6060"><b>(</b></font><font color="#009000"><b>num</b></font>-characters text<font color="#ff6060"><b>))))</b></font><br />
-               &nbsp;&nbsp;&nbsp;&nbsp;<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">#&quot;\n&quot;</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">#&quot;\s+&quot;</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">&quot;cero&quot;</span>
+      <span class="Special">(</span>= resto <span class="Constant">1</span><span class="Special">)</span> <span class="Constant">&quot;uno&quot;</span>
+      <span class="Special">(</span>= resto <span class="Constant">2</span><span class="Special">)</span> <span class="Constant">&quot;dos&quot;</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">&quot;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.&quot;</span>
+  <span class="Special">[</span><span class="Special">&amp;</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">&quot;cond requires an even number of forms&quot;</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=&gt; (def naturals (iterate inc 0))
+#'user/naturals
+user=&gt; (take 10 naturals)
+(0 1 2 3 4 5 6 7 8 9)</pre>
+      </li>
+      <li>...sin evaluarlas mientras no haga falta...
+<pre>user=&gt; (def zeros (cycle '(0)))
+#'user/zeros
+user=&gt; (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&amp; other) = 0; }
+
+struct Lion : Animal {
+    void encounter(Animal&amp; other) {
+        if (Lion* lion = dynamic_cast&lt;Lion*&gt;(&amp;other)) { fight(); }
+        else if (Bunny* bunny = dynamic_cast&lt;Bunny*&gt;(&amp;other)) { eat(); }
+        else { /* default handling here */ }
+    }
+}
+
+struct Bunny : Animal {
+    void encounter(Animal&amp; other) {
+        if (Lion* lion = dynamic_cast&lt;Lion*&gt;(&amp;other)) { run_away(); }
+        else if (Bunny* bunny = dynamic_cast&lt;Bunny*&gt;(&amp;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)
+-&gt; :mate
+(encounter b1 l1)
+-&gt; :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">&quot;Saw element: %s&quot;</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>