<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Planeta PyAr</title><link>http://planeta.python.org.ar/</link><description>Colección de blogs de PyAr.</description><atom:link href="http://planeta.python.org.ar/rss.xml" type="application/rss+xml" rel="self"></atom:link><language>es</language><lastBuildDate>Sun, 07 Jul 2019 01:18:12 GMT</lastBuildDate><generator>https://getnikola.com/</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Facundo Batista: Enseñando Python</title><link>http://planeta.python.org.ar/posts/9b29a001af04cd925053615a5195bd9c.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;El último finde terminó el segundo Seminario de Python armado con Onapsis.&lt;/p&gt;
&lt;p&gt;El primero &lt;a class="reference external" href="http://blog.taniquetil.com.ar/posts/0735/"&gt;había sido hace dos años&lt;/a&gt;, muy introductorio, para alrededor de cuarenta asistentes.&lt;/p&gt;
&lt;p&gt;El que acabo de completar, durante cuatro sábados de Junio, tuvo un &lt;a class="reference external" href="http://www.taniquetil.com.ar/facundo/curso-medio-avanzado.html"&gt;contenido más avanzado&lt;/a&gt;. También fue en oficinas de Onapsis, pero en las nuevas, porque justo se mudaron hace un par de meses. Y fue para más de sesenta personas, lo cual ya per se es un desafío.&lt;/p&gt;
&lt;img alt="La grupal, el último día" src="http://blog.taniquetil.com.ar/images/seminario-python-2019.jpeg"&gt;
&lt;p&gt;Aunque había más gente, estaba más cómodo que la vez pasada porque al ser un espacio más grande, permitía moverme mejor. Un factor clave: ¡di todo el curso parado! Es crítico para futuros casos similares conseguirme una mesita alta para poder usar la laptop parado, esta vez funcionó de maravillas.&lt;/p&gt;
&lt;p&gt;Y además el contenido en si del curso fue más interesante, porque fueron temas que en general no doy en los cursos, y más desafiante porque otros temas los recorrí con una mayor profundidad. Esto, sumado a que los tiempos eran super justos, me obligó a preparar bien las clases y ejecutarlas sin mucho margen.&lt;/p&gt;
&lt;p&gt;Pero salieron bien, lo cual me deja muy contento. Un experimento exitoso.&lt;/p&gt;
&lt;p&gt;Por otro lado, para seguir cambiando cosas e intentar cosas nuevas, estamos armando con Leandro la idea de unos cursos no sólo teóricos sino también con una parte práctica importante.&lt;/p&gt;
&lt;p&gt;Vamos a ver si hacemos un par básicos, y si nos gusta y funciona, podemos seguir con temas más avanzados. O ir cambiando horarios, o días, o la duración del curso en sí.&lt;/p&gt;
&lt;p&gt;Queremos ir probando distintas alternativas, pero para entender mejor qué quieren les posibles asistentes, armamos &lt;a class="reference external" href="https://docs.google.com/forms/d/1A-6nie0ud40aOyE_qBrQcjLS9ZNE4gJtjgGE6FyW8yU/edit"&gt;esta encuesta&lt;/a&gt;, no dejes de llenarla si te interesaría asistir.&lt;/p&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/9b29a001af04cd925053615a5195bd9c.html</guid><pubDate>Sat, 06 Jul 2019 21:29:00 GMT</pubDate></item><item><title>Facundo Batista: Python Argentina, actualidad y futuro</title><link>http://planeta.python.org.ar/posts/a3e17971ffd7d4a700557010990aa906.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;A nivel PyAr estamos teniendo un presente movidito. Venimos de un meetup en &lt;a class="reference external" href="https://www.trocafone.com.ar/"&gt;Trocafone&lt;/a&gt; y tenemos un &lt;a class="reference external" href="https://eventos.python.org.ar/events/pydaynea2019/"&gt;PyDay en Resistencia (Chaco)&lt;/a&gt; a fin de mes.&lt;/p&gt;
&lt;p&gt;El meetup en Trocafone estuvo bárbaro. Fue diferente a los que veníamos armando de un par de charlas y algo social tipo after office en la semana: lo que hicimos fue armar una mañana de charlas, y luego sprint/taller, o al menos esa era la idea.&lt;/p&gt;
&lt;p&gt;En la práctica, los meetups son más relajados que un PyDay o conferencia más grande, y nos permite acomodarnos a lo que va saliendo. Las charlas iniciales estuvieron muy bien, después hablé un poco de los proyectos de la tarde, comimos la picada bárbara cortesía de Trocafone, y después jugamos dos veces a eso que llamo "coding dojo rotativo rápido", y aprendimos &lt;a class="reference external" href="https://python-telegram-bot.org/"&gt;cómo hacer bots de Telegram con Python de forma super sencilla&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A nivel futuro estamos planeando un meetup en Rosario (algún día de semana, primeros días de Agosto? ¡tenemos que definir!), y luego va a realizarse un PyDay también en esa ciudad, con fecha a confirmar.&lt;/p&gt;
&lt;p&gt;Y ya tenemos definidas las fechas para la PyCon Argentina 2019: va a ser el 4, 5, y 6 de Diciembre (en el Centro Cultural General San Martín, CABA, como el año pasado).&lt;/p&gt;
&lt;div class="section" id="asociacion-civil-proximos-meses"&gt;
&lt;h3&gt;Asociación Civil, próximos meses&lt;/h3&gt;
&lt;p&gt;Específicamente hablando de la Asociación Civil Python Argentina, tengo planes armados para los próximos meses que presenté en una reunión para Comisión Directiva y amigues hace unas semanas en oficinas de Satellogic.&lt;/p&gt;
&lt;p&gt;Los punteo a continuación, pero tampoco entro en demasiado detalle para no aburrir. Sepan que si quieren más info de cualquiera de estos temas pueden preguntarme directamente o a través del grupo de Telegram de &lt;a class="reference external" href="https://t.me/amigues_asoc_civil_pyar"&gt;Amigues de la AC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terminar bootstrap de la Asociación Civil a nivel infraestructura&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Sistema de socies, tenerlo 100% funcional: para ello tenemos que terminar de cerrar &lt;a class="reference external" href="https://github.com/PyAr/asoc_members/issues"&gt;estos issues&lt;/a&gt;, todo lo que necesitamos está cargado ahí... no falta tanto, avanzamos mucho los últimos meses, laburando yo solo, o con mucha ayuda en el último PyCamp, y gracias a &lt;a class="reference external" href="https://twitter.com/gilgamezh"&gt;Gilgamezh&lt;/a&gt; por todo lo que es infraestructura ya lo tenemos en producción (ejemplo: les nueves socies pueden &lt;a class="reference external" href="https://admin.ac.python.org.ar/solicitud-alta/"&gt;anotarse acá&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Sistema de eventos completo: este no lo estamos haciendo a pulmón porque lo necesitamos más o menos rápido (es más, ya deberíamos estar empezándolo a usar), sino que se lo encargamos a &lt;a class="reference external" href="https://devecoop.com/"&gt;Devecoop&lt;/a&gt;, cooperativa amiga (y socia benefactora) que nos hizo precio con el laburo. Vamos a ver cuanto llegamos a hacer, pero está tomando cuerpo de forma genial, y a lo sumo nos quedarán algunos detalles a terminar a futuro.&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Gestión de Eventos" src="http://blog.taniquetil.com.ar/images/acplan19-gesti%C3%B3n.png"&gt;
&lt;p&gt;&lt;strong&gt;Que la AC haga break even&lt;/strong&gt;: para esto básicamente tenemos que tener una entrada mensual mayor a los gastos fijos que tenemos (abogado, contador, gastos bancarios, gastos operativos, etc.); para lograr esto queremos hacer foco en:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Juntar socies humanes y de organizaciones benefactoras: para la primera parte vamos por todos lados contando sobre la asociación y bajamos la barrera de entrada con el sistema de socies; para la segunda parte ya me estuve moviendo bastante antes de lanzar la PyCon, y pasamos de dos socias benefactoras a seis, lo cual casi da por cumplido ese objetivo (si conseguimos alguna más en el 2019 mejor, pero para el año estamos hechos).&lt;/li&gt;
&lt;li&gt;Al menos dos entradas por eventos PyAr y por eventos externos: esto nos da una pequeña entrada de guita que ayuda al movimiento de la Asociación Civil, y aunque no es grande, pega directamente en el propósito de la asociación: ayudar a que se hagan eventos.&lt;/li&gt;
&lt;li&gt;La PyCon (Argentina) nos tiene que dar un extra importante, aunque no la deberíamos contemplar como guita para el movimiento operativo de la asociación: por un lado nos debería "blindar" para la próxima conferencia grande, y por el otro tenemos que usar ese extra para consolidar infraestructura del grupo (comprar proyector, micrófonos, etc...).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Terminar bootstrap de la AC a nivel legal&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Tener exención de ganancias: esto ya lo ejecuté hace algunas semanas, y es un ejemplo de lo que decía arriba de gastos operativos que necesitamos afrontar en el día a día: solamente las copias autenticadas de papeles internos para presentar en la AFIP costaron $1500. Sí, una luca y media :/.&lt;/li&gt;
&lt;li&gt;Tener los papeles internos normalizados: para esto vamos a armar una o dos reuniones en el corto plazo donde nos vamos a sentar a llenar "libros legales", que es algo que tenemos medio (bastante) atrasado.&lt;/li&gt;
&lt;li&gt;Tener acceso del contador a sistemas bancarios: tenemos que ponernos con Leandro a toquetear permisos de plataformas...&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Libros, papeles, presentaciones" src="http://blog.taniquetil.com.ar/images/acplan19-libros.jpeg"&gt;
&lt;p&gt;&lt;strong&gt;Fortalecer/renovar/modernizar infraestructura del grupo&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Tener una forma primaria de comunicación asincrónica moderna, mantenida: vamos a cambiar la "lista de correo pura" que tenemos hoy por algo más nuevo; esto puede ser ir a una "lista de correo con foro decente", como nos brindaría mailman3, o "un foro que igual el que quiera lo pueda manejar como lista de correo", como Discourse, o algo por el estilo. En esto está &lt;a class="reference external" href="https://twitter.com/gilgamezh"&gt;Gilgamezh&lt;/a&gt;, más que nada supervisando/participando en una discusión similar que está teniendo la PSF sobre esto mismo... ellos le están poniendo mucho análisis, así que lo más probable es que nosotros "reutilicemos sus conclusiones" y vayamos para el mismo lado.&lt;/li&gt;
&lt;li&gt;Imagen más moderna y pensada: vamos a cambiar el logo! sí, después de 15 años, vamos a ir a un logo pensado/armado por un diseñador :) ... ¡y es una buena oportunidad para rehacer la bandera!&lt;/li&gt;
&lt;li&gt;Tener un sistema de eventos que sirva para pydays/pycon/meetups: esto es &lt;a class="reference external" href="https://github.com/eventoL/eventoL"&gt;Eventol&lt;/a&gt;, &lt;a class="reference external" href="https://eventos.python.org.ar/"&gt;servido por nosotros&lt;/a&gt;, el cual ya funciona para pydays/pycon, pero faltan hacerle detalles y un cambio un poco más grande para soportar meetups o juntadas (que tiene el modelo de suscripción invertido con respecto a las conferencias normales).&lt;/li&gt;
&lt;li&gt;Tener un sitio actualizado, elegante: un poco la imagen va a cambiar (por lo que decía arriba), y tenemos que corregirle cosas de la infraestructura que lo sirve ahora... no sólo a nivel de la migración que quedó por la mitad, sino también Waliki que se rompe seguido... ¿quizás cambiaremos la estructura que tiene el sitio en sí?&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/a3e17971ffd7d4a700557010990aa906.html</guid><pubDate>Tue, 18 Jun 2019 18:31:00 GMT</pubDate></item><item><title>Marcos Dione: osm-tile-tools-v1.0</title><link>http://planeta.python.org.ar/posts/23d38d8ebec32b9d2802e85d038904a6.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;Today I finally sat down and spun off &lt;code&gt;generate_tiles.py&lt;/code&gt; to its own repository,
so people can follow its development without having to clone my own osm-carto
fork. This happened just after I finished making the storage thread optional,
because I usualy have as many rendering threads as cores I have, so that extra
thread was not only compiting with them, but also it spent some time
de/marshaling the metatiles between processes, so I'm not sure it's worth it.
Maybe if I had more cores?&lt;/p&gt;

