<?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>Forem: Renato Alencar</title>
    <description>The latest articles on Forem by Renato Alencar (@renatoalencar).</description>
    <link>https://forem.com/renatoalencar</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%2F1189397%2Fac88c674-6c0a-4b1b-9c90-4ae92e25e943.jpg</url>
      <title>Forem: Renato Alencar</title>
      <link>https://forem.com/renatoalencar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/renatoalencar"/>
    <language>en</language>
    <item>
      <title>Introdução ao Clojure Component</title>
      <dc:creator>Renato Alencar</dc:creator>
      <pubDate>Mon, 27 Nov 2023 23:16:20 +0000</pubDate>
      <link>https://forem.com/renatoalencar/introducao-ao-clojure-component-1375</link>
      <guid>https://forem.com/renatoalencar/introducao-ao-clojure-component-1375</guid>
      <description>&lt;p&gt;Se você chegou até aqui já deve saber que Clojure é uma linguagem de programação funcional baseada em Lisp que tem ganhado popularidade no Brasil nos últimos anos, principalmente por causa da Nubank. Na minha experiencia pessoal, Clojure tem sido uma linguagem com uma entrada um pouco difícil, algumas coisas são complicadas de inicio, mas você ganha tração bem fácil à medida que você vai tentando se aprofundar.&lt;/p&gt;

&lt;p&gt;Algo que eu tenho notado é a falta de material mais profundo sobre Clojure em português, o que torna difícil para brasileiros em geral se aprofundarem no aprendizado da linguagem e na capacidade de gerar discussões em torno da linguagem e dos padrões que a comunidade cria em volta dela. Parte talvez do sucesso que o JavaScript, em especial no Brasil, tenha sido talvez devido a quantidade crescente de usuários e comunidades em português que surgem. Por isso decidi escrever esse artigo, e talvez outros, sobre como tem sido aprender Clojure, como um hobby nas horas vagas. Em especial, nesse artigo sobre a lib Component do Stuart Sierra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que usar Componentes?
&lt;/h2&gt;

&lt;p&gt;Stuart Sierra costumava trabalhar na Cognitect como consultor e desenvolvedor, e analisando os problemas na forma como comumente desenvolvedores estruturavam o estado de suas aplicações, em especial coisas que tem características de singleton, como um pool de conexão com bancos de dados, caching ou partes separadas de uma aplicação, criou um pequeno framework baseado na ideia de injeção de dependência e gerenciamento de estado da orientação a objetos: O Component.&lt;/p&gt;

&lt;p&gt;A questão é que temos o hábito de tentar encaixar tudo no modelo MVC, e tentar ver qualquer aplicação como uma extensão disso, tendo um &lt;strong&gt;banco de dados&lt;/strong&gt;, &lt;strong&gt;visualização&lt;/strong&gt; e seja lá o que você considere como &lt;strong&gt;lógica/modelo de negocio&lt;/strong&gt;, sendo que na realidade as coisas estão mais para um &lt;em&gt;spaghetti&lt;/em&gt; em formato de integrações com cache, serviços de terceiros, filas de jobs, etc. Então Stuart Sierra, definiu baseado nisso um framework que poderia criar uma abstração generalizada para lidar com esse problema, onde a ideia é:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Criar componentes que guardem a responsabilidade de manter uma parte do estado da aplicação;&lt;/li&gt;
&lt;li&gt;Definir um limite claro entre esses componentes;&lt;/li&gt;
&lt;li&gt;Definir como lidar com o ciclo de vida desses componentes, cada componente tem que saber como inicializar a si próprio e e como parar;&lt;/li&gt;
&lt;li&gt;Definir as dependências entre componentes de forma explícita e que respeite os limites entre os componentes e as partes da aplicação.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mas como que faz isso? Ajuda aí, cara!
&lt;/h2&gt;

