<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: muro</title>
    <description>The latest articles on DEV Community by muro (@mrmuro).</description>
    <link>https://dev.to/mrmuro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1325749%2F8baec2b5-c17f-4295-8dc7-076cfc030b82.png</url>
      <title>DEV Community: muro</title>
      <link>https://dev.to/mrmuro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrmuro"/>
    <language>en</language>
    <item>
      <title>Querido Yo del Futuro: Hoy intentaremos configurar una aplicación fullstack en Clojure</title>
      <dc:creator>muro</dc:creator>
      <pubDate>Mon, 09 Sep 2024 06:18:45 +0000</pubDate>
      <link>https://dev.to/mrmuro/querido-yo-del-futuro-hoy-intentaremos-configurar-una-aplicacion-fullstack-en-clojure-153k</link>
      <guid>https://dev.to/mrmuro/querido-yo-del-futuro-hoy-intentaremos-configurar-una-aplicacion-fullstack-en-clojure-153k</guid>
      <description>&lt;p&gt;Hola, querido Yo del Futuro:&lt;br&gt;
Como recordarás (o quizás no, dada nuestra mala memoria), hoy hemos estado sumergiéndonos en el mundo de Clojure y ClojureScript, intentando construir algunas aplicaciones simples. El camino no ha sido fácil; todavía nos cuesta entender cómo hacer ciertas cosas, pero poco a poco hemos ido progresando.&lt;/p&gt;

&lt;p&gt;Pensé que sería bueno dejar unas notas detalladas de cómo hemos ido avanzando. Así, cuando en el futuro nos preguntemos "¿cómo demonios hicimos funcionar esa aplicación en Clojure?", tendremos un registro de cómo nos las ingeniamos para lograrlo.&lt;br&gt;
¡Que lo disfrutes tanto como yo disfruté (y sufrí) creándolo!"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fsv4qnl5njd90qgk767.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fsv4qnl5njd90qgk767.jpg" alt="It's Time!" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creando el esqueleto de la aplicacion
&lt;/h2&gt;

&lt;p&gt;Hemos seguido la guia de &lt;a href="https://shadow-cljs.github.io/" rel="noopener noreferrer"&gt;Shadow CLJS&lt;/a&gt; para crear nuestro proyecto:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx create-cljs-project fullstack&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Como ibamos a usar &lt;a href="https://clojars.org/reagent" rel="noopener noreferrer"&gt;Reagent&lt;/a&gt; en nuestro Frontend, entonces tuvimos que instalar react:&lt;br&gt;
&lt;code&gt;npm install react react-dom create-react-class&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Estructura Inicial del Proyecto
&lt;/h3&gt;

&lt;p&gt;Cuando creamos nuestro proyecto vimos que se crearon una serie de archivos y folders. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fesat4cry3rp82ahzi9bj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fesat4cry3rp82ahzi9bj.png" alt="Directorios y archivos creados por shadow-cljs" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;src/: Directorio principal para el código fuente.&lt;/li&gt;
&lt;li&gt;test/: Directorio para los tests.&lt;/li&gt;
&lt;li&gt;shadow-cljs.edn: Archivo de configuración de Shadow CLJS.&lt;/li&gt;
&lt;li&gt;package.json: Archivo de configuración de npm.&lt;/li&gt;
&lt;li&gt;node_modules/: Directorio de dependencias de Node.js.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Modificación de la estructura.
&lt;/h3&gt;

&lt;p&gt;Todo muy bien hasta aca, pero decidimos modificar un poco la estructura para incluir el backend. Recuerda que no estamos completamente seguros que esta sea la mejor forma de hacerlo. Si cuando leas esto en el futuro conoces una mejor manera, no dudes en usarla!&lt;/p&gt;

