<?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: Kelvin Mai</title>
    <description>The latest articles on DEV Community by Kelvin Mai (@kelvinmai).</description>
    <link>https://dev.to/kelvinmai</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%2F380623%2F0744a842-e256-4c0b-853e-5be6dbbf801a.jpeg</url>
      <title>DEV Community: Kelvin Mai</title>
      <link>https://dev.to/kelvinmai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kelvinmai"/>
    <language>en</language>
    <item>
      <title>How To Integrate HoneySQL with PostgreSQL</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Thu, 12 Nov 2020 19:08:16 +0000</pubDate>
      <link>https://dev.to/kelvinmai/how-to-integrate-honeysql-with-postgresql-108l</link>
      <guid>https://dev.to/kelvinmai/how-to-integrate-honeysql-with-postgresql-108l</guid>
      <description>&lt;p&gt;In returning to clojure, there was one library that I wanted to check out and that one is &lt;a href="https://github.com/seancorfield/honeysql"&gt;honeysql&lt;/a&gt;. HoneySQL is a library where you can create a clojure map and use the &lt;code&gt;sql/format&lt;/code&gt; function to turn that map into a raw sql query.&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;require&lt;/span&gt;&lt;span class="w"&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;honeysql.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;sql&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&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;honeysql.helpers&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="no"&gt;:all&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;helpers&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;sqlmap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="no"&gt;:from&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:foo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="no"&gt;:where&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:f.a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"baz"&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;sql/format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sqlmap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;gt; ["SELECT a, b, c FROM foo WHERE f.a = ?" "baz"]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example is one that shows off the capabilities of the library, but below we have the classic "get everything" query for simplicity's sake.&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="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sqlmap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&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;:from&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:bar&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;sql/format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sqlmap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;gt; ["SELECT * FROM bar"]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is one small problem, the library is very useful in creating raw query strings, but I couldn't find an example of actually executing these queries, and that is what I want to accomplish with this post. For this post we'll be using the Clojure CLI rather than lieningen, so I have included the minimum configuration of a deps.edn file below as well as a nrepl alias.&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"&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="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.10.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;org.postgresql/postgresql&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;"42.2.2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;seancorfield/next.jdbc&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.1.613"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;honeysql/honeysql&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.0.444"&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;:nrepl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:extra-deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nrepl/nrepl&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;"0.8.0"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&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="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;"0.25.2"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&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;"nrepl.cmdline"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"--middleware"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"[cider.nrepl/cider-middleware]"&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;Some of these versions may have been updated, so make sure to check &lt;a href="https://clojars.org/"&gt;clojars&lt;/a&gt;, and for this example I will be using postgres as the database of choice if you are instead interested in a different data source, relevant links to the drivers are available on the clojure &lt;a href="https://github.com/clojure/java.jdbc"&gt;jdbc&lt;/a&gt; library readme. Speaking of which, even though we'll be using &lt;a href="https://github.com/seancorfield/next-jdbc"&gt;next.jdbc&lt;/a&gt;, the initial configuration def will be the same as shown below.&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.db&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;next.jdbc&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;jdbc&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;db-config&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:dbtype&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"postgresql"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:dbname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"example_db"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:password&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"postgres"&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;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;jdbc/get-datasource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;db-config&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;I'm unsure what the difference between the original jdbc and &lt;code&gt;next.jdbc&lt;/code&gt; is, but figured it would be a good idea to use the latest and greatest connection library and skip whatever headaches were present that prompted the creation of this new library. Here you can see that connection configuration being used by &lt;code&gt;jdbc/get-datasource&lt;/code&gt; and the persisted connection is held in the &lt;code&gt;db&lt;/code&gt; var. And now all we need to do now is to execute queries which we can do by calling &lt;code&gt;jdbc/execute!&lt;/code&gt;. It's important to note that the first argument is the database connection which we've defined above.&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;jdbc/execute!&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="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"CREATE TABLE thing (
                     id SERIAL,
                     title TEXT,
                     description TEXT)"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;gt; [#:next.jdbc{:update-count 0}]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;jdbc/execute!&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="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"SELECT * FROM thing"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;gt; []&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And lastly instead of writing raw sql, we come full circle and can now use the honeysql library to pass in formatted sql maps. So simply replace the vector of sql queries with some honeysql operations. So if we were to run the following in the repl, we'll get some desired side effects. (The libraries are aliased as above from the &lt;code&gt;require&lt;/code&gt; statements.)&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;jdbc/execute!&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="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sql/format&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&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;:from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:thing&lt;/span&gt;&lt;span class="p"&gt;]}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;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;jdbc/execute!&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="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sql/format&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:insert-into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:thing&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="no"&gt;:columns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:text&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s"&gt;"blog"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"written articles"&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="s"&gt;"article"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"blog post"&lt;/span&gt;&lt;span class="p"&gt;]]}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;gt; [#:next.jdbc{:update-count 2}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;gt; [#:thing{:id 1, :title "blog", :description "written articles"}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;jdbc/execute!&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="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sql/format&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&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;:from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:thing&lt;/span&gt;&lt;span class="p"&gt;]}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; =&amp;gt; [#:thing{:id 2, :title "article", :description "blog post"}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all there is to it, I hope some have found this post useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://clojars.org/"&gt;clojars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/clojure/java.jdbc"&gt;clojure/java.jdbc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seancorfield/next-jdbc"&gt;next.jdbc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seancorfield/honeysql"&gt;honeysql&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clojure</category>
      <category>functional</category>
      <category>sql</category>
      <category>database</category>
    </item>
    <item>
      <title>Build a Port Scanner in Golang</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Tue, 29 Sep 2020 16:01:35 +0000</pubDate>
      <link>https://dev.to/kelvinmai/build-a-port-scanner-in-golang-149i</link>
      <guid>https://dev.to/kelvinmai/build-a-port-scanner-in-golang-149i</guid>
      <description>&lt;p&gt;In this video we create the freeCodeCamp port scanner project but instead of python, this application is written in golang.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KW8jls13YOY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/learn/information-security/information-security-projects/port-scanner"&gt;freeCodeCamp project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kelvin-mai/go-port-scanner"&gt;Source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How To Build a Full Stack Clojure Project</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Mon, 03 Aug 2020 17:44:27 +0000</pubDate>
      <link>https://dev.to/kelvinmai/how-to-build-a-full-stack-clojure-project-2223</link>
      <guid>https://dev.to/kelvinmai/how-to-build-a-full-stack-clojure-project-2223</guid>
      <description>&lt;p&gt;This is a video series that covers building a simple full stack CRUD application with clojure and clojurescript.&lt;/p&gt;