&lt;p&gt;Tudo isso começou semana passada, comigo tentando fazer alguns experimentos com Clojure, montar um web service simples que integrasse com banco de dados e me permitisse fazer algumas operações. Você precisar conectar com o banco e manter a mesma conexão (ou um pool) para usos posteriores, afinal você não vai criar uma nova conexão com o banco toda vez que precisar responder a uma requisição. A forma mais simples de fazer isso pode ser usando um &lt;em&gt;atom&lt;/em&gt; mesmo:&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;example-atom&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;: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;run-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;monger.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;mg&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;monger.collection&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;mc&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;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&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;connect-db!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uri&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;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;db&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;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="w"&gt;
                               &lt;/span&gt;&lt;span class="n"&gt;mg/connect-via-uri&lt;/span&gt;&lt;span class="w"&gt;
                               &lt;/span&gt;&lt;span class="no"&gt;:db&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;list-users!&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;mc/find-maps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:users&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;:body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clojure.string/join&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list-users!&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="nf"&gt;connect-db!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;System/getenv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"DATABASE_URL"&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;run-jetty&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="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="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;Simples, né? Parece até fácil demais para ser verdade. O problema é que quando isso cresce muito, a tendência é que vai ser bem complicado saber que tem acesso à essa conexão, devido ao fato de que essa dependência é implícita, além disso o acesso é a uma variável global e mutável. O outro problema comum é a necessidade de se adicionar cada vez mais dependências externas, que podem ser acessadas por um estado global na aplicação. Stuart Sierra explica isso com detalhes e com bons exemplos em &lt;a href="https://www.youtube.com/watch?v=1siSPGUu9JQ"&gt;&lt;em&gt;Clojure in the Large&lt;/em&gt;&lt;/a&gt;, onde ele conta a experiencia dele lidando com esse tipo de problema em aplicações de larga escala.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolando o banco de dados
&lt;/h2&gt;

&lt;p&gt;Como o problema inicial nesse exemplo é o banco, vamos começar por ele, esse na verdade é o exemplo clássico incluso no próprio README do projeto Component. Aqui, tudo se baseia em três coisas: o conexão com o banco tem um ciclo de vida, eu devo poder acessar ela na aplicação para poder consultar e inserir objetos e eu devo conseguir gerenciar isso como um estado da aplicação. Para começar vamos definir o que seria exatamente um componente banco de dados, o que devemos manter como estado e como gerenciar o ciclo de vida:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um banco de dados pode ser caracterizado aqui como a URL de conexão, a conexão em si e o objeto banco de dados onde a biblioteca faz as consultas;&lt;/li&gt;
&lt;li&gt;Eu preciso me conectar ao banco quando a aplicação e iniciar e guardar o banco em si e a conexão para ser fechada depois;&lt;/li&gt;
&lt;li&gt;Eu preciso fechar a conexão quando a aplicação parar ou pelo menos permitir faze-lo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em Clojure podemos definir os dados com um Record, que é um tipo de dados que tem a implementação de &lt;em&gt;map&lt;/em&gt; e que são utilizados como tipo para guardar dados em formato de &lt;em&gt;chave-valor&lt;/em&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;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connection&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;create-database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uri&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;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&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;mg/connect-via-uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uri&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;map-&amp;gt;Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="no"&gt;:database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="no"&gt;:connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&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;Agora que sabemos como encapsular nosso banco de dados, precisamos encapsular o próprio ciclo de vida dele. O Component usa o conceito de Protocolos do Clojure para resolver isso, inclusive protocolo é um conceito tao poderoso por si só que daria um artigo inteiro. O protocolo em questão é o &lt;em&gt;Lifecycle&lt;/em&gt;. Usando um protocolo em comum, o framework sabe como iniciar e como parar qualquer componente, assim você só tem que se preocupar com a implementação. Além de definir o componente em si, é interessante definir uma função (pura) que crie o componente, um &lt;em&gt;constructor&lt;/em&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;;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; Todo o ciclo de vida do banco de dados&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; fica encapsulado em um componente.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&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;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;component/Lifecycle&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;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;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;db&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;mg/connect-via-uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uri&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;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="no"&gt;::connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&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;stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;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="nb"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;::connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mg/disconnect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; O construtor tem que ser uma funcao pura&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&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;new-database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uri&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;map-&amp;gt;Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uri&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;h2&gt;
  
  
  Mas e o web server?
&lt;/h2&gt;