&lt;p&gt;Nuestra estructura modificada se ve algo así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b8vtvhr1smq24z0xq2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b8vtvhr1smq24z0xq2f.png" alt="Estructura modificada" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los cambios claves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hemos creado dentro de &lt;code&gt;src/main&lt;/code&gt; directorios separados para &lt;code&gt;backend&lt;/code&gt; y &lt;code&gt;frontend&lt;/code&gt;. Nota que tambien creamos dentro de cada uno de estos directorios &lt;code&gt;core.clj&lt;/code&gt; para el backend y &lt;code&gt;core.cljs&lt;/code&gt; para el frontend.&lt;/li&gt;
&lt;li&gt;Añadimos un archivo &lt;code&gt;deps.edn&lt;/code&gt; para manejar las dependencias de Clojure (backend).&lt;/li&gt;
&lt;li&gt;Mantuvimos &lt;code&gt;shadow-cljs.edn&lt;/code&gt; para las configuraciones de ClojureScript (frontend).&lt;/li&gt;
&lt;li&gt;Removimos el directorio &lt;code&gt;test&lt;/code&gt;. Esto es opcional. &lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Configurando el Frontend en &lt;code&gt;shadow-cljs.edn&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Hemos realizado varios ajustes significativos a nuestro archivo &lt;code&gt;shadow-cljs.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="c1"&gt;;; shadow-cljs configuration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:source-paths&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src/main"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

 &lt;/span&gt;&lt;span class="no"&gt;:dependencies&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;reagent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.2.0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cider/cider-nrepl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.24.0"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:dev-http&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:builds&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:frontend&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:browser&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:output-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"public/js"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:asset-path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"/js"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:modules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:init-fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frontend.core/init&lt;/span&gt;&lt;span class="p"&gt;}}}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En primer lugar, modificamos la ruta de origen a &lt;code&gt;["src/main"]&lt;/code&gt; ya que nuestro codigo fuente estará en este directorio.&lt;/p&gt;

&lt;p&gt;También hemos agregado Reagent como dependencia. Esta librería nos permitirá construir UI reactivas en ClojureScript aprovechando React.&lt;/p&gt;

&lt;p&gt;Como estamos utilizando Vim y Conjure como nuestro IDE, hemos agregado &lt;code&gt;cider/cider-nrepl&lt;/code&gt;, esto mejora la integración con el REPL en Conjure (según la documentación, aun tenemos que ver si es cierto).&lt;/p&gt;

&lt;p&gt;En cuanto al servidor de desarrollo, configuramos &lt;code&gt;:dev-http&lt;/code&gt; para servir desde el directorio "public" en el puerto 8080.&lt;/p&gt;

&lt;p&gt;Por último, definimos un build específico llamado &lt;code&gt;:frontend&lt;/code&gt;. El target es &lt;code&gt;:browser&lt;/code&gt; ya que estamos haciendo el proyecto para la web. El directorio de salida es "public/js" con la ruta de assets en "/js". Como punto final, especificamos el entry point de nuestra aplicación, que será con la función &lt;code&gt;init&lt;/code&gt; en &lt;code&gt;core.cljs&lt;/code&gt;. Para esto decimos que el módulo principal se inicializará con la función &lt;code&gt;frontend.core/init&lt;/code&gt;, la cual aún tenemos pendiente crear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurando el Backend en &lt;code&gt;deps.edn&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Ahora toca configurar el backend, recuerdas que habíamos creado &lt;code&gt;deps.edn&lt;/code&gt;? Bueno, ahora es momento de usarlo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src/main"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; 
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;org.clojure/clojure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.11.1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;ring/ring-core&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.9.6"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;ring/ring-jetty-adapter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.9.6"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:run-server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:main-opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-m"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"backend.core"&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al igual que hicimos en el frontend, comenzaremos con definir la ruta de origen de nuestro código, que en nuestro caso también es &lt;code&gt;["src/main"]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;En cuanto a dependencias necesitamos &lt;code&gt;org.clojure/clojure&lt;/code&gt; y para el servidor web hemos elegido Ring. Específicamente estamos utilizando &lt;code&gt;ring/ring-core&lt;/code&gt; y &lt;code&gt;ring/ring-jetty-adapter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hemos también creado un alias llamado &lt;code&gt;:run-server&lt;/code&gt; que está configurado para ejecutar la función &lt;code&gt;main&lt;/code&gt; en el namespace &lt;code&gt;backend.core&lt;/code&gt; cuando se invoque.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vamos a probar si todo funciona bien
&lt;/h2&gt;

&lt;p&gt;Primero vamos por el backend. En &lt;code&gt;src\main\backend\&lt;/code&gt; hemos creado &lt;code&gt;core.clj&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;backend.core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ring.adapter.jetty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jetty&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ring.middleware.params&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hola desde el backend de Clojure."&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="w"&gt; 
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;params/wrap-params&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Iniciando el servidor en http://localhost:3000"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;jetty/run-jetty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:join?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí, luego de importar las dependencias de Ring, creamos una función &lt;code&gt;handler&lt;/code&gt; que por ahora simplemente responde con un mensaje de texto.&lt;br&gt;
También hemos definido nuestra &lt;code&gt;app&lt;/code&gt; que usa &lt;code&gt;wrap-params&lt;/code&gt; para manejar parámetros de la solicitud. &lt;br&gt;
Finalmente tenemos nuestra función de entrada &lt;code&gt;-main&lt;/code&gt; que inicia el servidor en el puerto 3000.&lt;/p&gt;