&lt;h1&gt;
  
  
  What you will learn
&lt;/h1&gt;

&lt;p&gt;The main focus here is the language of clojure itself, and the libraries used isn't as important. There is a small assumption that you are already a javascript/react developer and so some technologies have been chosen should be familiar, like the usage of VS Code instead of emacs. This is also the reason why helix was chosen instead of something more popular like reagent, because if you already know modern React, I didn't want that knowledge to be thrown away. If you don't know modern react however, it shouldn't be difficult to follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reitit Ring Set Up
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/R5YZRfABbWY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage dependencies with &lt;a href="https://clojure.org/guides/deps_and_cli"&gt; deps.edn &lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Set up a &lt;a href="https://github.com/ring-clojure/ring"&gt; ring &lt;/a&gt; server with &lt;a href="http://http-kit.github.io/"&gt; http-kit &lt;/a&gt; and &lt;a href="https://cljdoc.org/d/metosin/reitit/0.5.5/doc/introduction"&gt; reitit &lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add middlewares and test routes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Database Configuration
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/2_Pd6QeFqYs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;a href="https://www.hugsql.org/"&gt;hugsql&lt;/a&gt; to connect to a postgresql database&lt;/li&gt;
&lt;li&gt;Write SQL to generate CRUD functions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API endpoints
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dMB-EWpR_Cw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create api routes and endpoints for each of the CRUD operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Front End Preparation
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Jf94HNmCXyU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up &lt;a href="http://shadow-cljs.org/"&gt;shadow-cljs&lt;/a&gt; for front end dev server and dependencies&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://github.com/Lokeh/helix"&gt;Helix&lt;/a&gt; to add React to our front end&lt;/li&gt;
&lt;li&gt;Add &lt;a href="https://tailwindcss.com/"&gt;Taliwind CSS&lt;/a&gt; for styling and theming&lt;/li&gt;
&lt;li&gt;Connect to the backend api we've built&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  React Components
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PDtv-CL0XeI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create react components by using the helix library&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  State Management
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PRDP5ba8lPU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up a redux style state management system using react context&lt;/li&gt;
&lt;li&gt;Introduction to clojure multimethods&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Integration
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/p8d9VtrdZ7Y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrating our state management with api requests&lt;/li&gt;
&lt;li&gt;A little bit of styling with tailwind css&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clojure</category>
      <category>react</category>
      <category>tutorial</category>
      <category>functional</category>
    </item>
    <item>
      <title>Understanding Clojure Multimethods</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Mon, 20 Jul 2020 21:31:47 +0000</pubDate>
      <link>https://dev.to/kelvinmai/understanding-clojure-multimethods-2cd0</link>
      <guid>https://dev.to/kelvinmai/understanding-clojure-multimethods-2cd0</guid>
      <description>&lt;p&gt;It took me quite a while to wrap my head around clojure's multimethods, which is clojure's version of pattern matching and polymorphism. Pattern matching is a pretty core part of how functional programming languages to combat the ambiguaty of &lt;code&gt;null&lt;/code&gt;. The big draw to it in typed languages like scala and ocaml is to exhaust all possibilites, however clojure is a dynamically typed language so there is a different interest here. We're interested in the branching paths, kinda like an expanded if statement, to call a different function depending on the condition. Javascript and other C-like languages can do a pretty good impression of this with the &lt;code&gt;switch&lt;/code&gt; statement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;switchFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;false&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;maybe?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is the clojure equivalent of a switch case, using clojure keywords (used by the ':' syntax) instead of strings as the conditions. And it may not be the best example for boolean cases, as you would opt for a switch when you have more than 2 possibilities. But this is the&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight clojure"&gt;&lt;code&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;switch-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;condition&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;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;:true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;prn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;:false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;prn&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;span class="no"&gt;:default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;prn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"maybe?"&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;But the downside of the case function is that to update the functionality you would have to edit the function altogether. It may not seem like that big of a deal until polymorphism is taken into account. Say for example you want to add an additional case to a third party library, which may be almost impossible. This is an extreme case, but it does illustrate the limitations of a switch case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multimethods