&lt;p&gt;Bem, nesse momento, você talvez já teve algum tipo de epifania e pensado: "Mas o servidor web também se encaixa nesse padrão". Sim, e vamos encapsular ele também:&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;;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; O web server pode seguir o mesmo protocolo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; e principios que o banco de dados.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&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;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;WebServer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="w"&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="n"&gt;component/Lifecycle&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;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="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="no"&gt;::jetty&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;run-jetty&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;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:handler&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;:port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&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;stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;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="nb"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;::jetty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.close&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;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;new-web-server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;port&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;component/using&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map-&amp;gt;WebServer&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="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;;; Declaramos explicitamente a dependencia&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;;; de um componente `: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;:app&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;Aqui nós adicionamos algo novo: a função &lt;em&gt;component/using&lt;/em&gt;. Ela é responsável poder deixar explicito que um componente depende de outro, nesse caso o &lt;em&gt;app&lt;/em&gt;, que possui uma chave &lt;em&gt;handler&lt;/em&gt;. Nesse caso o handler deve ser uma função que é responsável por responder a requisições.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como que junta isso tudo?
&lt;/h2&gt;

&lt;p&gt;Agora vamos precisar de um componente &lt;em&gt;App&lt;/em&gt;, que deve depender do banco para fazer as consultas necessárias, usando esse componente vamos passar o banco de dados pelo &lt;em&gt;map&lt;/em&gt; da requisição para ser usado internamente pelo handler.&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;;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; Associa um valor `value` a um chave `key` no&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; primeiro argumento da funcao `f`.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; Espera-se que `f` seja um handler que possa&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; ser usado com o Ring.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&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;wrap-assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&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;fn&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="nf"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&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;defrecord&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="n"&gt;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;component/Lifecycle&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;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;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;database&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;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:database&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;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&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;wrap-assoc&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="no"&gt;:database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;database&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;new-app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;handler&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;component/using&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map-&amp;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;:handler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handler&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;:database&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;list-users-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;:body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clojure.string/join&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"\n"&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;request&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="no"&gt;:database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;;; Aqui nós acessamos a chave `:database`&lt;/span&gt;&lt;span class="w"&gt;
                         &lt;/span&gt;&lt;span class="c1"&gt;;; que foi associada pelo componente `App`.&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mc/find-maps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:users&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;h2&gt;
  
  
  Como eu inicio a aplicação agora?
&lt;/h2&gt;

&lt;p&gt;Com tudo definido, só precisamos juntar tudo em um &lt;em&gt;map&lt;/em&gt;, usando a função &lt;em&gt;component/system-map&lt;/em&gt;. Aqui você pode criar uma função pura que é responsável por criar o sistema em si. E então chamar &lt;em&gt;component/start&lt;/em&gt; nesse &lt;em&gt;map&lt;/em&gt;, dentro da função &lt;em&gt;-main&lt;/em&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;;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; Apesar de podermos fazer isso diretamente no `-main`, aqui&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; podemos separar a responsabilidade de interpretar as&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; opcoes e passar para os respectivos constructores dos&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; componentes.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&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;system&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;options&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;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;database-url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;options&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;component/system-map&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;:database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;new-database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;database-url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;:app&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;new-app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;list-users-handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;:server&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;new-web-server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&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="nf"&gt;component/start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:database-url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;System/getenv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&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="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Considerações finais
&lt;/h2&gt;

&lt;p&gt;Você pode estar se perguntando por que eu não usei &lt;em&gt;Compojure&lt;/em&gt; ou por que eu usei MongoDB como exemplo. Bem, a intenção desse exemplo é de ser focado no &lt;em&gt;Component&lt;/em&gt;, e ao mesmo tempo como ele pode ser usado em conjunto com outras ferramentas. Eu tentei evitar ao máximo adicionar a necessidade de conhecimento sobre outras ferramentas para facilitar o entendimento do exemplo.&lt;/p&gt;

&lt;p&gt;O código com as configurações todas no ponto de rodar tá no GitHub em &lt;a href="https://github.com/renatoalencar/component-example"&gt;https://github.com/renatoalencar/component-example&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/stuartsierra/component"&gt;https://github.com/stuartsierra/component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Clojure in the Large: &lt;a href="https://www.youtube.com/watch?v=1siSPGUu9JQ"&gt;https://www.youtube.com/watch?v=1siSPGUu9JQ&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Components Just Enough Structure: &lt;a href="https://www.youtube.com/watch?v=13cmHf_kt-Q"&gt;https://www.youtube.com/watch?v=13cmHf_kt-Q&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clojure</category>
      <category>architecture</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Should You Learn OCaml?</title>
      <dc:creator>Renato Alencar</dc:creator>
      <pubDate>Wed, 08 Nov 2023 20:56:50 +0000</pubDate>
      <link>https://forem.com/renatoalencar/why-should-you-learn-ocaml-1pll</link>
      <guid>https://forem.com/renatoalencar/why-should-you-learn-ocaml-1pll</guid>
      <description>&lt;p&gt;When I decided to learn OCaml, one of the first talks I watched was Yaron Minsky's 'Why OCaml?'. Where he presents some of the reasons why Jane Street have choose OCaml as the language they would use to build almost everything within the company. What is interesting, is that OCaml was the language I've choose for very specific and well though reasons that kept being true with time and experience with the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functional programming
&lt;/h2&gt;

&lt;p&gt;A few years ago I've been focusing a lot on functional programming, which I believe to be the best way of writing software and its counterparts. Although one can use functional programming elements in languages like Python and Ruby, the idioms are still designed towards a more Object Oriented approach, which makes such idioms a lot of times almost impossible to understand, mostly when used in conjunction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python and Clojure
&lt;/h2&gt;

&lt;p&gt;Python was the first language I could say I mastered in depth, back in 2012, since then I have a certain love for simplicity, and a lot of that simplicity comes from its influences from Lisp.&lt;/p&gt;

&lt;p&gt;Clojure being functional and with its syntax inherited from Lisp, easily caught my attention, I spent a lot of time focused on the idioms of the language. But essentially, there was something missing, like a good type system (types and Clojure are a very deep rabbit hole) and the dependency on the JVM (what's actually good on the domains Clojure is mostly present as a language). Moreover, the tooling it's reasonably complicated, there's a lack of documentation and the community tends to be very consulting and enterprise focused.&lt;/p&gt;

&lt;h2&gt;
  
  
  Haskell
&lt;/h2&gt;

&lt;p&gt;I tried Haskell, but although it's an interesting language, there's a few things to consider. The whole tooling tends to be heavyweight, for example the Docker image has 700 MB (it was more than 1 GB when I first tried). Moreover, there's a certain overhead on doing more practical things, something that is easier in Clojure for instance with state, using just an &lt;code&gt;atom&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enters OCaml
&lt;/h2&gt;

&lt;p&gt;OCaml makes things a little bit different, the syntax closer to ML with the possibility to run side effects without much complexity helps who's learning, also making experimentation and a more progressive design easier.&lt;/p&gt;

&lt;p&gt;It isn't necessary to understand the &lt;code&gt;IO&lt;/code&gt; monad to make a simple Hello World, but it is possible to run everything behind a monad if that's the interest of the programmer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;putStrLn&lt;/span&gt; &lt;span class="s"&gt;"Hello world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print_endline&lt;/span&gt; &lt;span class="s2"&gt;"Hello world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;print_endline&lt;/code&gt; is a direct call, there's no extra abstractions and little to no overhead to understand a single line of code.&lt;/p&gt;

&lt;p&gt;If I have the OCaml tooling locally installed, I can even compile a &lt;code&gt;.ml&lt;/code&gt; file with a simple &lt;code&gt;ocamlc&lt;/code&gt; call without the need of creating a project from scratch just to make little experiments like in Clojure. Babashka solves this problem, but adds an extra burden to newcomers.&lt;/p&gt;

&lt;h2&gt;
  
  
  (Good) Types
&lt;/h2&gt;

&lt;p&gt;I lot of people don't like types, and I particularly think that TypeScript creates some hardships if you're just trying to build something very simple, besides having a type system I particularly think it's not very pleasant, structural subtyping creates some error messages that are very hard to read and understand.&lt;/p&gt;

&lt;p&gt;Moreover, there's another problem: having to always declare types if you want to compiler to verify what you want.&lt;/p&gt;

&lt;p&gt;In Python for instance, the following function has to use &lt;code&gt;Any&lt;/code&gt; for &lt;code&gt;n&lt;/code&gt; and for the return type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&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;span class="c1"&gt;# def fib(n: Any) -&amp;gt; Any
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the following OCaml code has its types inferred with no further problems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&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;span class="c"&gt;(* val fib : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Errors become obvious
&lt;/h2&gt;

&lt;p&gt;Functional languages in general have this property of letting that code that probably shouldn't be done that way it was more obvious. With a good type system that becomes even more obvious.&lt;/p&gt;

&lt;p&gt;For example, serializers should be pure functions, and shouldn't make queries to the database. For obvious performance and maintenance reasons, also rarely would someone expect that a serializer would be making a database query.&lt;/p&gt;

&lt;p&gt;In OCaml, for production systems, we usually use Lwt, which is basically a promise system for asynchronous IO and concurrency. But the &lt;code&gt;Lwt.t&lt;/code&gt; type is a monad, and monads have this property of "infecting" everything it touches. Let's suppose you serializer follows the following signature, where it converts a given type &lt;code&gt;t&lt;/code&gt; into a  string to be sent to another service (probably JSON).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;serialize&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to convert some information to a string, this is the signature your serializer should have. However, if you need to make a database query inside the &lt;code&gt;serializer&lt;/code&gt;, for whatever reason, the function is forced to have another signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;serialize&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nn"&gt;Lwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which makes obvious that &lt;code&gt;serialize&lt;/code&gt; is doing something that it shouldn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Another important factor is performance. OCaml has very predictable performance, if you come to explore a little on how the compiler works, and how your code ends up in the final Assembly on a given architecture. You'll end up realizing that you are able to predict beforehand with a certain ease how your code it's actually executed.&lt;/p&gt;

&lt;p&gt;The OCaml compiler is very well known for emitting very efficient code, which is very good for a language that offers the level of abstraction OCaml does.&lt;/p&gt;

&lt;p&gt;Fibonacci is classical example, look how efficient is the final emitted code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;b&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OCaml uses the least significant bit to differentiate between integers and pointers and make unboxed integer operations. So the code is little different than the expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;camlExample__fib_268:
        subq    $8, %rsp
.L101:
        cmpq    (%r14), %r15
        jbe     .L102
.L103:
        cmpq    $5, %rax
        jge     .L100
        movq    %rdi, %rax
        addq    $8, %rsp
        ret
.L100:
        leaq    -1(%rbx,%rdi), %rsi
        addq    $-2, %rax
        movq    %rdi, %rbx
        movq    %rsi, %rdi
        jmp     .L101
.L102:
        call    caml_call_gc@PLT
.L104:
        jmp     .L103
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obverse a few details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the operation is done directly in the registers.&lt;/li&gt;
&lt;li&gt;Recursions are converted into a loop in a efficient manner.&lt;/li&gt;
&lt;li&gt;Registers are used are the same as the ones from the calling convention, System V in this case.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ecosystem
&lt;/h2&gt;

&lt;p&gt;The ecosystem is very accessible if know English, the community &lt;a href="//discuss.ocaml.org/"&gt;Discourse&lt;/a&gt; instance is quite crowded and the people involved in the libraries and the language almost always answer people on the forum. Which is very cool, since you have a direct perspective from the people that work on that instead of only a direct user of the language of library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to begin?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I recommended &lt;a href="https://github.com/Camilotk/ocaml4noobs"&gt;ocaml4noobs&lt;/a&gt; in the Portuguese version of this article, but for English the &lt;a href="https://ocaml.org/docs/installing-ocaml"&gt;Get Started&lt;/a&gt; docs are great!&lt;/li&gt;
&lt;li&gt;Real World OCaml is a little more advanced and for more practical uses: &lt;a href="https://realworldocaml.org/"&gt;https://realworldocaml.org/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;OCaml Programming: Correct + Efficient + Beautiful with theoretical and more computer science focused content: &lt;a href="https://cs3110.github.io/textbook/cover.html"&gt;https://cs3110.github.io/textbook/cover.html&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>career</category>
      <category>ocaml</category>
    </item>
    <item>
      <title>Por que aprender OCaml?</title>
      <dc:creator>Renato Alencar</dc:creator>
      <pubDate>Thu, 02 Nov 2023 14:00:23 +0000</pubDate>
      <link>https://forem.com/renatoalencar/por-que-aprender-ocaml-38dc</link>
      <guid>https://forem.com/renatoalencar/por-que-aprender-ocaml-38dc</guid>
      <description>&lt;p&gt;Quando eu decidi aprender OCaml, uma das primeiras palestras que assisti foi a &lt;a href="https://youtu.be/v1CmGbOGb2I?si=aI4ji7qH59V8E8a9"&gt;&lt;strong&gt;Por que OCaml?&lt;/strong&gt; do Yaron Minsky&lt;/a&gt;. Onde ele apresenta algumas das razões pelas quais a Jane Street escolheu OCaml como a linguagem que iriam usar para construir quase tudo dentro da empresa. O que é interessante, é que OCaml foi uma linguagem que escolhi por motivos bem específicos e pensados que se mantiveram verdade com o tempo e experiência com a linguagem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programação funcional
&lt;/h2&gt;

&lt;p&gt;Há alguns anos que tenho focado bastante em programação funcional, que acredito ser uma melhor forma de escrever software que suas contrapartes. Apesar de se poder usar elementos de programação funcional em linguagens como Python e Ruby, os idiomas dessas linguagens ainda são voltados para um modelo mais baseado em Orientação a Objetos, o que torna os idiomas funcionais muitas vezes quase impossíveis de entender.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python e Clojure
&lt;/h2&gt;

&lt;p&gt;Python foi a primeira linguagem que dominei com maior profundidade, lá em 2012, desde então tenho um certo amor pela simplicidade. Muita dessa simplicidade vem das influencias de Lisp que a linguagem possui.&lt;/p&gt;

&lt;p&gt;Clojure já sendo funcional e com uma sintaxe próxima do Lisp, me chamou atenção facilmente, passei bastante tempo focado aprendendo os idiomas da linguagem. Mas essencialmente faltavam algumas coisas, como um bom sistema de tipos (tipos e Clojure é uma toca do coelho bem funda) e a dependencia na JVM (o que é bom no tipo de domínio onde Clojure é presente como linguagem). Além disso, o tooling é razoavelmente complicado, falta documentação em algumas coisas e a comunidade tende a ser muito focada em enterprise ou consultoria.&lt;/p&gt;

&lt;h2&gt;
  
  
  Haskell
&lt;/h2&gt;

&lt;p&gt;Tentei gostar de Haskell, mas apesar de Haskell ser interessante, algumas coisas pesam bastante. Todo o tooling tende a ser pesado, exemplificando a imagem Docker tem 700 MB (na época passava de 1GB). Além disso, há um certo overhead até conseguir fazer algo mais prático, algo que já é mais fácil em Clojure por exemplo com estado, usando apenas um &lt;code&gt;atom&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entra OCaml
&lt;/h2&gt;

&lt;p&gt;OCaml já faz as coisas de uma forma um pouco diferente, a sintaxe mais próxima do ML com a possibilidade de rodar side-effects sem muita complicação ajuda a quem está tentando aprender, além de facilitar experimentação e um design mais progressivo.&lt;/p&gt;

&lt;p&gt;Não é necessário entender a monad &lt;code&gt;IO&lt;/code&gt; do Haskell para poder fazer um simples Hello World, mas é possível rodar tudo atrás de monads se for do interesse de quem tá programando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;putStrLn&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print_endline&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;print_endline&lt;/code&gt; é uma chamada direta, não há abstrações extras bem pouco overhead para entender essa única linha de código.&lt;/p&gt;

&lt;p&gt;Se eu possuir algum tooling de OCaml instalado localmente, eu ainda consigo compilar um arquivo &lt;code&gt;.ml&lt;/code&gt; com um simples &lt;code&gt;ocamlc&lt;/code&gt; sem precisar criar um projeto inteiro do zero só para fazer pequenos experimentos como em Clojure. O Babashka resolve esse problema, mas adiciona mais um overhead para quem está aprendendo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tipos (bons)
&lt;/h2&gt;

&lt;p&gt;Muita gente não gosta de tipos, Rich Hickey que o diga. E eu particularmente acho que TypeScript cria várias dificuldades se você tá só tentando implementar algo simples, além de ter um sistema de tipos que eu particularmente acho desagradável, subtipagem estrutural cria mensagens de erro péssimas com objetos grandes.&lt;/p&gt;

&lt;p&gt;Além disso, entra outro problema: ter que sempre declarar os tipos se você quiser que o compilador verifique o você quer. Isso graças a necessidade de se juntar tipos abstratos com subtipagem.&lt;/p&gt;

&lt;p&gt;Em Python por exemplo, a seguinte função vai ter que usar &lt;code&gt;Any&lt;/code&gt; para &lt;code&gt;n&lt;/code&gt; e para o valor de retorno:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&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;span class="c1"&gt;# def fib(n: Any) -&amp;gt; Any
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Já o seguinte código em OCaml tem seus tipos inferidos sem problema algum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&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;span class="c"&gt;(* val fib : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Erros ficam óbvios
&lt;/h2&gt;

&lt;p&gt;Linguagens funcionais em geral tem essa propriedade de deixar aquele código que provavelmente não deveria ser feito que você fez mais óbvio. Com um bom sistema de tipos, isso fica ainda mais óbvio.&lt;/p&gt;

&lt;p&gt;Por exemplo, serializers deveriam ser funções puras, e não fazer consultas ao banco. Por questões óbvias de performance, de manutenção, e raramente alguem espera que um serializer esteja fazendo um consulta ao banco.&lt;/p&gt;

&lt;p&gt;Em OCaml, para sistemas em produção, normalmente utilizamos &lt;a href="https://github.com/ocsigen/lwt"&gt;Lwt&lt;/a&gt;, que é basicamente um sistema de promises para IO assíncrono e concorrência. Acontece o tipo &lt;code&gt;Lwt.t&lt;/code&gt; é uma mônada, e mônadas tem essa propriedade interessante de "contaminar" tudo que elas tocam. Vamos supor que seu serializer tenha a seguinte assinatura, você converte um dado do tipo &lt;code&gt;t&lt;/code&gt; para uma string a ser enviada para outro serviço (provavelmente JSON).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;serialize&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se você só precisa converter a informação pra &lt;code&gt;string&lt;/code&gt;, é essa a assinatura que o seu serializer deve ter. Porém, se você precisa fazer uma consulta ao banco dentro de &lt;code&gt;serialize&lt;/code&gt;, por qualquer que seja o motivo, a função é forçada a ter outra assinatura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;serialize&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nn"&gt;Lwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que torna óbvio que &lt;code&gt;serialize&lt;/code&gt; tá fazendo algo que não deveria.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Outro fator importante, é performance. OCaml tem performance bem previsível, se você chegar a explorar um pouco sobre como o próprio compilador funciona, e como seu código final fica em Assembly na arquitetura em uso. Você acaba percebendo com o tempo, que você é capaz de perceber de antemão com uma certa facilidade como que o seu código vai ser executado em máquina.&lt;/p&gt;

&lt;p&gt;O compilador do OCaml já é bem conhecido por emitir código bem eficiente, o que é muito bom pra uma linguagem com o nível de abstração que o OCaml oferece.&lt;/p&gt;

&lt;p&gt;Talvez um exemplo clássico seja Fibonacci, veja como emite código eficiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ocaml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;b&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OCaml usa o bit menos significativo pra diferenciar inteiros de ponteiros e fazer cálculo com inteiros unboxed. O código fica um pouco diferente do que se esperaria, mas ainda assim muito performático:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;camlExample__fib_268:
        subq    $8, %rsp
.L101:
        cmpq    (%r14), %r15
        jbe     .L102
.L103:
        cmpq    $5, %rax
        jge     .L100
        movq    %rdi, %rax
        addq    $8, %rsp
        ret
.L100:
        leaq    -1(%rbx,%rdi), %rsi
        addq    $-2, %rax
        movq    %rdi, %rbx
        movq    %rsi, %rdi
        jmp     .L101
.L102:
        call    caml_call_gc@PLT
.L104:
        jmp     .L103
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observe alguns detalhes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Todo o cálculo é feito diretamente nos registradores;&lt;/li&gt;
&lt;li&gt;A recursão é convertida em um loop de forma eficiente;&lt;/li&gt;
&lt;li&gt;Os registradores usados são os mesmos dos parâmetros da convenção de chamada.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ecossistema
&lt;/h2&gt;

&lt;p&gt;O ecossistema é bem acessível se você souber inglês pelo menos, o &lt;a href="https://discuss.ocaml.org/"&gt;forúm&lt;/a&gt; é bem movimentado e as pessoas envolvidas tanto na linguagem quanto nas bibliotecas quase sempre respondem as pessoas lá mesmo. O que é bem legal, já que você tem a perspectiva diretamente das pessoa que trabalham naquilo ao invés de outro usuário direto da linguagem ou biblioteca.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por onde começar?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ocaml4noobs é muito bom pra quem quer começar em Português: &lt;a href="https://github.com/Camilotk/ocaml4noobs"&gt;https://github.com/Camilotk/ocaml4noobs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Real World OCaml já te dá um conteúdo bem mais avançado com casos de usos mais práticos: &lt;a href="https://realworldocaml.org/"&gt;https://realworldocaml.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;OCaml Programming: Correct + Efficient + Beautiful com conhecimentos teóricos de Ciência da Computação aplicados à linguagem: &lt;a href="https://cs3110.github.io/textbook/cover.html"&gt;https://cs3110.github.io/textbook/cover.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>career</category>
      <category>ocaml</category>
    </item>
  </channel>
</rss>