&lt;p&gt;Para probar el backend simplemente abremos un terminal en el root de nuestro proyecto:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
clj -M:run-server&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Si vamos a &lt;code&gt;http://localhost:3000/&lt;/code&gt; deberiamos ver el mensaje "Hola desde el backend de Clojure."&lt;/p&gt;

&lt;p&gt;Ahora probemos si el frontend functiona correctamente. Vamos a crear en &lt;code&gt;src/main/frontend/&lt;/code&gt; el archivo &lt;code&gt;core.cljs&lt;/code&gt; con el siguiente contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frontend.core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;goog.dom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gdom&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;reagent.core&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reagent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:refer&lt;/span&gt;&lt;span class="w"&gt; &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="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;reagent.dom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rdom&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:div&lt;/span&gt;&lt;span class="w"&gt; 
   &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:h1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Welcome to my Clojurescript App"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"This is a basic Reagent component"&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mount-app-element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rdom/render&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gdom/getElement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mount-app-element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="no"&gt;:after-load&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on-reload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mount-app-element&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí, primero importamos las dependencias necesarias como &lt;code&gt;goog.dom&lt;/code&gt; para manipular el DOM y los componentes core y dom de Reagent.&lt;br&gt;
Tambien hemos definido la función &lt;code&gt;app&lt;/code&gt; que es nuestro componente principal de Reagent. Por ahora es un simple HTML con un título y un párrafo.&lt;br&gt;
Luego tenemos &lt;code&gt;mount-app-element&lt;/code&gt; que es la función que renderizará nuestro componente &lt;code&gt;app&lt;/code&gt; en el elemento del DOM con id &lt;code&gt;app&lt;/code&gt;. &lt;br&gt;
Finalmente creamos una función &lt;code&gt;on-reload&lt;/code&gt; que está diseñada para trabajar con hot reloading así no tenemos que recargar la página para que se actualize el navegador.&lt;/p&gt;

&lt;p&gt;Para arrancar el frontend abrimos un nuevo terminal, vamos al root del proyecto y ejecutamos: &lt;br&gt;
&lt;code&gt;&lt;br&gt;
shadow-cljs watch frontend&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Si todo sale bien deberiamos ver una página que dice "Welcome to my ClojureScript App" en &lt;code&gt;localhost:8080&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hasta aquí tenemos todo funcionando bien. Aún tenemos que  configurar las bases de datos y mucho más, nos queda mucho que aprender. Espero que para cuando leas esto ya tengamos una mejor idea de como hacerlo.&lt;/p&gt;

&lt;p&gt;Saludos cordiales,&lt;br&gt;
Tu Yo del Pasado.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>fullstack</category>
      <category>web</category>
      <category>clojurescript</category>
    </item>
    <item>
      <title>"YYYY-MM-DD" to Time in Common Lisp</title>
      <dc:creator>muro</dc:creator>
      <pubDate>Mon, 04 Mar 2024 18:56:36 +0000</pubDate>
      <link>https://dev.to/mrmuro/yyyy-mm-dd-to-time-in-common-lisp-2e0f</link>
      <guid>https://dev.to/mrmuro/yyyy-mm-dd-to-time-in-common-lisp-2e0f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: &lt;br&gt;
&lt;em&gt;The purpose of this post is to track my journey into Common Lisp. Though there might exist more optimal ways, this represents my personal path.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;While querying an API, I encountered dates formatted as strings in the "YYYY-MM-DD" format (for instance, "2023-01-21"), prompting me to seek a method to transform these into a format conducive to date comparisons.&lt;/p&gt;

&lt;p&gt;Let's break it down step by step to get to the final solution, shall we? &lt;/p&gt;

&lt;p&gt;First up, we're going to tackle that date string by splitting it into its parts: the year (yup, the 'YYYY' bit), the month (the 'MM' bit), and the day (you guessed it, the 'DD' part).&lt;/p&gt;