&lt;/h2&gt;

&lt;p&gt;And that's where clojure's multimethods come in. Using the &lt;code&gt;defmulti&lt;/code&gt; and &lt;code&gt;defmethod&lt;/code&gt; macros we can define both the switch and cases separately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defmulti&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;identity&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;defmethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&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;defmethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&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;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&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;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 5040&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is an example of implementing a factorial function with multimethods instead of the more typical recursive alternative. The &lt;code&gt;defmulti&lt;/code&gt; macro's form structure first takes in the name of the multimethod, and subsequently each &lt;code&gt;defmethod&lt;/code&gt;'s first param must be the name of the same as the one in defmulti so that clojure knows which multimethod it belongs to. The second argument of defmulti defines the function on how to determine wich method to use, here it's provided the identity method so whatever number is provided will be the case. In the methods, the second is the cases and uses a &lt;code&gt;:default&lt;/code&gt; as the default case and the last param is the return value. The list param is what confused me, it will match the same input as the defmulti so it will always include the cases, in this factorial example it's not too complex as the number is also the condition. But if you want a React/Redux style action dispatch system it will end up looking like this instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defmulti&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app-reducer&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;state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;action&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;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;action&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;defmethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app-reducer&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="no"&gt;:set-list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;action-type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&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;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state&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;defmethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app-reducer&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="no"&gt;:add-to-list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;action-type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&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;conj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;;; calling the actions here&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;app-reducer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:set-list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&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;app-reducer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:add-to-list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&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;With the redux style reducer you will always have 2 arguments, the state and action, but the action is then divided into it's action type and payload. So to maintain arity (number of arguments) the action here is embedded in a list of it's own, being destructured in each of the &lt;code&gt;defmethod&lt;/code&gt;s. In the &lt;code&gt;defmulti&lt;/code&gt; the function here returns just the action type to determine which condition to use, which is why it returns the first in the action list. But in the methods return value we are only interested in the payload, so we ignore the action type as it has already been used to determine which method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.patreon.com/kelvinmai"&gt;Patreon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clojure</category>
      <category>functional</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Introduction to Clojure Ring</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Fri, 10 Jul 2020 14:43:23 +0000</pubDate>
      <link>https://dev.to/kelvinmai/introduction-to-clojure-ring-2eff</link>
      <guid>https://dev.to/kelvinmai/introduction-to-clojure-ring-2eff</guid>
      <description>&lt;p&gt;This is an introduction to clojure ring. Ring is a low level library that makes it possible to build web servers, it's important to understand the internals of this library as most, if not all other web frameworks in clojure is built on top of Ring.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/3AWXM8CN6FA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Included in video
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Project setup with deps.edn&lt;/li&gt;
&lt;li&gt;VS Code Calva editor integration&lt;/li&gt;
&lt;li&gt;Setting up a ring server&lt;/li&gt;
&lt;li&gt;Explanation of middleware usage with ring&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resource Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ring-clojure/ring"&gt;Ring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.patreon.com/kelvinmai"&gt;Patreon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clojure</category>
      <category>functional</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Set Up Shadow CLJS</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Mon, 06 Jul 2020 14:34:21 +0000</pubDate>
      <link>https://dev.to/kelvinmai/how-to-set-up-shadow-cljs-l98</link>
      <guid>https://dev.to/kelvinmai/how-to-set-up-shadow-cljs-l98</guid>
      <description>&lt;p&gt;This is a simple walkthrough of how to set up a shadow cljs project&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/p61lhOvQg2Q"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Included in video
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Configuring a shadow-cljs edn file&lt;/li&gt;
&lt;li&gt;Adding clojurescript support in the chrome console&lt;/li&gt;
&lt;li&gt;Adding CLJS/JS dependencies and interoping with existing Javascript libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The completed shadow-cljs.edn file will look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight clojure"&gt;&lt;code&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/cljs"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:nrepl&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;9000&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;cider/cider-nrepl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.21.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;binaryage/devtools&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.0.2"&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;lilactown/helix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.0.13"&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;: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;: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;"resources/public/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;app.core/init&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:devtools&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:preloads&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;devtools.preload&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                           &lt;/span&gt;&lt;span class="no"&gt;:http-root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"resources/public"&lt;/span&gt;&lt;span class="w"&gt;
                           &lt;/span&gt;&lt;span class="no"&gt;:http-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;
  
  
  Resource Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://shadow-cljs.org/"&gt;Shadow CLJS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://shadow-cljs.github.io/docs/UsersGuide.html"&gt;Shadow CLJS Docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Lokeh/helix"&gt;Lokeh/helix&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clojure</category>
      <category>functional</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Dinosaur Rest API with Dactyl and denoDB</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Mon, 29 Jun 2020 15:51:28 +0000</pubDate>
      <link>https://dev.to/kelvinmai/a-dinosaur-rest-api-with-dactyl-and-denodb-5e1j</link>
      <guid>https://dev.to/kelvinmai/a-dinosaur-rest-api-with-dactyl-and-denodb-5e1j</guid>
      <description>&lt;p&gt;In this video, I try out deno by creating a simple REST API with database crud operations using the Dactyl web framework as well as the denodb library. Dactyl aims to be the NestJS of deno and built on top of Oak.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/feNNPKHCYFg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Included in video
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Creating a deno project from scratch&lt;/li&gt;
&lt;li&gt;Adding a custom tsconfig for deno&lt;/li&gt;
&lt;li&gt;Dependency management with file architecture&lt;/li&gt;
&lt;li&gt;Connecting to a postgres database with denodb&lt;/li&gt;
&lt;li&gt;Serving api endpoints with dactyl&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resource Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kelvin-mai/deno-dactyl-example"&gt;Source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://deno.land/"&gt;deno&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://deno.land/x/dactyl"&gt;Dactyl Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eveningkid.github.io/denodb-docs/"&gt;denoDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>deno</category>
      <category>nestjs</category>
      <category>node</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create the Frontend Mentor Countries app in Angular</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Mon, 22 Jun 2020 15:30:47 +0000</pubDate>
      <link>https://dev.to/kelvinmai/create-the-frontend-mentor-countries-app-in-angular-2ikc</link>
      <guid>https://dev.to/kelvinmai/create-the-frontend-mentor-countries-app-in-angular-2ikc</guid>
      <description>&lt;p&gt;In this video series, I took the frontend mentor challenge to do the countries REST api application with Angular.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4nMpvb12Uo8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/YkVShyTILpY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hXXwm0QRTEU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4ekenSY6jac"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Included in video
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Setting up an Angular 9 &lt;/li&gt;
&lt;li&gt;Generating components and services with the Angular CLI&lt;/li&gt;
&lt;li&gt;RxJS Observable logic for global theme state&lt;/li&gt;
&lt;li&gt;Lots of SCSS with some special Angular host-context&lt;/li&gt;
&lt;li&gt;Creating a component with 2 way binding&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resource Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kelvin-mai/ng-countries"&gt;Source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.frontendmentor.io/challenges/rest-countries-api-with-color-theme-switcher-5cacc469fec04111f7b848ca"&gt;Frontend Mentor Challenge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow and support me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/kelvinmai"&gt;YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kelvinmai"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Use Docker and Docker Compose for Local Databases</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Mon, 15 Jun 2020 16:30:21 +0000</pubDate>
      <link>https://dev.to/kelvinmai/use-docker-and-docker-compose-for-local-databases-4492</link>
      <guid>https://dev.to/kelvinmai/use-docker-and-docker-compose-for-local-databases-4492</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/IEE6wwZ3_9s"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Just a quick introduction video on how to use docker and docker-compose for developing with local databases like postgres or mongodb&lt;/p&gt;