&lt;p&gt;The new repo is &lt;a href="https://github.com/StyXman/osm-tile-tools"&gt;here&lt;/a&gt;. There are
some other tools there (hence the tools in the repo's name), but they're not so
polished or documented. You're free to look and ask :)&lt;/p&gt;

&lt;p&gt;What if I do a release, I hear (it must be the voice in my head)? Why not! I even
decided to go bold and tagged it as
&lt;a href="https://github.com/StyXman/osm-tile-tools/releases/tag/v1.0"&gt;v1.0&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;a href="http://www.grulic.org.ar/~mdione/glob//tags/openstreetmap/"&gt;openstreetmap&lt;/a&gt; &lt;a href="http://www.grulic.org.ar/~mdione/glob//tags/pyhton/"&gt;pyhton&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/23d38d8ebec32b9d2802e85d038904a6.html</guid><pubDate>Fri, 24 May 2019 10:46:00 GMT</pubDate></item><item><title>Marcos Dione: osm-render-tools-v1.0</title><link>http://planeta.python.org.ar/posts/b4a25b7d5bafd1594a9bac96d119067b.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;Today I finally sat down and spun off &lt;code&gt;generate_tiles.py&lt;/code&gt; to its own repository,
so people can follow its development without having to clone my own osm-carto
fork. This happened just after I finished making the storage thread optional,
because I usualy have as many rendering threads as cores I have, so that extra
thread was not only compiting with them, but also it spent some time
de/marshaling the metatiles between processes, so I'm not sure it's worth it.
Maybe if I had more cores?&lt;/p&gt;

&lt;p&gt;The new repo is &lt;a href="https://github.com/StyXman/osm-tile-tools"&gt;here&lt;/a&gt;. There are
some other tools there (hence the tools in the repo's name), but they're not so
polished or documented. You're free to look and ask :)&lt;/p&gt;

&lt;p&gt;What if I do a release, I hear (it must be the voice in my head)? Why not! I even
decided to go bold and tagged it as
&lt;a href="https://github.com/StyXman/osm-tile-tools/releases/tag/v1.0"&gt;v1.0&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;a href="http://www.grulic.org.ar/~mdione/glob//tags/openstreetmap/"&gt;openstreetmap&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/b4a25b7d5bafd1594a9bac96d119067b.html</guid><pubDate>Thu, 23 May 2019 17:53:00 GMT</pubDate></item><item><title>Facundo Batista: A todo Python, noticias, eventos</title><link>http://planeta.python.org.ar/posts/5bea9f7d2898f1d65631a7134722f7b6.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;div class="section" id="curso-s"&gt;
&lt;h3&gt;Curso(s)&lt;/h3&gt;
&lt;p&gt;Hace unas semanas anunciaba &lt;a class="reference external" href="https://blog.taniquetil.com.ar/posts/0782/"&gt;por acá&lt;/a&gt; (y por otros lados) que iba a dar un Seminario Python nivel medio/avanzado con apoyo de Onapsis, abierto a la comunidad.&lt;/p&gt;
&lt;p&gt;Explotó, en cuatro días tenía el 80% de las vacantes con la reserva confirmada, en siete días estaba todo cerrado. No esperaba un éxito tan rotundo, pero estoy muy contento. El lado gris es que un par se me enojaron porque no llegaron a entrar en el curso porque se demoraron en pagar (la mayoría lo entendió perfectamente).&lt;/p&gt;
&lt;p&gt;Seguramente haré otros cursos durante el año. SPOILER ALERT: quizás algo introductorio primero y medio/avanzado luego, pero no sólo teoría sino también práctica, en conjunto con otro docente. Ya habrán novedades.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="charla"&gt;
&lt;h3&gt;Charla&lt;/h3&gt;
&lt;p&gt;Ayer sábado fui invitado por &lt;a class="reference external" href="https://twitter.com/AnaJuliaVelezR1"&gt;Ana Vélez Rueda&lt;/a&gt; a dar una charla de introducción a la programación primero e introducción a Python luego, en la Universidad de Quilmes, para futuros docentes de Python. Luego de pensarlo bastante estos últimos días mezclé un poco ambas charlas, y creo que salió muy bien. La gente estuvo super interesada, y aunque fue largo y cansador (¡sábado a la tarde!) se la bancaron.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="proximos-eventos-de-pyar"&gt;
&lt;h3&gt;Próximos eventos de PyAr&lt;/h3&gt;
&lt;p&gt;Hay dos juntadas planeadas a futuro. La primera, bastante confirmada y que será anunciada estos días es el martes 21 a la tarde/noche, en J.P. Morgan, y va a ser una charla/taller sobre testing, más la parte social de siempre.&lt;/p&gt;
&lt;p&gt;La segunda, todavía en etapa de "ver qué forma le damos" va a ser en Trocafone, el sábado 15 de Junio. Como es sábado, la idea es hacer algo más tipo sprint. O sea, ponernos a trabajar en algo (puntual o no), aunque seguramente abriremos el día con un par de charlas, quizás trabajar a la tarde luego del almuerzo, etc. Como les decía, todavía hay que definir la dinámica de ese día, pero está bueno volver cada tanto a la juntada de sábado, para hacer cosas :)&lt;/p&gt;
&lt;p&gt;Anunciaremos detalles sobre ambas juntadas tanto en &lt;a class="reference external" href="http://twitter.com/facundobatista/"&gt;mi tuiter&lt;/a&gt; como en el &lt;a class="reference external" href="https://twitter.com/pythonargentina/"&gt;de Pyar&lt;/a&gt;, pero la coordinación la haremos a través del &lt;a class="reference external" href="https://www.meetup.com/es-ES/Buenos-Aires-Python-Meetup/"&gt;meetup de Buenos Aires&lt;/a&gt; así que también se pueden sumar ahí.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/5bea9f7d2898f1d65631a7134722f7b6.html</guid><pubDate>Sun, 12 May 2019 12:32:00 GMT</pubDate></item><item><title>Facundo Batista: Seminario Python, nivel medio/avanzado</title><link>http://planeta.python.org.ar/posts/37fa5d0736510ea64721629a89c267bc.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;Por segunda oportunidad voy a dar un Seminario de Python abierto al público en general, coordinado con Onapsis, aunque esta vez no va a ser introductorio sino que va a tener un nivel de medio a avanzado.&lt;/p&gt;
&lt;p&gt;El contenido apunta a aquelles que ya tienen una base de Python y buscan formalizar conocimientos y terminar de establecer una estructura que les permita explorar temas más avanzados. De esta manera sólo voy a hacer un repaso rápido de los temas más simples, y haré foco en cuestiones más avanzadas o poco conocidas del lenguaje.&lt;/p&gt;
&lt;p&gt;En otras palabras, asumiré un conocimiento de las estructuras más simples y usadas del lenguaje (que voy a repasar de forma breve) y voy a profundizar en otros temas del lenguaje y sus bibliotecas. El &lt;a class="reference external" href="http://www.taniquetil.com.ar/facundo/curso-medio-avanzado.html"&gt;programa&lt;/a&gt; es super variado, me entusiasmé y metí un montón de temas, así que el ritmo de las clases va a ser interesante. Vengan despiertes :p&lt;/p&gt;
&lt;p&gt;Algunos títulos (¡no todos!) son:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Generadores&lt;/li&gt;
&lt;li&gt;Scopes&lt;/li&gt;
&lt;li&gt;Closures y decoradores&lt;/li&gt;
&lt;li&gt;Clases, y métodos especiales&lt;/li&gt;
&lt;li&gt;Virtualenvs&lt;/li&gt;
&lt;li&gt;Unit testing, logging, serialización&lt;/li&gt;
&lt;li&gt;Concurrencia y paralelismo, threading y async&lt;/li&gt;
&lt;li&gt;Context managers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les decía que el Seminario es abierto al público en general, y será de 16 horas en total, cuatro sábados de Junio, durante la mañana, en CABA.&lt;/p&gt;
&lt;p&gt;El costo es súper accesible, $1400, ya que parte lo cubre Onapsis, y la idea es hacerlo barato para que pueda venir la mayor cantidad de gente posible, y encima van a haber algunas becas.  Ojo que los cupos son limitados (la oficina tiene un límite), por lo que cuanto antes consigan reserva la posición, mejor... tengan en cuenta que para la primera edición hubo gente que quedó afuera.&lt;/p&gt;
&lt;p&gt;Al final del Seminario entregaré un certificado de asistencia y la totalidad del curso en formato electrónico.&lt;/p&gt;
&lt;p&gt;Para realizar la reserva deben &lt;a class="reference external" href="mailto:facundo@taniquetil.com.ar?subject=Reserva%20para%20el%20Seminario%20de%20Python"&gt;enviarme un mail&lt;/a&gt; así les confirmo disponibilidad y les paso los datos necesarios para realizar el pago (que podrá ser por depósito, transferencia bancaria, tarjeta de crédito, débito, etc.).&lt;/p&gt;
&lt;p&gt;Acá están &lt;a class="reference external" href="http://www.taniquetil.com.ar/facundo/curso-medio-avanzado.html"&gt;todos los detalles del curso&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/37fa5d0736510ea64721629a89c267bc.html</guid><pubDate>Mon, 22 Apr 2019 14:59:00 GMT</pubDate></item><item><title>Mariano Guerra: search erlang &amp; efene code by pattern matching code with "holes"</title><link>http://planeta.python.org.ar/posts/d9738e8fd06681cbd8c1747fed8c6e1f.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;div class="section" id="why-and-what"&gt;
&lt;h3&gt;Why and what?&lt;/h3&gt;
&lt;p&gt;One day, for weird reasons I was looking for a data structure that would allow
me to pattern match it quick without being confused by existing data, I thought
"nobody would have a tuple inside a one item tuple!", but I wasn't sure.&lt;/p&gt;
&lt;p&gt;This wasn't the first time I wanted to search code by structure, not by text.&lt;/p&gt;
&lt;p&gt;What I mean by "by structure"?&lt;/p&gt;
&lt;p&gt;You may want to search for stuff like:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Calls to function f1 on module m1 with 3 arguments&lt;ul&gt;
&lt;li&gt;Same but where some argument has a specific value&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Tuples with a specific number of items where the first item is a given atom&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I guess you get the idea, you want to match some expression's structure, but not
the text, because of formatting, new lines, spacing and also because some of the
values are not important, you would like to match any expression in some
places.&lt;/p&gt;
&lt;p&gt;Given that I have &lt;a class="reference external" href="https://efene.org"&gt;experience generating Erlang AST&lt;/a&gt; (abstract syntax tree) and
&lt;a class="reference external" href="https://hex.pm/packages/ast_walk"&gt;walking AST trees&lt;/a&gt; (for parse transforms and some macro magic in &lt;a class="reference external" href="https://efene.org"&gt;efene&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I decided to give it a try, and the result worked, a year later I decided to write a blog post about it :)&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_f259c6b88c9d4c7eacc17c90331ac886-1"&gt;&lt;/a&gt;erlplorer search &lt;span class="s2"&gt;"{{_@0, _@1, _@2}}"&lt;/span&gt; **/src/*.erl
&lt;/pre&gt;&lt;pre class="literal-block"&gt;
asn1/src/asn1ct.erl:1366 {{decode,{Module,Type,Value},Error}}
dialyzer/src/dialyzer_plt.erl:675 {{M,_F,_A}}
kernel/src/pg2.erl:300 {{local_member,Name,Pid}}
kernel/src/pg2.erl:302 {{pid,Pid,Name}}
kernel/src/pg2.erl:343 {{local_member,Name,'$1'}}
kernel/src/pg2.erl:354 {{pid,Pid,'$1'}}
mnesia/src/mnesia_locker.erl:263 {{Tid,Oid,Op}}
mnesia/src/mnesia_locker.erl:266 {{Tid,Oid,read}}
mnesia/src/mnesia_locker.erl:269 {{Tid,Oid,write}}
mnesia/src/mnesia_locker.erl:309 {{Tid,Oid,{queued,Op}}}
mnesia/src/mnesia_locker.erl:508 {{Tid,Oid,{queued,Op}}}
mnesia/src/mnesia_locker.erl:524 {{'$1','_','_'}}
mnesia/src/mnesia_locker.erl:536 {{Tid,'_','_'}}
parsetools/src/yecc.erl:1075 {{From,Sym,Next}}
parsetools/src/yecc.erl:1164 {{From,Sym,To}}
reltool/src/reltool_server.erl:764 {{'$1','$2','$3'}}
&lt;/pre&gt;
&lt;p&gt;Welp, yes, there are.&lt;/p&gt;
&lt;p&gt;But what was that?&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer"&gt;erlplorer&lt;/a&gt; is a command line tool built in &lt;a class="reference external" href="https://efene.org"&gt;efene&lt;/a&gt; that allows
to search for Erlang and efene code by providing expressions with holes.&lt;/p&gt;
&lt;p&gt;The first argument &lt;cite&gt;"{{_@0, _@1, _@2}}"&lt;/cite&gt; is an Erlang expression, in this case
a one item tuple holding a 3 item tuple, the weird looking variables are a
specially named variables that erlplorer interprets as "match any AST node
here, I don't care", they start with &lt;cite&gt;_@&lt;/cite&gt;, any other variable will match that variable name in the code.&lt;/p&gt;
&lt;p&gt;We can see that by searching for places that match a 3 item tuple ignoring the 3 places:&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_9e85cd10f3f64bfe81ad92dcbfe26c89-1"&gt;&lt;/a&gt;erlplorer search &lt;span class="s2"&gt;"{_, _, _}"&lt;/span&gt; **/src/*.erl
&lt;/pre&gt;&lt;pre class="literal-block"&gt;
asn1/src/asn1ct_check.erl:917 {_,_,_}
... to many results to show
&lt;/pre&gt;
&lt;p&gt;We can use this "meta variables" to do more pattern matching, let's search
for 3 item tuples that have the same thing in the 3 places:&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_7af8a5aa041f4b5da83565e33b88cc51-1"&gt;&lt;/a&gt;erlplorer search &lt;span class="s2"&gt;"{_@, _@, _@}"&lt;/span&gt; **/src/*.erl
&lt;/pre&gt;&lt;pre class="literal-block"&gt;
asn1/src/asn1ct_check.erl:917 {_,_,_}
...
asn1/src/asn1ct_constructed_ber_bin_v2.erl:701 {[],[],[]}
...
asn1/src/asn1ct_constructed_per.erl:401 {false,false,false}
...
common_test/src/ct_framework.erl:1130 {_,_,_}
...
common_test/src/ct_logs.erl:1492 {"","",""}
...
&lt;/pre&gt;
&lt;p&gt;Or search for identity functions:&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_427a79109e6a427c978166bd0266bff9-1"&gt;&lt;/a&gt;erlplorer search &lt;span class="s2"&gt;"fun(_@) -&amp;gt; _@ end"&lt;/span&gt; **/src/*.erl
&lt;/pre&gt;&lt;pre class="literal-block"&gt;
asn1/src/asn1ct.erl:2099 fun(D) -&amp;gt; D end
asn1/src/asn1ct_gen_ber_bin_v2.erl:650 fun(V) -&amp;gt; V end
common_test/src/test_server.erl:2067 fun(T) -&amp;gt; T end
compiler/src/beam_a.erl:147 fun(L) -&amp;gt; L end
compiler/src/beam_jump.erl:289 fun(Old) -&amp;gt; Old end
...
&lt;/pre&gt;
&lt;p&gt;Places that add 0 to something:&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_15df211b7baf40e4aa4eff68a3c682e7-1"&gt;&lt;/a&gt;erlplorer search &lt;span class="s2"&gt;"_@ + 0"&lt;/span&gt; **/src/*.erl
&lt;/pre&gt;&lt;pre class="literal-block"&gt;
asn1/src/asn1rtt_per_common.erl:187 N + 0
asn1/src/asn1rtt_per_common.erl:197 N + 0
stdlib/src/ms_transform.erl:90 16 + 0
stdlib/src/ms_transform.erl:92 17 + 0
stdlib/src/ms_transform.erl:97 22 + 0
stdlib/src/ms_transform.erl:102 18 + 0
stdlib/src/ms_transform.erl:106 23 + 0
stdlib/src/ms_transform.erl:111 24 + 0
stdlib/src/ms_transform.erl:167 20 + 0
stdlib/src/ms_transform.erl:170 19 + 0
stdlib/src/ms_transform.erl:174 21 + 0
&lt;/pre&gt;
&lt;p&gt;Places that add the same thing:&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_822f1c14944f4513bee3da59f8c05a3b-1"&gt;&lt;/a&gt;erlplorer search &lt;span class="s2"&gt;"_@ + _@"&lt;/span&gt; **/src/*.erl
&lt;/pre&gt;&lt;pre class="literal-block"&gt;
dialyzer/test/small_SUITE_data/src/maps_redef2.erl:18 A + A
stdlib/src/dets_utils.erl:1138 1 + 1
stdlib/src/dets_utils.erl:1226 1 + 1
stdlib/src/rand.erl:1464 Y + Y
stdlib/src/zip.erl:1315 Sz + Sz
&lt;/pre&gt;
&lt;p&gt;You get the idea...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="how-to-use-it"&gt;
&lt;h3&gt;How to use it&lt;/h3&gt;
&lt;p&gt;You need Erlang and rebar3 installed and in your &lt;cite&gt;$PATH&lt;/cite&gt;&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_89c28c2214054fe78d6a86cd5a7a160f-1"&gt;&lt;/a&gt;git clone https://github.com/marianoguerra/erlplorer
&lt;a name="rest_code_89c28c2214054fe78d6a86cd5a7a160f-2"&gt;&lt;/a&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; erlplorer
&lt;a name="rest_code_89c28c2214054fe78d6a86cd5a7a160f-3"&gt;&lt;/a&gt;rebar3 escriptize
&lt;a name="rest_code_89c28c2214054fe78d6a86cd5a7a160f-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# ~/bin or any other folder in your $PATH&lt;/span&gt;
&lt;a name="rest_code_89c28c2214054fe78d6a86cd5a7a160f-5"&gt;&lt;/a&gt;cp _build/default/bin/erlplorer ~/bin
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="how-is-it-implemented"&gt;
&lt;h3&gt;How is it implemented?&lt;/h3&gt;
&lt;p&gt;Wrap the expression passed in a function &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id11" id="id2"&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Compile the module to Erlang AST &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id12" id="id3"&gt;[2]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Extract the AST body of the dummy function &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id13" id="id4"&gt;[3]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;"abstract the AST", that is, I take an AST as Erlang data and I generate an
AST that when compiled will generate that Erlang AST, I need that because I
will put that AST in a pattern match position to pattern match AST nodes as I
walk Erlang ASTs &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id14" id="id5"&gt;[4]&lt;/a&gt;. yeah, meta and too many AST references&lt;/p&gt;
&lt;p&gt;An example is worth many of my words:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_a1748b3ee98c41f49de3a353a74ca392-1"&gt;&lt;/a&gt;&lt;span class="c"&gt;% the 42 is a fake "line" where the code was supposedly parsed&lt;/span&gt;
&lt;a name="rest_code_a1748b3ee98c41f49de3a353a74ca392-2"&gt;&lt;/a&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;erl_parse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;abstract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hi"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a name="rest_code_a1748b3ee98c41f49de3a353a74ca392-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,[{&lt;/span&gt;&lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;},{&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},{&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"hi"&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;We have to take care of two things:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;vars must match an AST node for a var with that name, not act as vars that will be bound on first match and pattern matched on successive matches&lt;/li&gt;
&lt;li&gt;vars that start with _@ will be compiled to actual vars that behave as vars in a pattern match, that's how we can use them to pattern match&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then compile the abstracted AST into a module with a function we can pass to &lt;cite&gt;ast_walk/3&lt;/cite&gt; &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id15" id="id6"&gt;[5]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Load the compiled module &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id16" id="id7"&gt;[6]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Parse the files passed as last argument &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id17" id="id8"&gt;[7]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And walk the parsed AST with our compiled matcher &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id18" id="id9"&gt;[8]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For each match, since we have the AST, try to pretty print it &lt;a class="footnote-reference" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id19" id="id10"&gt;[9]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Give it a try and let me know what you think.&lt;/p&gt;
&lt;p&gt;PS: the code is a hack I did to use it when I needed it, don't judge efene by the
code you see on that project :P&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id11" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id2"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L53"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L53&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id12" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id3"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L56"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L56&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id13" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id4"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L57"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L57&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id14" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id5"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L58"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L58&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id15" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id6"&gt;[5]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L64"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L64&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id16" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id7"&gt;[6]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L13"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L13&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id17" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id8"&gt;[7]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L152"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L152&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id18" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id9"&gt;[8]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L156"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L156&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id19" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="http://marianoguerra.org/posts/erplorer-search-erlang-and-efene-code-by-pattern-matching-the-ast.html#id10"&gt;[9]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L76"&gt;https://github.com/marianoguerra/erlplorer/blob/0bdd56057dfeb399b9961ae6322f74ccabc2cc5a/src/erlplorer.fn#L76&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/d9738e8fd06681cbd8c1747fed8c6e1f.html</guid><pubDate>Wed, 17 Apr 2019 18:09:00 GMT</pubDate></item><item><title>Facundo Batista: Sincronizando (una historia de "soltar")</title><link>http://planeta.python.org.ar/posts/5c5a4a772a346e990159090cd2810029.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;En una charla nerds con amigos surgió el tema de cómo guardar "pequeñas notas" de forma piola (que se replique, que sea posible buscar, que sea más o menos simple, etc.). En su momento barajamos varias opciones, y a mí me quedó dando vueltas en la cabeza un clientito que se instala y trabaja contra &lt;a class="reference external" href="https://nextcloud.com/"&gt;Nextcloud&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nextcloud es una suite de servicios alrededor de sincronizar archivos, notas, tareas, etc, y ofrece formas de armar grupos de colaboración para trabajar con todo eso. Yo puntualmente estaba interesado en lo que es sincronización de archivos, y potencialmente notas.&lt;/p&gt;
&lt;p&gt;Para mí es todo un viaje, porque tomé la decisión de que si Nextcloud funcionaba correctamente dejaba de usar &lt;a class="reference external" href="http://blog.taniquetil.com.ar/posts/0687/"&gt;Magicicada&lt;/a&gt; (ex Ubuntu One). Aunque estoy emocionalmente atado a ese pedazo de software, y todo lo que representó en mi carrera laboral y como evolución en Python, en algún punto entendí que NUNCA voy a tener tiempo de agregarle los features que quería para que cumpla con todo lo que quiero tener, en parte porque el tiempo que sí tengo prefiero (o preferiría) dedicárselo a otras cosas, incluso a otros proyectos de software, u otros hobbies no tan relacionados con la informática.&lt;/p&gt;
&lt;div class="section" id="la-decision"&gt;
&lt;h3&gt;La decisión&lt;/h3&gt;
&lt;p&gt;Entonces, me voy de Magicicada. Cuando internamente terminó de madurar ese proceso adentro mío, me puse a laburar seriamente con Nextcloud. Lo instalé en mi servercito casero, y funcionó. Luego, toda la fase de cómo usarlo desde cada computadora. Quise probar que sincronice archivos desde el desktop, y a priori no anduvo.&lt;/p&gt;
&lt;p&gt;Investigué un poco, creo que es por algo de la URL, y para dejar 100% como dice el manual del server le tengo que instalar SSL. Puedo para eso usar el servicio de LetsEncrypt, pero para que funcione (según entendí y probé) tengo que tener el puerto 80 accesible desde afuera. El tema es que Claro (mi proveedor de internechi) no me enruta más puerto por puerto, con lo que tendría que armar una DMZ acá en mi intranet, lo cual no es trivial (y asumiendo que el cambio de config de Claro no me rompa otra cosa y  me deje en pelotas y en la vía).&lt;/p&gt;
&lt;p&gt;Pero... pero.... pero.... pero...  Me dí cuenta que NO tengo ganas de crear todo un universo sólo para &lt;a class="reference external" href="https://www.youtube.com/watch?v=LTo31PjL05c"&gt;finalmente tener una tarta de manzana&lt;/a&gt; :)&lt;/p&gt;
&lt;img alt="Alta tarta de manzanas" src="http://blog.taniquetil.com.ar/images/sync/tarta.jpeg"&gt;
&lt;p&gt;Y, pensé en &lt;a class="reference external" href="https://www.dropbox.com"&gt;Dropbox&lt;/a&gt;...&lt;/p&gt;
&lt;p&gt;Hasta ahora venía esquivando Dropbox porque es una empresa yanqui, y meter todos mis datos ahí siempre me dio escozor. Como uno no tiene control sobre la encriptación de los archivos (se encriptan al transmitirse, y teóricamente cuando están guardados, pero Dropbox posee la clave para abrirlos) pueden ver todo lo que tengo. ¿En qué me jodía? Por un lado tengo mucha música en mp3, y aunque toda esa música la bajé de CDs que legalmente compré (!) no quiero que el día de mañana me rompan las pelotas porque les parezca que estoy infringiendo copyright. Por otro lado, tengo un montón de datos sensibles que no me gustaría que queden expuestos al mundo en caso de un fallo de seguridad de Dropbox.&lt;/p&gt;
&lt;p&gt;Pero, estos dos aspectos ahora no me joden tanto. Con respecto a la música, es un riesgo que puedo correr. Con respecto a mis datos privados, hoy por hoy los tengo todos bajo &lt;a class="reference external" href="https://www.keepassx.org/"&gt;KeePassX&lt;/a&gt;, así que todo bien ahí.&lt;/p&gt;
&lt;p&gt;Por otro lado, al mismo tiempo NO quiero todo encriptado, porque ahí ya no podría acceder a mis archivos desde el teléfono o desde la web directamente, en caso de necesitarlo, y este es un feature que sí quiero... y una de las razones fuertes para irme de Magicicada.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="el-nuevo-mundo"&gt;
&lt;h3&gt;El nuevo mundo&lt;/h3&gt;
&lt;p&gt;Habiendo sopesado estas variables, terminé de tomar la decisión. Me voy a Dropbox. La cuenta gratuita no me alcanza, pero la más barata sí, porque me ofrecen un terabyte de almacenamiento (puedo meter todas mis fotos y videos caseros, entre los cuales no llego a los 300GB), y cuesta USD 8.25, que por todo lo que yo uso este servicio, se justifica.&lt;/p&gt;
&lt;p&gt;Igual, antes de "tirarme a la pileta", tenía que hacer otra verificación. Dropbox, ¿funciona?&lt;/p&gt;
&lt;p&gt;Ejecuté una batería de pruebas desde mi computadora de escritorio. Funciona bien con Vim, que es complicado porque mueve/graba/mueve todo el tiempo.  Funciona bien con LibreOffice, que maneja cada documento como un directorio comprimido con montón de archivitos adentros. También le abrí un archivo &lt;tt class="docutils literal"&gt;.tar&lt;/tt&gt; de pocos archivos inmensos, y otro de montonazo de pequeños archivos en una árbol grandote de directorios, y se la bancó.&lt;/p&gt;
&lt;p&gt;Y después ya en el baile le puse toda mi música, y todos mis archivos "simples" (en otras palabras, todo lo que sincronizo normalmente, excepto fotos y videos).&lt;/p&gt;
&lt;p&gt;En todos los casos, fui comprobando los hashes de todo contra lo que el mismo Dropbox bajaba en la laptop. Se la bancó.&lt;/p&gt;
&lt;img alt="Yo, tirándole cosas a Dropbox hasta asegurarme que funca" src="http://blog.taniquetil.com.ar/images/sync/bulletproof.jpeg"&gt;
&lt;p&gt;Bien, ¡funciona! ¿Tiene algunos puntos débiles o negativos? Encontré tres grandes cosas que me molestan...&lt;/p&gt;
&lt;p&gt;Por un lado, tenés que tener &lt;em&gt;todo&lt;/em&gt; dentro del directorio &lt;tt class="docutils literal"&gt;$HOME/Dropbox&lt;/tt&gt;. Con Ubuntu One y Magicicada yo siempre tuve el directorio default de cada uno, más una de Música, una de video, y una de fotos, que eran externas. Pero Dropbox no te deja hacer eso, tiene que estar todo adentro de la misma raíz.&lt;/p&gt;
&lt;p&gt;La solución/parche que implementé es tener un &lt;tt class="docutils literal"&gt;.externals&lt;/tt&gt; en ese directorio raíz, y ahí adentro la de música, fotos y videos, y desde los otros lugares hice un enlace simbólico. No es lo que más lindo queda, pero funciona. Un enlace simbólico al revés NO funciona, ya que Dropbox sincroniza el archivo del &lt;em&gt;symlink&lt;/em&gt; en sí, y no el directorio al que apunta.&lt;/p&gt;
&lt;p&gt;Otro punto negativo que me pareció HORRIBLE al principio pero luego no me pegó tanto (aunque tuve que tocar un par de archivos) es que Dropbox no respeta diferencias entre mayúsculas y minúsculas. O sea, que si vos tenés un archivo &lt;tt class="docutils literal"&gt;barco&lt;/tt&gt; y otro &lt;tt class="docutils literal"&gt;Barco&lt;/tt&gt;, Dropbox NO te sincroniza ambos, sino que uno de los dos te lo renombra para indicarte la &lt;em&gt;colisión&lt;/em&gt;. Entiendo que se debe a que algunos sistemas de archivos de Windows tienen este mismo problema, pero Dropbox debería ser más inteligente y como yo tengo en todos lados Linux, no exponerme a esa limitación.&lt;/p&gt;
&lt;p&gt;Finalmente, Dropbox es bastante flojo con respecto a sus notificaciones y data que tira al usuario. En mi sistema operativo (KDE Neon sobre Ubuntu Bionic) me pone un ícono en el systray que tiene un tilde verde, y cuando está sincronizando titila algo azul. Si lo abro, junto con otra info me dice en qué estado está: normalmente en "Actualizado", a veces mostrando la operación actual, pero de forma bastante resumida.&lt;/p&gt;
&lt;p&gt;Desde linea de comandos puedo hacer &lt;tt class="docutils literal"&gt;dropbox status&lt;/tt&gt; que me muestra esa misma info, pero me es más accesible. También es útil el &lt;tt class="docutils literal"&gt;dropbox ls&lt;/tt&gt; o &lt;tt class="docutils literal"&gt;dropbox filestatus&lt;/tt&gt; pero le falta información realmente sobre qué hizo, algo detallado que muestre en qué estado está con cada cosa, o donde poder revisar qué pasó media hora atrás... o sea, logs.&lt;/p&gt;
&lt;img alt="Quiero ver qué está haciendo, dejame ver qué está haciendo, mostrame qué está haciendo" src="http://blog.taniquetil.com.ar/images/sync/rawdata.jpeg"&gt;
&lt;p&gt;Entiendo que a la mayoría de los usuarios finales no les importe más información que esa, pero yo en algunos casos &lt;em&gt;necesito&lt;/em&gt; tener más control de lo que está haciendo o pasó.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="y-las-pequenas-notas"&gt;
&lt;h3&gt;¿Y las pequeñas notas?&lt;/h3&gt;
&lt;p&gt;Para cerrar el ciclo con el arranque del artículo, ¿qué onda sincronizar notas? &lt;a class="reference external" href="https://chaghi.com.ar/"&gt;Mariano&lt;/a&gt; me dijo que usaba bastante &lt;a class="reference external" href="http://zim-wiki.org/"&gt;Zim Wiki&lt;/a&gt;, que es 100% texto y guarda las cosas en archivos sincronizados por, claro, Dropbox.&lt;/p&gt;
&lt;p&gt;Él lo usa con el cliente que proveen en Linux y Windows, o directamente tocando el archivo de texto correspondiente en el teléfono.  Me comentó también que tiene un "buscar" que funciona, y permite agregarle etiquetas (&lt;em&gt;tags&lt;/em&gt;) a las notas.&lt;/p&gt;
&lt;p&gt;Lo voy a probar.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/5c5a4a772a346e990159090cd2810029.html</guid><pubDate>Tue, 16 Apr 2019 16:01:00 GMT</pubDate></item><item><title>Mariano Guerra: Elixir protocols, how do they work? the erlang perspective</title><link>http://planeta.python.org.ar/posts/4ed3cf19c8f8ff88f9412f73e37685b2.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;We will start by creating a new project to &lt;cite&gt;learn&lt;/cite&gt; more about Elixir protocols:&lt;/p&gt;
&lt;pre class="code elixir"&gt;&lt;a name="rest_code_26916acd59544dc6b963697329c661bf-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;mix&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;learn&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;Learn&lt;/span&gt;
&lt;a name="rest_code_26916acd59544dc6b963697329c661bf-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;learn&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;note: I'm using Erlang 21.3 and Elixir 1.8.1 and I never coded in Elixir before :)&lt;/p&gt;
&lt;p&gt;I searched for Elixir protocols and found the official documentation with an
example for a &lt;a class="reference external" href="https://elixir-lang.org/getting-started/protocols.html"&gt;Size protocol&lt;/a&gt;
I added it to the &lt;cite&gt;lib/learn.ex&lt;/cite&gt; file and added some calls on the hello function
to try it, it ended up looking like this:&lt;/p&gt;
&lt;pre class="code elixir"&gt;&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;defmodule&lt;/span&gt; &lt;span class="nc"&gt;Learn&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-2"&gt;&lt;/a&gt;  &lt;span class="na"&gt;@moduledoc&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-3"&gt;&lt;/a&gt;&lt;span class="sh"&gt;  Documentation for Learn.&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-4"&gt;&lt;/a&gt;&lt;span class="sh"&gt;  """&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-6"&gt;&lt;/a&gt;  &lt;span class="na"&gt;@doc&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-7"&gt;&lt;/a&gt;&lt;span class="sh"&gt;  Hello world.&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-8"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-9"&gt;&lt;/a&gt;&lt;span class="sh"&gt;  &lt;/span&gt;&lt;span class="err"&gt;##&lt;/span&gt;&lt;span class="sh"&gt; Examples&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-10"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-11"&gt;&lt;/a&gt;&lt;span class="sh"&gt;  iex&amp;gt; Learn.hello()&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-12"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-13"&gt;&lt;/a&gt;&lt;span class="sh"&gt;  """&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-14"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-15"&gt;&lt;/a&gt;    &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"asd"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-16"&gt;&lt;/a&gt;    &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(%{})&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-17"&gt;&lt;/a&gt;    &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-18"&gt;&lt;/a&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-19"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-20"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;defprotocol&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-21"&gt;&lt;/a&gt;    &lt;span class="na"&gt;@doc&lt;/span&gt; &lt;span class="s2"&gt;"Calculates the size (and not the length!) of a data structure"&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-22"&gt;&lt;/a&gt;    &lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-23"&gt;&lt;/a&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-24"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-25"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;defimpl&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BitString&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-26"&gt;&lt;/a&gt;    &lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;byte_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-27"&gt;&lt;/a&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-28"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-29"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;defimpl&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-30"&gt;&lt;/a&gt;    &lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;map_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-31"&gt;&lt;/a&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-32"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-33"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;defimpl&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Tuple&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-34"&gt;&lt;/a&gt;    &lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tuple_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-35"&gt;&lt;/a&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-36"&gt;&lt;/a&gt;
&lt;a name="rest_code_7f45a51123e84412971f8b39f33d4090-37"&gt;&lt;/a&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Compiled the project:&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_3f8d85856504466989b2ef297d6f1fc5-1"&gt;&lt;/a&gt;mix compile
&lt;/pre&gt;&lt;p&gt;Opened an Elixir shell:&lt;/p&gt;
&lt;pre class="code sh"&gt;&lt;a name="rest_code_958786b06bef4968a16042e42e425f7c-1"&gt;&lt;/a&gt;iex
&lt;/pre&gt;&lt;p&gt;Wrote a little script to decompile all beam files to Erlang (warning: Elixir
flavored Erlang ahead!):&lt;/p&gt;
&lt;pre class="code elixir"&gt;&lt;a name="rest_code_34a1d93212a84b9f930baf35d6a71fc0-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="ss"&gt;:filelib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wildcard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./_build/dev/lib/*/*/*.beam'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_34a1d93212a84b9f930baf35d6a71fc0-2"&gt;&lt;/a&gt;  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:beam_lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="ss"&gt;:abstract_code&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;a name="rest_code_34a1d93212a84b9f930baf35d6a71fc0-3"&gt;&lt;/a&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="bp"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,[{&lt;/span&gt;&lt;span class="ss"&gt;:abstract_code&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="bp"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ac&lt;/span&gt;&lt;span class="p"&gt;}}]}}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;a name="rest_code_34a1d93212a84b9f930baf35d6a71fc0-4"&gt;&lt;/a&gt;  &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:erl_prettypr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:erl_syntax&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ac&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a name="rest_code_34a1d93212a84b9f930baf35d6a71fc0-5"&gt;&lt;/a&gt;  &lt;span class="n"&gt;out_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.beam'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.erl'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_34a1d93212a84b9f930baf35d6a71fc0-6"&gt;&lt;/a&gt;  &lt;span class="ss"&gt;:file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_34a1d93212a84b9f930baf35d6a71fc0-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The results:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$  tree
.
├── _build
│   └── dev
│       └── lib
│           └── learn
│               ├── consolidated
│               │   ├── Elixir.Collectable.beam
│               │   ├── Elixir.Collectable.erl
│               │   ├── Elixir.Enumerable.beam
│               │   ├── Elixir.Enumerable.erl
│               │   ├── Elixir.IEx.Info.beam
│               │   ├── Elixir.IEx.Info.erl
│               │   ├── Elixir.Inspect.beam
│               │   ├── Elixir.Inspect.erl
│               │   ├── Elixir.Learn.Size.beam
│               │   ├── Elixir.Learn.Size.erl
│               │   ├── Elixir.List.Chars.beam
│               │   ├── Elixir.List.Chars.erl
│               │   ├── Elixir.String.Chars.beam
│               │   └── Elixir.String.Chars.erl
│               └── ebin
│                   ├── Elixir.Learn.beam
│                   ├── Elixir.Learn.erl
│                   ├── Elixir.Learn.Size.beam
│                   ├── Elixir.Learn.Size.BitString.beam
│                   ├── Elixir.Learn.Size.BitString.erl
│                   ├── Elixir.Learn.Size.erl
│                   ├── Elixir.Learn.Size.Map.beam
│                   ├── Elixir.Learn.Size.Map.erl
│                   ├── Elixir.Learn.Size.Tuple.beam
│                   ├── Elixir.Learn.Size.Tuple.erl
│                   └── learn.app
&lt;/pre&gt;
&lt;p&gt;From the result it seems that it "consolidates" the protocols into the
&lt;cite&gt;consolidated&lt;/cite&gt; folder and then puts the modules at &lt;cite&gt;ebin&lt;/cite&gt; (with protocol
implementations named like the protocol plus the type they handle).&lt;/p&gt;
&lt;p&gt;It's also clear that all Elixir modules are prefixed with &lt;cite&gt;Elixir.&lt;/cite&gt;, also that
if I declare a protocol inside a module the protocol "belongs" to the module,
in this case the "full qualified name" of the protocol is &lt;cite&gt;Elixir.Learn.Size&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Let's start exploring what code is generated by inspecting the main module we
wrote (I will cleanup unneeded code from the examples):&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_d5f9a94f22c14716b85a139a057dde6a-1"&gt;&lt;/a&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'Elixir.Learn'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a name="rest_code_d5f9a94f22c14716b85a139a057dde6a-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;export&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;
&lt;a name="rest_code_d5f9a94f22c14716b85a139a057dde6a-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_d5f9a94f22c14716b85a139a057dde6a-4"&gt;&lt;/a&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_d5f9a94f22c14716b85a139a057dde6a-5"&gt;&lt;/a&gt;    &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"asd"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;a name="rest_code_d5f9a94f22c14716b85a139a057dde6a-6"&gt;&lt;/a&gt;    &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(#{}),&lt;/span&gt;
&lt;a name="rest_code_d5f9a94f22c14716b85a139a057dde6a-7"&gt;&lt;/a&gt;    &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;We can see that calling a function from a protocol implies calling the desired
function on the consolidated module for the protocol itself.&lt;/p&gt;
&lt;p&gt;Let's now see what the &lt;cite&gt;Elixir.Learn.Size&lt;/cite&gt; module does:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-1"&gt;&lt;/a&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;export&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;'__protocol__'&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;impl_for&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;'impl_for!'&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-4"&gt;&lt;/a&gt;&lt;span class="nf"&gt;'impl_for!'&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-5"&gt;&lt;/a&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-6"&gt;&lt;/a&gt;      &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=:=&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt; &lt;span class="ow"&gt;orelse&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=:=&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-7"&gt;&lt;/a&gt;      &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;'Elixir.Protocol.UndefinedError'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-8"&gt;&lt;/a&gt;                                    &lt;span class="n"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-9"&gt;&lt;/a&gt;                                   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-10"&gt;&lt;/a&gt;                                    &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}]));&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-11"&gt;&lt;/a&gt;      &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-12"&gt;&lt;/a&gt;    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-13"&gt;&lt;/a&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-14"&gt;&lt;/a&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'impl_for!'&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-15"&gt;&lt;/a&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-16"&gt;&lt;/a&gt;&lt;span class="nf"&gt;struct_impl_for&lt;/span&gt;&lt;span class="p"&gt;(_)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-17"&gt;&lt;/a&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-18"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(#{&lt;/span&gt;&lt;span class="n"&gt;'__struct__'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-19"&gt;&lt;/a&gt;    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;is_atom&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-20"&gt;&lt;/a&gt;    &lt;span class="n"&gt;struct_impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-21"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;is_tuple&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-22"&gt;&lt;/a&gt;    &lt;span class="n"&gt;'Elixir.Learn.Size.Tuple'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-23"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;is_map&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-24"&gt;&lt;/a&gt;    &lt;span class="n"&gt;'Elixir.Learn.Size.Map'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-25"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;is_bitstring&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-26"&gt;&lt;/a&gt;    &lt;span class="n"&gt;'Elixir.Learn.Size.BitString'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-27"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(_)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-28"&gt;&lt;/a&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-29"&gt;&lt;/a&gt;&lt;span class="nf"&gt;'__protocol__'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-30"&gt;&lt;/a&gt;&lt;span class="nf"&gt;'__protocol__'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}];&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-31"&gt;&lt;/a&gt;&lt;span class="nf"&gt;'__protocol__'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'consolidated?'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-32"&gt;&lt;/a&gt;&lt;span class="nf"&gt;'__protocol__'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;impls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-33"&gt;&lt;/a&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;consolidated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_290012b9d66149eca54cd6ebea200e9a-34"&gt;&lt;/a&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;'Elixir.Map'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;'Elixir.BitString'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;'Elixir.Tuple'&lt;/span&gt;&lt;span class="p"&gt;]}.&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The exported function for the protocol (&lt;cite&gt;size/1&lt;/cite&gt;) does a simple thing, it asks
the &lt;cite&gt;impl_for!/1&lt;/cite&gt; function for the module that knows how to handle
&lt;cite&gt;Learn.Size.size/1&lt;/cite&gt; for the given argument and then calls that module's
&lt;cite&gt;size/1&lt;/cite&gt; function:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_bebc2c13a0724752a042c8bd8cfed835-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'impl_for!'&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;&lt;cite&gt;impl_for!/1&lt;/cite&gt; just calls &lt;cite&gt;impl_for/1&lt;/cite&gt; with the argument and handles the case
where the value doesn't have a known implementation, in that case it raises an
exception (&lt;cite&gt;Elixir.Protocol.UndefinedError&lt;/cite&gt;), otherwise it just returns the
module name.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;impl_for/1&lt;/cite&gt; starts by checking if the argument is an &lt;a class="reference external" href="https://elixir-lang.org/getting-started/structs.html"&gt;Elixir struct&lt;/a&gt;,
which underneath is just a map with a "well known" key &lt;cite&gt;__struct__&lt;/cite&gt; that
contains the type of the struct as an atom:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_7bdadab8d0d44d43b59cbac83ae6bef8-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(#{&lt;/span&gt;&lt;span class="n"&gt;'__struct__'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;a name="rest_code_7bdadab8d0d44d43b59cbac83ae6bef8-2"&gt;&lt;/a&gt;    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;is_atom&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;if it's a struct it calls &lt;cite&gt;struct_impl_for/1&lt;/cite&gt; with the struct type as argument:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_d31ce6ba0b7c4b55b87e65f05b4ba0fe-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;struct_impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;In our example, there's no struct that implements this protocol so the implementation of &lt;cite&gt;struct_impl_for/1&lt;/cite&gt; is simple:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_3587bf5a870e47878af1315e56c230b2-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;struct_impl_for&lt;/span&gt;&lt;span class="p"&gt;(_)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;After that it starts trying to find the implementation for non protocol types (mostly Erlang types), it tries to match using guards to check for the types, if none match, it returns nil like &lt;cite&gt;struct_impl_for/1&lt;/cite&gt;:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;is_tuple&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-2"&gt;&lt;/a&gt;    &lt;span class="n"&gt;'Elixir.Learn.Size.Tuple'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-4"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;is_map&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-5"&gt;&lt;/a&gt;    &lt;span class="n"&gt;'Elixir.Learn.Size.Map'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-6"&gt;&lt;/a&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-7"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;is_bitstring&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-8"&gt;&lt;/a&gt;    &lt;span class="n"&gt;'Elixir.Learn.Size.BitString'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_7301dde976f6484989bae3701d8ed6f9-10"&gt;&lt;/a&gt;&lt;span class="nf"&gt;impl_for&lt;/span&gt;&lt;span class="p"&gt;(_)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Now that we got the module that handles the protocol function for each type, let's see their implementations:&lt;/p&gt;
&lt;p&gt;Elixir.Learn.Size.BitString:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_c7e5f1e37516461db16e54d6772b2868-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;byte_size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Elixir.Learn.Size.Map:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_5000575923294fa8b55999785bac27ca-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;map_size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Elixir.Learn.Size.Tuple:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_b143ea49c5a841c49d95bdbaacbfaeee-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;tuple_size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Now that we got the basic call and dispatch sequence let's try adding two
structs and implement this protocol to see how it works for them:&lt;/p&gt;
&lt;p&gt;I added two structs to the lib/learn.ex module:&lt;/p&gt;
&lt;pre class="code elixir"&gt;&lt;a name="rest_code_9d7fd26bdb47440d8bae4c71bde0acb8-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;
&lt;a name="rest_code_9d7fd26bdb47440d8bae4c71bde0acb8-2"&gt;&lt;/a&gt;
&lt;a name="rest_code_9d7fd26bdb47440d8bae4c71bde0acb8-3"&gt;&lt;/a&gt;&lt;span class="kd"&gt;defmodule&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_9d7fd26bdb47440d8bae4c71bde0acb8-4"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;
&lt;a name="rest_code_9d7fd26bdb47440d8bae4c71bde0acb8-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Added calls to &lt;cite&gt;Size.size/1&lt;/cite&gt; in the &lt;cite&gt;hello/0&lt;/cite&gt; function:&lt;/p&gt;
&lt;pre class="code elixir"&gt;&lt;a name="rest_code_9fe1d2eb58394e30a5a8dcd3308f2788-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_9fe1d2eb58394e30a5a8dcd3308f2788-2"&gt;&lt;/a&gt;  &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"asd"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_9fe1d2eb58394e30a5a8dcd3308f2788-3"&gt;&lt;/a&gt;  &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(%{})&lt;/span&gt;
&lt;a name="rest_code_9fe1d2eb58394e30a5a8dcd3308f2788-4"&gt;&lt;/a&gt;  &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;a name="rest_code_9fe1d2eb58394e30a5a8dcd3308f2788-5"&gt;&lt;/a&gt;  &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;a name="rest_code_9fe1d2eb58394e30a5a8dcd3308f2788-6"&gt;&lt;/a&gt;  &lt;span class="nc"&gt;Learn.Size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="nc"&gt;Learn&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;a name="rest_code_9fe1d2eb58394e30a5a8dcd3308f2788-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;And implemented the protocol &lt;cite&gt;Size&lt;/cite&gt; for both structs:&lt;/p&gt;
&lt;pre class="code elixir"&gt;&lt;a name="rest_code_d6460c2283214bad8327a70458897e76-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;defimpl&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Learn&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_d6460c2283214bad8327a70458897e76-2"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;learn&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;learn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;a name="rest_code_d6460c2283214bad8327a70458897e76-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_d6460c2283214bad8327a70458897e76-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_d6460c2283214bad8327a70458897e76-5"&gt;&lt;/a&gt;&lt;span class="kd"&gt;defimpl&lt;/span&gt; &lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_d6460c2283214bad8327a70458897e76-6"&gt;&lt;/a&gt;  &lt;span class="kd"&gt;def&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;a name="rest_code_d6460c2283214bad8327a70458897e76-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Compiled with &lt;cite&gt;mix compile&lt;/cite&gt; and inside &lt;cite&gt;iex&lt;/cite&gt; pasted the script again, let's
see what changed.&lt;/p&gt;
&lt;p&gt;The hello world function looks like this:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-2"&gt;&lt;/a&gt;        &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"asd"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-3"&gt;&lt;/a&gt;        &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(#{}),&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-4"&gt;&lt;/a&gt;        &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-5"&gt;&lt;/a&gt;        &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(#{&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-6"&gt;&lt;/a&gt;                                   &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-7"&gt;&lt;/a&gt;                                   &lt;span class="n"&gt;'__struct__'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;'Elixir.Learn.User'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-8"&gt;&lt;/a&gt;        &lt;span class="nn"&gt;'Elixir.Learn.Size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(#{&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-9"&gt;&lt;/a&gt;                                   &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_1e1e25c08db64a449d26cfeebdb5c7a0-10"&gt;&lt;/a&gt;                                   &lt;span class="n"&gt;'__struct__'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;'Elixir.Learn'&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Which confirms that Elixir structs are maps with a special &lt;cite&gt;__struct__&lt;/cite&gt; key.&lt;/p&gt;
&lt;p&gt;Checking the generated files, there's a new file for our &lt;cite&gt;User&lt;/cite&gt; struct
(&lt;cite&gt;Elixir.Learn.User.erl&lt;/cite&gt;), the other struct is defined inside
&lt;cite&gt;Elixir.Learn.erl&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;The module code relevant for the struct doesn't have anything specific to the
protocols it implements:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-1"&gt;&lt;/a&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'Elixir.Learn.User'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="ni"&gt;export&lt;/span&gt;&lt;span class="p"&gt;([_&lt;/span&gt;&lt;span class="n"&gt;struct__'/0, '&lt;/span&gt;&lt;span class="p"&gt;__&lt;/span&gt;&lt;span class="n"&gt;struct__&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-4"&gt;&lt;/a&gt;&lt;span class="nf"&gt;'__struct__'&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-5"&gt;&lt;/a&gt;        &lt;span class="p"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;'__struct__'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;'Elixir.Learn.User'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-6"&gt;&lt;/a&gt;          &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-8"&gt;&lt;/a&gt;&lt;span class="nf"&gt;'__struct__'&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-9"&gt;&lt;/a&gt;        &lt;span class="nn"&gt;'Elixir.Enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-10"&gt;&lt;/a&gt;                         &lt;span class="p"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;'__struct__'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;'Elixir.Learn.User'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-11"&gt;&lt;/a&gt;                           &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-12"&gt;&lt;/a&gt;                         &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;({__@&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-13"&gt;&lt;/a&gt;                                 &lt;span class="nn"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_439f5d8597db4b4ea409db3cc5f79295-14"&gt;&lt;/a&gt;                         &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Almost the same code is inside &lt;cite&gt;Elixir.Learn.erl&lt;/cite&gt; for the other struct.&lt;/p&gt;
&lt;p&gt;This shows that each struct has two "constructors", one without arguments that
returns a struct with the default values for all fields and one that merges
the arguments on the default values.&lt;/p&gt;
&lt;p&gt;Let's see what changed on the consolidated protocol module:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_4f9d329367964bedac962e49c2a2a9e5-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;struct_impl_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'Elixir.Learn.User'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_4f9d329367964bedac962e49c2a2a9e5-2"&gt;&lt;/a&gt;        &lt;span class="n"&gt;'Elixir.Learn.Size.Learn.User'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_4f9d329367964bedac962e49c2a2a9e5-3"&gt;&lt;/a&gt;&lt;span class="nf"&gt;struct_impl_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'Elixir.Learn'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_4f9d329367964bedac962e49c2a2a9e5-4"&gt;&lt;/a&gt;        &lt;span class="n"&gt;'Elixir.Learn.Size.Learn'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_4f9d329367964bedac962e49c2a2a9e5-5"&gt;&lt;/a&gt;&lt;span class="nf"&gt;struct_impl_for&lt;/span&gt;&lt;span class="p"&gt;(_)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Each struct &lt;cite&gt;type&lt;/cite&gt; returns the module where the protocol is implemented,
let's see both implementations:&lt;/p&gt;
&lt;p&gt;Elixir.Learn.Size.Learn.User.erl:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_f106247c7c894489881b71f703187297-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_f106247c7c894489881b71f703187297-2"&gt;&lt;/a&gt;        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
&lt;a name="rest_code_f106247c7c894489881b71f703187297-3"&gt;&lt;/a&gt;          &lt;span class="p"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_f106247c7c894489881b71f703187297-4"&gt;&lt;/a&gt;          &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;is_map&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_f106247c7c894489881b71f703187297-5"&gt;&lt;/a&gt;          &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;badkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;a name="rest_code_f106247c7c894489881b71f703187297-6"&gt;&lt;/a&gt;          &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a name="rest_code_f106247c7c894489881b71f703187297-7"&gt;&lt;/a&gt;        &lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_f106247c7c894489881b71f703187297-8"&gt;&lt;/a&gt;          &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Elixir.Learn.Size.Learn.erl:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(_&lt;/span&gt;&lt;span class="n"&gt;learn&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-2"&gt;&lt;/a&gt;        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt;&lt;span class="n"&gt;learn&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-3"&gt;&lt;/a&gt;          &lt;span class="p"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-4"&gt;&lt;/a&gt;          &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;is_map&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-5"&gt;&lt;/a&gt;          &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;badkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-6"&gt;&lt;/a&gt;          &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-7"&gt;&lt;/a&gt;        &lt;span class="k"&gt;end&lt;/span&gt;
&lt;a name="rest_code_c694d18a84bd46f0adfb39bba93e244f-8"&gt;&lt;/a&gt;          &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Summary:&lt;/p&gt;
&lt;p&gt;Elixir protocols are compiled to its own module whose content is the
consolidated dispatch logic for it.&lt;/p&gt;
&lt;p&gt;This logic is created by getting all the &lt;cite&gt;defimpl&lt;/cite&gt; statements for it and adding
a function clause to the &lt;cite&gt;struct_impl_for/1&lt;/cite&gt; function if the target type is an
Elixir struct and a clause to the &lt;cite&gt;impl_for/1&lt;/cite&gt; function if the target type is
any other type.&lt;/p&gt;
&lt;p&gt;The function (&lt;cite&gt;impl_for!/1&lt;/cite&gt;) returns the module that has the protocol
implementation for the provided type.&lt;/p&gt;
&lt;p&gt;Each protocol function asks for the module via &lt;cite&gt;impl_for!/1&lt;/cite&gt; and calls it with
the given arguments.&lt;/p&gt;
&lt;p&gt;This is just guessing, but the module indirection must be there to allow
hot code reloading protocol implementations for each type independently without
requiring also reloading the protocol consolidation. The struct_impl_for function
is there to destructure the map only once.&lt;/p&gt;
&lt;p&gt;I don't see traces of dynamic dispatch in case a module is loaded with a
protocol implementation that was not known at consolidation time, I need
to research this further.&lt;/p&gt;
&lt;p&gt;An extra guess, this logic on the struct field to get the &lt;cite&gt;age&lt;/cite&gt; field:&lt;/p&gt;
&lt;pre class="code erlang"&gt;&lt;a name="rest_code_c5f47891b3c840b7826f80bf80302df9-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt;&lt;span class="n"&gt;learn&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
&lt;a name="rest_code_c5f47891b3c840b7826f80bf80302df9-2"&gt;&lt;/a&gt;  &lt;span class="p"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_c5f47891b3c840b7826f80bf80302df9-3"&gt;&lt;/a&gt;  &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;is_map&lt;/span&gt;&lt;span class="p"&gt;(__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a name="rest_code_c5f47891b3c840b7826f80bf80302df9-4"&gt;&lt;/a&gt;  &lt;span class="nn"&gt;erlang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;badkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;a name="rest_code_c5f47891b3c840b7826f80bf80302df9-5"&gt;&lt;/a&gt;  &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;__@&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a name="rest_code_c5f47891b3c840b7826f80bf80302df9-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;May be because Elixir allows to call a struct "method" without parenthesis and
that's why it looks for the field first and the function with the same name second?
I'm not entirely sure since my Elixir knowledge is basically non existent :)&lt;/p&gt;
&lt;p&gt;If you have any questions or corrections I'm &lt;a class="reference external" href="https://twitter.com/warianoguerra"&gt;@warianoguerra&lt;/a&gt; my other accounts here: &lt;a class="reference external" href="https://keybase.io/marianoguerra"&gt;https://keybase.io/marianoguerra&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/4ed3cf19c8f8ff88f9412f73e37685b2.html</guid><pubDate>Sun, 07 Apr 2019 18:50:00 GMT</pubDate></item><item><title>Facundo Batista: Películas, duda, series</title><link>http://planeta.python.org.ar/posts/15a32071a42cbfc6cba819cdafe6e7be.html</link><dc:creator>PyAr</dc:creator><description>&lt;div&gt;&lt;p&gt;De nuevo vi bastante más que las que anoté para ver. Pero no le estoy dedicando mucho tiempo a ver películas (aunque aproveché bastante los vuelos largos en el último viaje), con lo cual creo que lo que pasa es que estoy anotando pocas nuevas.&lt;/p&gt;
&lt;p&gt;¿Por qué? Creo que porque no hay mucho que me interese de lo que está saliendo (por ejemplo, ignoro todo lo que sean películas basadas en guerra, o de terror "normal" (o sea, aburrido), o la trigésimo novena de los avengers, etc...).&lt;/p&gt;
&lt;p&gt;¿O quizás estoy perdiéndome de ver trailers que están buenos? ¿Hay películas que están por salir que piensan que están buenas y NO estoy anotando? ¿Mejores lugares para buscar trailers que &lt;a class="reference external" href="https://www.imdb.com/trailers"&gt;IMDb&lt;/a&gt;? Propongan.&lt;/p&gt;
&lt;p&gt;Por otro lado, estuve arrancando y cerrando un par de series. Recomiendo fuerte &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Borgen"&gt;Borgen&lt;/a&gt;, enterita. Es muy buena. La primera temporada de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Fargo_(serie_de_televisi%C3%B3n)"&gt;Fargo&lt;/a&gt; es &lt;strong&gt;genial&lt;/strong&gt;, la segunda pinta muy bien (estoy en eso). También estoy viendo &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Girls_(serie_de_televisi%C3%B3n)"&gt;Girls&lt;/a&gt;, que zafa. Y para que vean que no son todas rosas, tenía bajadas para ver y no pude pasar del primer capítulo (y picoteos de otros capítulos, para asegurarme de no llevarme una impresión equivocada) de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Flight_of_the_Conchords"&gt;Flight of the Conchords&lt;/a&gt; (no es mi tipo de humor, no me da nada, muy aburrida) y &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Dark_Net_(TV_series)"&gt;Dark Net&lt;/a&gt; (odio las series medio en primera persona onda "yo soy un muchacho tranquilo, crecí en oklahoma, conocí mi chica online" mientras lo muestran llevarle pasto a una vaca o una boludez así).&lt;/p&gt;
&lt;p&gt;Bueno. A los bifes...&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1727770/"&gt;Absolutely Anything&lt;/a&gt;: +0. Una idea no nueva, pero encarada de un lado interesante y divertida.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt2406566/"&gt;Atomic Blonde&lt;/a&gt;: +0. No deja de ser una de espías en la época de la guerra fría, pero atrapa, divierte, y convence (si es que te interesa ese tipo de películas).&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt2449638/"&gt;Atomica&lt;/a&gt;: -0. El contexto y parte de la historia eran interesantes, pero las actuaciones bleh, la peli en general no suma.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5614612/"&gt;Black Snow&lt;/a&gt;: -0. La historia zafa y las actuaciones están buenas, pero es muy lenta por partes, y no te deja gran cosa.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt3716530/"&gt;Elle&lt;/a&gt;: -0. Es una historia chata, en el sentido que va contando cosas que poquito a poquito suma un relato, pero nunca te das cuenta cual es el nudo de la cuestión, entonces como que no vas entendiendo mucho, pero algo se forma; más allá de eso, no me entusiasmó nada.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1290138/"&gt;Frank &amp;amp; Lola&lt;/a&gt;: +0. La película está bien, no es gran cosa pero cierra y se pasa un buen rato. Compensan que sí me gustan las películas "de chefs" y que no me gustan las películas donde las parejas tienen relaciones tóxicas.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt4975856/"&gt;Future Man&lt;/a&gt;: No es una peli, sino una serie! Ahí la reencolé donde corresponde, sacándola de acá.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt3625516/"&gt;MindGamers&lt;/a&gt;: -0. Tiene partes muy interesantes, pero el estilo de filmación la hace medio insoportable, y aunque una notable suma de sinsentidos parece acomodarse luego, no llega a funcionar.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt3402236/"&gt;Murder on the Orient Express&lt;/a&gt;: -0. No me terminó de enganchar... No sé exactamente qué es lo que hizo que la peli se me haga muy anodina.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1355644/"&gt;Passengers&lt;/a&gt;: +0. Divertida, con efectos interesantes, con una trama liviana pero dinámica y se la pasa bien.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1677720/"&gt;Ready Player One&lt;/a&gt;: +0. Está buena por los efectos y por todas las referencias... luego la historia no me llamó demasiado la atención.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5149030/"&gt;Rooster's Blood&lt;/a&gt;: +0. Casi la saco cuando habían pasado veinte minutos y la historia no apuntaba a ningún lado, pero terminó zafando y está buena. Hay que bancarse algunos planos lentos interminables, pero va.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5034474/"&gt;The Assignment&lt;/a&gt;: -0. Me gustó la forma gráfica de contar y mostrar la historia, y la historia misma no está mal, con un par de vueltas que sorprenden y te llevan hasta el final. Pero está armada como si fuese el suceso épico del cine y se queda muy corta, y eso hace que le reste un montón.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt3289956/"&gt;The Autopsy of Jane Doe&lt;/a&gt;: +1. Con la base de la historia muy conocida (se trató miles de veces), la peli logra darle un giro totalmente "real" pero sorprendente, lo cual más allá de que la peli es en sí de terror, tiene ese misterio que te lleva hasta al final y vale la pena.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt4287320/"&gt;The Circle&lt;/a&gt;: +0. La historia zafa, los paralelos con la realidad son evidentes; es una muy buena película para que muchos tomen conciencia de a donde nos dirigimos.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1967614/"&gt;The Comedian&lt;/a&gt;: -0. La historia zafa, pero no va a ningún lado, las actuaciones están bien, pero a la peli le falta como "consistencia"...&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5155780/"&gt;The Discovery&lt;/a&gt;: +0. El concepto base de la historia está bueno, la trama alrededor también, y la vuelta del final es inesperada. Está bien.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5666304/"&gt;The Little Hours&lt;/a&gt;: +0. Muy divertida, muy atípica. Ligeramente basada en el Decamerón, es una excusa para hilar una historia que lleva bien la peli.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5669936/"&gt;The Recall&lt;/a&gt;: -1. Es muy mala. Así y todo la terminé de ver, porque no es que haya algo que sea insoportable, sólo es muy mala de forma parejita :).&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt3503406/"&gt;The Whole Truth&lt;/a&gt;: +0. Está bien, se nota que la trama es más compleja y está resuelta con la voz en off, pero se sigue bien y se arma todo bien, con un desenlace no esperado y que cambia un poco la perspectiva de lo anterior.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1734493/"&gt;Unlocked&lt;/a&gt;: +0. No deja de ser una de espías/acción, pero las idas y vuelta que tiene la hacen interesante. Pierde un poco la gracia el final como apostando a secuelas, pero bueh, la primera zafa, si hacen una continuación no me anoto...&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1536537/"&gt;What Happened to Monday&lt;/a&gt;: +0. Muy rara, pero entretenida. Lo que labura la actriz con los múltiples papeles es loable.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5446858/"&gt;Zero Days&lt;/a&gt;: -1. No la pude terminar de ver de lo embolante que era. Hay toda una parte interesante que es, justamente, el tema del virus. Y todo lo relacionado con la planta atómica también está bueno. Pero si estirás eso a casi dos horas de película, encima en ese formato de "entrevistas", se hace insoportable.&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Jane Doe" src="http://blog.taniquetil.com.ar/images/pelis/janedoe.png"&gt;
&lt;p&gt;De las pocas nuevas...&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt2274648/"&gt;Hellboy&lt;/a&gt;: (2019; Action, Adventure, Fantasy, Sci-Fi) Based on the graphic novels by Mike Mignola, Hellboy, caught between the worlds of the supernatural and human, battles an ancient sorceress bent on revenge.::Dominic Henriott AND ABDUL [D: Neil Marshall; A: David Harbour, Milla Jovovich, Ian McShane]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt8079248/"&gt;Yesterday&lt;/a&gt;: (2019; Comedy, Drama, Fantasy, Music, Musical, Romance) A struggling musician realizes he's the only person on Earth who can remember The Beatles.::a_clockwork_alpaca [D: Danny Boyle; A: Ana de Armas, Lily James, Kate McKinnon]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt7173652/"&gt;All Inclusive&lt;/a&gt;: (2018; Comedy) Pablo and Lucia live together. Pablo buys an All-Inclusive in Brazil online as a surprise for Lucia but his boss firing him, so Pablo tries to cancel the trip but he can't. They travel anyway, but Brazil waits with nothing but trouble.. [D: Diego Levy, Pablo Levy; A: Alan Sabbagh, Julieta Zylberberg, Mike Amigorena]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt7589524/"&gt;Aniara&lt;/a&gt;: (2018; Drama, Sci-Fi) A spaceship carrying settlers to Mars is knocked off course, causing the consumption-obsessed passengers to consider their place in the universe. [D: Pella Kagerman, Hugo Lilja; A: Emelie Jonsson, Bianca Cruzeiro, Arvin Kananian]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt6131450/"&gt;Asher&lt;/a&gt;: (2018; Drama, Thriller) An aging hitman's last job goes sideways, forcing him to redeem himself. [D: Michael Caton-Jones; A: Famke Janssen, Ron Perlman, Richard Dreyfuss]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt8425058/"&gt;Brexit&lt;/a&gt;: (2019; Biography, Drama, History) Political strategist Dominic Cummings leads a popular but controversial campaign to convince British voters to leave the European Union from 2015 up until the present day. [D: Toby Haynes; A: Benedict Cumberbatch, Sarah Belcher, Malcolm Freeman]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5886046/"&gt;Escape Room&lt;/a&gt;: (2019; Action, Adventure, Drama, Horror, Mystery, Sci-Fi, Thriller) Six strangers find themselves in a maze of deadly mystery rooms, and must use their wits to survive. [D: Adam Robitel; A: Taylor Russell, Logan Miller, Jay Ellis]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt6966692/"&gt;Green Book&lt;/a&gt;: (2018; Biography, Comedy, Drama, Music) A working-class Italian-American bouncer becomes the driver of an African-American classical pianist on a tour of venues through the 1960s American South. [D: Peter Farrelly; A: Viggo Mortensen, Mahershala Ali, Linda Cardellini]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt5034212/"&gt;Incontrol&lt;/a&gt;: (2017; Drama, Sci-Fi, Thriller) 4 university students hook up to a machine allowing them to become one of their fellow students - e.g. allowing them each to party as one of the rich and beautiful. The long hook-ups start seriously affecting their normal selves.::Scott Filtenborg [D: Kurtis David Harder; A: Sarah Troyer, Anja Savcic, Valerie Planche]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt0837563/"&gt;Pet Sematary&lt;/a&gt;: (2019; Horror, Thriller) Louis Creed, his wife Rachel, and their two children Gage and Ellie move to a rural home where they are welcomed and enlightened about the eerie 'Pet Sematary' located nearby. After the tragedy of their cat being killed by a truck, Louis resorts to burying it in the mysterious pet cemetery, which is definitely not as it seems, as it proves to the Creeds that sometimes, dead is better. [D: Kevin Kölsch, Dennis Widmyer; A: John Lithgow, Jason Clarke, Amy Seimetz]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt4633694/"&gt;Spider-Man: Into the Spider-Verse&lt;/a&gt;: (2018; Animation, Action, Adventure, Family, Sci-Fi) Teen Miles Morales becomes Spider-Man of his reality, crossing his path with five counterparts from other dimensions to stop a threat for all realities.::Chockys [D: Bob Persichetti, Peter Ramsey, Rodney Rothman; A: Shameik Moore, Jake Johnson, Hailee Steinfeld]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt1302006/"&gt;The Irishman&lt;/a&gt;: (2019; Biography, Crime, Drama, History, Thriller) A mob hitman recalls his possible involvement with the slaying of Jimmy Hoffa. [D: Martin Scorsese; A: Anna Paquin, Robert De Niro, Al Pacino]&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.imdb.com/title/tt7398584/"&gt;Get Her... If You Can&lt;/a&gt;: (2019; Comedy) Roberto (Javier Rey) and Daniela (Amaia Salamanca) are siblings, both wealthy business people, with very different styles. Roberto's plot to return her sister her sense of humour gets unexpectedly out of hand. [D: Inés de León; A: Amaia Salamanca, Hugo Silva, Javier Rey]&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finalmente, el conteo de pendientes por fecha:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
(Jun-2013)    2
(Sep-2013)    8
(Dic-2013)   12   4
(Abr-2014)    8   3
(Jul-2014)   10  10   5   1
(Nov-2014)   22  22  22   7
(Feb-2015)   13  13  13  10
(Jun-2015)   16  16  15  13  11   1
(Dic-2015)       21  19  19  18   6   1
(May-2016)           26  25  23  21   9
(Sep-2016)               19  19  18  14   1
(Feb-2017)                   26  25  23  21   9   1
(Jun-2017)                       23  23  21  18   5
(Dic-2017)                           19  19  18  16
(May-2018)                               22  22  22
(Sep-2018)                                   12  12
(Mar-2019)                                       13
Total:       91  89 100  94  97  94  89  84  79  69
&lt;/pre&gt;&lt;/div&gt;</description><guid>http://planeta.python.org.ar/posts/15a32071a42cbfc6cba819cdafe6e7be.html</guid><pubDate>Fri, 15 Mar 2019 01:45:00 GMT</pubDate></item></channel></rss>