&lt;p&gt;So, we've got our example date string: '2023-01-21'. Now, let's snag the 'YYYY' part. According to the &lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/f_subseq.htm#subseq" rel="noopener noreferrer"&gt;Common Lisp Hyperspec (CLHS)&lt;/a&gt;, there's a handy function that lets us pull out a chunk of a sequence when we tell it where to start and stop. In our scenario, that sequence is our date string. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;From the CLHS:&lt;br&gt;
subseq creates a sequence that is a copy of the subsequence of sequence bounded by start and end.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, we're going to apply subseq to our date string. Since the year part stretches from positions 0 to 4, we just feed those numbers into our function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subseq&lt;/span&gt; &lt;span class="s"&gt;"2023-01-21"&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;;;; returns "2023"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, we're on the right track! &lt;/p&gt;

&lt;p&gt;Now, it's key to note that our result, "2023", comes back as a string. To transform it into an integer, we can use the parse-integer function. This step will convert the string "2023" into an actual numeric value, making it ready for any date comparisons or calculations we might want to perform later on. &lt;br&gt;
Let's now enclose our snippet with &lt;code&gt;parse-integer&lt;/code&gt; to perform the conversion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse-integer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subseq&lt;/span&gt; &lt;span class="s"&gt;"2023-01-21"&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;;;; returns 2023 (now it's an integer)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our strategy in place, we're ready to define a function named parse-date. This function will extract and return three pieces of information from our date string: the year, the month, and the day:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;parse-date&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;date-string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s"&gt;"Extracts year, month, and day from a date string formatted as YYYY-MM-DD."&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;year&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse-integer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subseq&lt;/span&gt; &lt;span class="nv"&gt;date-string&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;month&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse-integer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subseq&lt;/span&gt; &lt;span class="nv"&gt;date-string&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;day&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse-integer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subseq&lt;/span&gt; &lt;span class="nv"&gt;date-string&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;values&lt;/span&gt; &lt;span class="nv"&gt;year&lt;/span&gt; &lt;span class="nv"&gt;month&lt;/span&gt; &lt;span class="nv"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's transform the day, month, and year values into a universal time format, enabling us to perform comparisons between different dates.&lt;/p&gt;

&lt;p&gt;Luckily, Common Lisp offers the encode-universal-time function, capable of transforming our values into universal time. As outlined in the &lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/f_encode.htm" rel="noopener noreferrer"&gt;CLHS&lt;/a&gt;, to use this function effectively, we should supply the seconds, minutes, hour, day, month, and year as arguments, precisely in that sequence. &lt;br&gt;
Given that we lack the specifics for seconds, minutes, and hours, we'll substitute zeroes for these values instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="c1"&gt;;;; Let's convert 2023-01-21:&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;encode-universal-time&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;;; returns 3883233600&lt;/span&gt;
&lt;span class="c1"&gt;;;; Let's convert 2023-01-22:&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;encode-universal-time&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;;; returns 3883320000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a function that turns a date string straight into universal time. We're going to use our parse-date function here. Remember, parse-date gives us three things: the year, the month, and the day. We'll grab these three using something called multiple-value-bind, and then use them to get everything set up for the encode-universal-time function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;date-string-to-universal-time&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;date-string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s"&gt;"Converts a date string in the format 'YYYY-MM-DD' to universal time."&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;multiple-value-bind&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;year&lt;/span&gt; &lt;span class="nv"&gt;month&lt;/span&gt; &lt;span class="nv"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parse-date&lt;/span&gt; &lt;span class="nv"&gt;date-string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;encode-universal-time&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;; second&lt;/span&gt;
                           &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;; minute&lt;/span&gt;
                           &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;; hour&lt;/span&gt;
                           &lt;span class="nv"&gt;day&lt;/span&gt;
                           &lt;span class="nv"&gt;month&lt;/span&gt;
                           &lt;span class="nv"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we're equipped to perform date comparisons right from the date string, let's write an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;date-string-to-universal-time&lt;/span&gt; &lt;span class="s"&gt;"2023-01-21"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;date-string-to-universal-time&lt;/span&gt; &lt;span class="s"&gt;"2023-01-22"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;;; returns NIL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;date-string-to-universal-time&lt;/span&gt; &lt;span class="s"&gt;"2023-01-21"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;date-string-to-universal-time&lt;/span&gt; &lt;span class="s"&gt;"2023-01-22"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;;; returns T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you have it. See you next time!&lt;/p&gt;

</description>
      <category>commonlisp</category>
    </item>
  </channel>
</rss>