&lt;h2&gt;
  
  
  Included in Video
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to use the docker cli&lt;/li&gt;
&lt;li&gt;Pull docker images&lt;/li&gt;
&lt;li&gt;Start docker container with image and options&lt;/li&gt;
&lt;li&gt;Executing commands inside docker container&lt;/li&gt;
&lt;li&gt;Writing a docker compose file&lt;/li&gt;
&lt;li&gt;Using docker compose for multiple containers&lt;/li&gt;
&lt;li&gt;Multiple container interactions &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resource Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/docker/compose"&gt;Docker compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to create a Weather App in Reason and React</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Fri, 12 Jun 2020 16:30:31 +0000</pubDate>
      <link>https://dev.to/kelvinmai/how-to-create-a-weather-app-in-reason-and-react-406a</link>
      <guid>https://dev.to/kelvinmai/how-to-create-a-weather-app-in-reason-and-react-406a</guid>
      <description>&lt;p&gt;Topics covered in this video includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reason interop with raw Javascript&lt;/li&gt;
&lt;li&gt;Using native Javascript geolocation api&lt;/li&gt;
&lt;li&gt;Decoding JSON&lt;/li&gt;
&lt;li&gt;Using Reason libraries such as bs-fetch and bs-json&lt;/li&gt;
&lt;li&gt;Fetching data from rest api&lt;/li&gt;
&lt;li&gt;React useState&lt;/li&gt;
&lt;li&gt;Handling React forms in Reason&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Webpack Setup
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0CMmML7Q6Ds"&gt;
&lt;/iframe&gt;
&lt;br&gt;
I felt that the webpack configuration deserved it's own dedicated video.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tutorial
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/H6X6AJZna98"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kelvin-mai/reason-weather"&gt;Source Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openweathermap.org/api"&gt;Weather API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/manifestinteractive/weather-underground-icons"&gt;Weather Icons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>reason</category>
      <category>react</category>
      <category>tutorial</category>
      <category>functional</category>
    </item>
    <item>
      <title>Build a Typing Speed Test with React Context</title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Mon, 08 Jun 2020 16:30:23 +0000</pubDate>
      <link>https://dev.to/kelvinmai/build-a-typing-speed-test-with-react-context-4ekk</link>
      <guid>https://dev.to/kelvinmai/build-a-typing-speed-test-with-react-context-4ekk</guid>
      <description>&lt;p&gt;In this video we create a typing test application that captures the typing speed in the form of WPM using the react context api and hooks to manage it's state.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ntMezAkFPYM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Note: I fail to mention this in the video, but wpm is calculated with the average word being 5 characters.&lt;/p&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Examples Using Recoil State Management </title>
      <dc:creator>Kelvin Mai</dc:creator>
      <pubDate>Tue, 19 May 2020 07:30:22 +0000</pubDate>
      <link>https://dev.to/kelvinmai/recoil-state-management-42oc</link>
      <guid>https://dev.to/kelvinmai/recoil-state-management-42oc</guid>
      <description>&lt;p&gt;Facebook has recently released a brand new state management library for React and I wanted to go over some examples on how to use it.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wN0YpP8Ckpc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>state</category>
      <category>recoil</category>
    </item>
  </channel>
</rss>
