<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>nbeloglazov blog</title>
    <description>Quil, Clojure and programming in general</description>		
    <link>http://nbeloglazov.com</link>
    <atom:link href="http://nbeloglazov.com/feed.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Random Vector Generation</title>
      <description>&lt;p&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/vector-generation.css&quot;&gt;&lt;/p&gt;

&lt;p&gt;In this article, I want to discuss unit vector generation. It was inspired by the recent addition of &lt;a href=&quot;http://quil.info/api/math/random#random-2d&quot;&gt;random-2d&lt;/a&gt; and &lt;a href=&quot;http://quil.info/api/math/random#random-3d&quot;&gt;random-3d&lt;/a&gt; functions in Quil API. The goal is simple: write a function that generates a random unit vector, both in 2D and 3D. This article doesn’t use advanced math (e.g. statistics) and discusses the matter from software engineer point of view who forgot college course about statistics and theory around generating random values.&lt;/p&gt;

&lt;h3&gt;2D vectors&lt;/h3&gt;

&lt;p&gt;Let&amp;#39;s start with the 2D. Here the naive approach that I would try first:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; as random numbers from &lt;code&gt;[-1, 1]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Normalize vector: divide &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; by the vector length to make it a unit vector.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Clojure implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rand-2d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/sqrt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let’s see how well it works in practice. To do that let’s generate 2000 vectors and draw them. When drawing I &amp;quot;cut&amp;quot; beginning of vectors to make image cleaner:&lt;/p&gt;

&lt;div id=&quot;vectors-2d-v1&quot; class=&quot;example-host&quot;&gt;
  &lt;img src=&quot;/images/vector-generation/vectors_2d_v1.png&quot; style=&quot;display: block;&quot;&gt;&lt;/img&gt;
  &lt;canvas style=&quot;display: none;&quot;&gt;&lt;/canvas&gt;
  &lt;button&gt;animate&lt;/button&gt;
&lt;/div&gt;

&lt;p&gt;It&amp;#39;s not obvious, but you can see that there are more vectors in the &amp;quot;corners&amp;quot; at 45°, 135°, 225° and 315° and fewer vectors at 0°, 90°, 180° and 270°. You can start animation to see better. This clustering doesn’t seem good. Good vector generator must generate uniformly distributed vectors.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s try another approach that uses the fact that unit vector is &amp;quot;almost&amp;quot; defined by just one of its coordinate, x or y. Given x we can calculate y as ±√(1 - x²). So let’s try this approach:
1. Generate &lt;code&gt;x&lt;/code&gt; as random number from [-1, 1].
2. Calculate &lt;code&gt;y&lt;/code&gt; as &lt;code&gt;sqrt(1 - x * x)&lt;/code&gt;.
3. Multiply &lt;code&gt;y&lt;/code&gt; by -1 with 0.5 chance otherwise, y will be always positive.&lt;/p&gt;

&lt;p&gt;Clojure implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rand-2d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;sign&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rand-nth&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sign&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/sqrt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;- &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Visualization:&lt;/p&gt;

&lt;div id=&quot;vectors-2d-v2&quot; class=&quot;example-host&quot;&gt;
  &lt;img src=&quot;/images/vector-generation/vectors_2d_v2.png&quot; style=&quot;display: block;&quot;&gt;&lt;/img&gt;
  &lt;canvas style=&quot;display: none;&quot;&gt;&lt;/canvas&gt;
  &lt;button&gt;animate&lt;/button&gt;
&lt;/div&gt;

&lt;p&gt;Turns out it&amp;#39;s even worse than the first approach. At least now we can clearly see that it&amp;#39;s bad.&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s try yet another approach. In the first and second approaches we saw vectors clustered around certain angles. So we need to make angles uniformly distributed. To achieve that instead of generating x and y we’ll randomly choose an angle and calculate x and y based on the angle. In other words we&amp;#39;ll generate a unit vector in polar coordinates instead of cartesian. In cartesian coordinates vector is defined by a pair [x, y] while in polar the pair is [r, ϕ] where r is the vector length and ϕ is the angle:&lt;/p&gt;

&lt;p&gt;&lt;a title=&quot;By No machine-readable author provided. Mets501 assumed (based on copyright claims). [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)], via Wikimedia Commons&quot; href=&quot;https://commons.wikimedia.org/wiki/File%3APolar_to_cartesian.svg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;Polar to cartesian&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Polar_to_cartesian.svg/256px-Polar_to_cartesian.svg.png&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Third (polar) approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set &lt;code&gt;r = 1&lt;/code&gt; (unit vector). Generate ϕ as random number from &lt;code&gt;[0, 2π]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Calculate &lt;code&gt;x = r*cos(ϕ)&lt;/code&gt;, &lt;code&gt;y = r*sin(ϕ)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Clojure implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rand-2d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;phi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Math/PI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/cos&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;phi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/sin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;phi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Visualization:&lt;/p&gt;

&lt;div id=&quot;vectors-2d-v3&quot; class=&quot;example-host&quot;&gt;
  &lt;img src=&quot;/images/vector-generation/vectors_2d_v3.png&quot; style=&quot;display: block;&quot;&gt;&lt;/img&gt;
  &lt;canvas style=&quot;display: none;&quot;&gt;&lt;/canvas&gt;
  &lt;button&gt;animate&lt;/button&gt;
&lt;/div&gt;

&lt;p&gt;Finally it looks good. Comparing with the first approach vectors feel more uniformly distributed.&lt;/p&gt;

&lt;h3&gt;3D vectors&lt;/h3&gt;

&lt;p&gt;Great, we figured out 2D. What about 3D then? The situation is very similar. Let’s try the first (naive) approach;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;z&lt;/code&gt; as random numbers from &lt;code&gt;[-1, 1]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Normalize vector: divide &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; by the vector length to make it unit vector.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Clojure implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rand-3d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/sqrt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Visulization:&lt;/p&gt;

&lt;div id=&quot;vectors-3d-v1&quot; class=&quot;example-host&quot;&gt;
  &lt;img src=&quot;/images/vector-generation/vectors_3d_v1.png&quot; style=&quot;display: block;&quot;&gt;&lt;/img&gt;
  &lt;canvas style=&quot;display: none;&quot;&gt;&lt;/canvas&gt;
  &lt;button&gt;animate&lt;/button&gt;
&lt;/div&gt;

&lt;p&gt;Unfortunately my visualization sucks. I couldn&amp;#39;t come up with a better technique to draw vectors in 3D. Red/green/blue lines are X/Y/Z axis. It&amp;#39;s kinda hard to see if the vectors uniformly distributed or not. Let&amp;#39;s try other approaches. I&amp;#39;ll skip code for the second approach (it&amp;#39;s equivalent to 2D), here is the visualization:&lt;/p&gt;

&lt;div id=&quot;vectors-3d-v2&quot; class=&quot;example-host&quot;&gt;
  &lt;img src=&quot;/images/vector-generation/vectors_3d_v2.png&quot; style=&quot;display: block;&quot;&gt;&lt;/img&gt;
  &lt;canvas style=&quot;display: none;&quot;&gt;&lt;/canvas&gt;
  &lt;button&gt;animate&lt;/button&gt;
&lt;/div&gt;

&lt;p&gt;As for the third approach, in 3D we have to use spherical coordinates. In spherical coordinates vector is defined by three numbers (r, φ, θ):&lt;/p&gt;

&lt;p&gt;&lt;a title=&quot;By Andeggs (Own work) [Public domain], via Wikimedia Commons&quot; href=&quot;https://commons.wikimedia.org/wiki/File%3A3D_Spherical.svg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;3D Spherical&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/3D_Spherical.svg/256px-3D_Spherical.svg.png&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The algorithm is the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set &lt;code&gt;r = 1&lt;/code&gt;. Generate &lt;code&gt;θ&lt;/code&gt; as random number from &lt;code&gt;[-π/2, π/2]&lt;/code&gt;, φ from &lt;code&gt;[0, 2π]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Calculate &lt;code&gt;x = r*cos(θ)*cos(φ)&lt;/code&gt;, &lt;code&gt;y = r*cos(θ)*sin(φ)&lt;/code&gt;, &lt;code&gt;z = r*sin(θ)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Clojure implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rand-3d-v3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;phi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Math/PI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;theta&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;- &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Math/PI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Math/PI&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/cos&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;theta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/cos&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;phi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/cos&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;theta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/sin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;phi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/sin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;theta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Visualization:&lt;/p&gt;

&lt;div id=&quot;vectors-3d-v3&quot; class=&quot;example-host&quot;&gt;
  &lt;img src=&quot;/images/vector-generation/vectors_3d_v3.png&quot; style=&quot;display: block;&quot;&gt;&lt;/img&gt;
  &lt;canvas style=&quot;display: none;&quot;&gt;&lt;/canvas&gt;
  &lt;button&gt;animate&lt;/button&gt;
&lt;/div&gt;

&lt;p&gt;Results surprised me. My mind tells me that the third approach is the best, but my eyes prefer the first approach. The visualization from the first approach feels more uniform, I see fewer clusters. But maybe it&amp;#39;s inefficiencies of my 3D visualization: some vectors are close to the camera and they look bigger and more clustered while the ones which further look smaller. If you have ideas how to fix it - please leave comments. I&amp;#39;m curious how better I can visualize it.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;If you need to generate random vectors think carefully if your approach produces uniformly distributed vectors (if it matters for your application). I like the approach with polar/spherical coordinates because I can &amp;quot;see&amp;quot; it. If you google around you&amp;#39;ll find suggestions to use gaussian distribution but to me it&amp;#39;s harder to understand.&lt;/p&gt;

&lt;p&gt;Also while working on article I found embarrassing things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;random-2d&lt;/code&gt; and &lt;code&gt;random-3d&lt;/code&gt; were supposed to be released in Quil 2.6.0 but they&amp;#39;re not there. Apparently I built the release from earlier commit.&lt;/li&gt;
&lt;li&gt;Quil &lt;code&gt;random-3d&lt;/code&gt; has bug and it produces only vectors with positive z coordinate:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;example-host&quot;&gt;
  &lt;img src=&quot;/images/vector-generation/vectors_bug.png&quot; style=&quot;display: block;&quot;&gt;&lt;/img&gt;
&lt;/div&gt;

&lt;p&gt;If you want to play with generation and animation you can use Quil sketch editor for Clojurescript: &lt;a href=&quot;http://quil.info/sketches/show/-KhLDgDNaWefS_AJF0YB&quot;&gt;2D sketch&lt;/a&gt; and &lt;a href=&quot;http://quil.info/sketches/show/-KhLDmUbrARfacc4hQe-&quot;&gt;3D sketch&lt;/a&gt;. If you prefer Clojure - checkout this &lt;a href=&quot;https://github.com/nbeloglazov/blog-projects/tree/master/vector-generation&quot;&gt;project&lt;/a&gt;.&lt;/p&gt;

&lt;script&gt;window.generationFrameRate=5;&lt;/script&gt;

&lt;script src=&quot;/scripts/vector-generation.js&quot;&gt;&lt;/script&gt;
</description>
      <pubDate>Sun, 09 Apr 2017 00:00:00 -0700</pubDate>
      <link>http://nbeloglazov.com/2017/04/09/random-vector-generation.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2017/04/09/random-vector-generation.html</guid>
    </item>
    
    <item>
      <title>Getting Started with Self-Hosted ClojureScript. Part 3.</title>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/2016/03/05/getting-started-with-self-hosted-cljs-part-1.html&quot;&gt;Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2016/03/07/getting-started-with-self-hosted-cljs-part-2.html&quot;&gt;Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Part 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In previous parts of this tutorial we learned how to compile ClojureScript code using only ClojureScript. In this article we&amp;#39;ll see how we can optimize this process by using compilation cache.&lt;/p&gt;

&lt;h3&gt;Cache in self-hosted cljs&lt;/h3&gt;

&lt;p&gt;If you read &lt;a href=&quot;https://github.com/cljsinfo/cljs-api-docs/blob/catalog/refs/cljs.js/STARload-fnSTAR.md&quot;&gt;documentation&lt;/a&gt; for &lt;code&gt;*load-fn*&lt;/code&gt; carefully you probably noticed that one of the values we can pass to to callback function is &lt;code&gt;:cache&lt;/code&gt; . When is it useful? A couple of use case come in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In jsfiddle-like service. Your service might provide a set of cljs libraries to use. It makes sense to precompile all these libraries as they don&amp;#39;t change from user to user. That&amp;#39;s what I do for Quil: I precompile &lt;code&gt;quil.core&lt;/code&gt; and load cache only, no source code. Fully compiling Quil using self-hosted js takes around 5 sec on my laptop which is quite a lot especially if you want to compile simple sketch.&lt;/li&gt;
&lt;li&gt;Mike Fikes &lt;a href=&quot;http://blog.fikesfarm.com/posts/2016-02-03-planck-macros-aot.html&quot;&gt;uses&lt;/a&gt; caching capabilities to precompile macros for Planck, OS X ClojureScript REPL.&lt;/li&gt;
&lt;li&gt;Going further I can imagine web IDE for ClojureScript. In such IDE project might consist of dozens of cljs files and compiling them might be long. To optimize cache of each source file compilation might be stored in browser local storage and reused.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&amp;#39;s cache now! The first question is where do we get cache from? Obviously, we need to compile source first and somehow get cache from that compilation. Here is the way I did it: you can pass &lt;code&gt;:cache-source&lt;/code&gt; function in compilation &lt;code&gt;opts&lt;/code&gt; map. This function will be called once each namespace is compiled and compiler passes a map that contains compiled source and analysis cache. For now, let&amp;#39;s simply log the map in console:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;&amp;#39;my.math&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;(ns my.math) (defmacro triple [x] (* 3 x))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.test (:require-macros my.math))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (def foo (my.math/triple 5))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Loading dependency&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;if-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dep-source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:clj&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dep-source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;js/Error.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Unknown namespace &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;print-cache&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:load&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:cache-source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;print-cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;print-cache&lt;/code&gt; takes 2 arguments: map with cache data and callback to call once we&amp;#39;re done with processing cache. In our case we print cache and call &lt;code&gt;cb&lt;/code&gt; immediately after that. Here is the cache we get in console:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:clj&lt;/span&gt;,
 &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my.math&lt;/span&gt;,
 &lt;span class=&quot;ss&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;my/math&amp;quot;&lt;/span&gt;,
 &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt;
 &lt;span class=&quot;s&quot;&gt;&amp;quot;goog.provide(\&amp;quot;my.math$macros\&amp;quot;);\nmy.math$macros.triple = (function my$math$macros$triple(_AMPERSAND_form,_AMPERSAND_env,x){\nreturn ((3) * x);\n});\n\nmy.math$macros.triple.cljs$lang$macro = true;\n&amp;quot;&lt;/span&gt;,
 &lt;span class=&quot;ss&quot;&gt;:cache&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:use-macros&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:excludes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my.math$macros&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:imports&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:requires&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:uses&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:defs&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;triple&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:protocol-inline&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:meta&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:file&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my.math&lt;/span&gt;,
     &lt;span class=&quot;ss&quot;&gt;:line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;,
     &lt;span class=&quot;ss&quot;&gt;:column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;,
     &lt;span class=&quot;ss&quot;&gt;:end-line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;,
     &lt;span class=&quot;ss&quot;&gt;:end-column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;,
     &lt;span class=&quot;ss&quot;&gt;:macro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;,
     &lt;span class=&quot;ss&quot;&gt;:arglists&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])}&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my.math$macros/triple&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:variadic&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:file&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:end-column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:method-params&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:protocol-impl&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:arglists-meta&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:macro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:end-line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:max-fixed-arity&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:fn-var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;,
    &lt;span class=&quot;ss&quot;&gt;:arglists&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])}}&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:require-macros&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;,
  &lt;span class=&quot;ss&quot;&gt;:doc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now is the time to compile using that cache. To achieve that we&amp;#39;re going to replace &lt;code&gt;load-inlined&lt;/code&gt; function with &lt;code&gt;load-cached&lt;/code&gt;. &lt;code&gt;load-cached&lt;/code&gt; is going to return cache data you saw above (I simply copy-pasted it):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;my.math&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;goog.provide(\&amp;quot;my.math$macros\&amp;quot;);\nmy.math$macros.triple = (function my$math$macros$triple(_AMPERSAND_form,_AMPERSAND_env,x){\nreturn ((3) * x);\n});\n\nmy.math$macros.triple.cljs$lang$macro = true;\n&amp;quot;&lt;/span&gt;,
              &lt;span class=&quot;ss&quot;&gt;:cache&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:use-macros&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:excludes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my.math$macros&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:imports&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:requires&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:uses&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:defs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;triple&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:protocol-inline&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:meta&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:file&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my.math&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:end-line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:end-column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:macro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:arglists&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;quote &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))}&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my.math$macros/triple&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:variadic&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:file&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:end-column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:method-params&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:protocol-impl&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:arglists-meta&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:column&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:macro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:end-line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:max-fixed-arity&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:fn-var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:arglists&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;quote &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))}}&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:require-macros&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;, &lt;span class=&quot;ss&quot;&gt;:doc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.test (:require-macros my.math))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (my.math/triple 5)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-cached&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Loading cached dependency&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;if-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dep&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:js&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:cache&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:cache&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;js/Error.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Unknown namespace &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;print-cache&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pr &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:load&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-cached&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:cache-source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;print-cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Console output:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;goog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;provide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my.test&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;goog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;cljs.core&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It works! Few notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We never pass the source of &lt;code&gt;my.math&lt;/code&gt; to the compiler. Instead we pass compiled js and analysis cache.&lt;/li&gt;
&lt;li&gt;When using cache we provide compiled js so &lt;code&gt;:lang&lt;/code&gt; must be set to &lt;code&gt;:js&lt;/code&gt;, not &lt;code&gt;:clj&lt;/code&gt; as we did before.&lt;/li&gt;
&lt;li&gt;If experimenting with it yourself - don&amp;#39;t forget to add quote &lt;code&gt;&amp;#39;&lt;/code&gt; before cache map because it contains symbols and without quoting ClojureScript is going to try and resolve them thinking that they&amp;#39;re actual variables.&lt;/li&gt;
&lt;li&gt;A map passed to &lt;code&gt;:cache-source&lt;/code&gt; doesn&amp;#39;t tell you if a namespace is macro or regular. Check the cache above and you&amp;#39;ll see that there is no &lt;code&gt;:macro true&lt;/code&gt; or similar in it. It might be problematic if you have some namespace compiled both as macros and as regular namespace. For example in Part 2 we had &lt;code&gt;my.math&lt;/code&gt; both as macro and regular namespace. In that case &lt;code&gt;:cache-source&lt;/code&gt; will be called twice and you&amp;#39;ll have to figure out if given cache is for macro or regular namespace. One workaround is to check &lt;code&gt;(:name (:cache opts))&lt;/code&gt; which has &lt;code&gt;$macros&lt;/code&gt; at the end  if it&amp;#39;s a macro namespace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In your real application you probably want to gather caches of all namespaces and save them somewhere for later use. There are various ways to do it. For example, I collect all caches into an atom and once everything compiled I save the content of the atom in a file on disk (I&amp;#39;m running on nodejs so I have access to filesystem).&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;I hope this tutorial was useful and helped to start working with self-hosted cljs. Personally, I believe it is important to have a way to experiment with self-hosted cljs without distractions of loading files from a filesystem, understanding the difference between clj, cljs, cljc files and other. The compiler doesn&amp;#39;t care about it at all.  That&amp;#39;s what I tried to do in this tutorial: having single file that contains all necessary data to play with self-hosted cljs. If you&amp;#39;re interested in more advanced/practical things here are some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checkout amazing Mike Fikes&amp;#39; blog: &lt;a href=&quot;http://blog.fikesfarm.com/&quot;&gt;http://blog.fikesfarm.com/&lt;/a&gt;. It contains a lot of insights on various self-hosted cljs things.&lt;/li&gt;
&lt;li&gt;Checkout articles on ClojureScript &lt;a href=&quot;https://github.com/clojure/clojurescript/wiki&quot;&gt;wiki&lt;/a&gt; about bootstrapped cljs.&lt;/li&gt;
&lt;li&gt;Checkout &lt;a href=&quot;https://github.com/Lambda-X/replumb&quot;&gt;replumb&lt;/a&gt; library that does some plumbing of self-hosted cljs infrastructure.&lt;/li&gt;
&lt;li&gt;If you have problems, ask on ClojureScript mailing list. There are many experienced people (e.g Mike) who&amp;#39;re willing to help.&lt;/li&gt;
&lt;li&gt;If something doesn&amp;#39;t work as you expect - it might be a bug. There are still some rough edges in self-hosted cljs and you might stumble upon one. Try to prepare minimal reproducible example and send it to the mailing list.&lt;/li&gt;
&lt;li&gt;Try reading and debugging &lt;a href=&quot;https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/js.cljs&quot;&gt;&lt;code&gt;js.cljs&lt;/code&gt;&lt;/a&gt; source code. It&amp;#39;s not easy but very useful if you get some issues with cljs compilation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have fun with self-hosted cljs!&lt;/p&gt;
</description>
      <pubDate>Fri, 11 Mar 2016 00:00:00 -0800</pubDate>
      <link>http://nbeloglazov.com/2016/03/11/getting-started-with-self-hosted-cljs-part-3.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2016/03/11/getting-started-with-self-hosted-cljs-part-3.html</guid>
    </item>
    
    <item>
      <title>Getting Started with Self-Hosted ClojureScript. Part 2.</title>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/2016/03/05/getting-started-with-self-hosted-cljs-part-1.html&quot;&gt;Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Part 2&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2016/03/11/getting-started-with-self-hosted-cljs-part-3.html&quot;&gt;Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;a href=&quot;/2016/03/05/getting-started-with-self-hosted-cljs-part-1.html&quot;&gt;Part 1&lt;/a&gt; we learned how to compile simple cljs namespaces. Here is what we had at the end of the previous article:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;ns &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my.main&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cljs.js&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cljs.pprint&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:refer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enable-console-print!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cjs/empty-state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cjs/compile-str&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;bla&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.test)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (defn triple [x] (* x 3))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (triple 5)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&amp;#39;s modify callback function in &lt;code&gt;compile&lt;/code&gt; function so it prints compiled code if it was successful or error otherwise:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;print-result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cjs/compile-str&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;bla&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;print-result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Adding some :require&lt;/h3&gt;

&lt;p&gt;Now we&amp;#39;re going to use functions from other namespaces. We&amp;#39;re going to move function &lt;code&gt;triple&lt;/code&gt; into separate namespace &lt;code&gt;my.math&lt;/code&gt; and require &lt;code&gt;my.math&lt;/code&gt; from &lt;code&gt;my.test&lt;/code&gt;. When cljs compiles namespace and sees that it requires another namespace - the compiler needs to get the source of that dependancy namespace as well. The compiler doesn&amp;#39;t know how to get them (all it knows is how to compile). So we have to provide a &lt;code&gt;load&lt;/code&gt; function that given namespace name loads source of the namespace. Usually, this &lt;code&gt;load&lt;/code&gt; function fetches clj/cljs/cljc files from disk. We want to keep it simple so we&amp;#39;re going to inline source of &lt;code&gt;my.math&lt;/code&gt; in our file without loading it from anywhere. Here is the code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;&amp;#39;my.math&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;(ns my.math) (defn triple [x] (* 3 x))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.test (:require my.math))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (my.math/triple 5)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Loading dependency&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;if-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dep-source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:clj&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dep-source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;js/Error.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Unknown namespace &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:load&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Console output:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;Loading dependency {:name my.math, :path my/math}

goog.provide(&amp;#39;my.test&amp;#39;);
goog.require(&amp;#39;cljs.core&amp;#39;);
goog.require(&amp;#39;my.math&amp;#39;);
my.math.triple.call(null,(5));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that final output contains only compiled &lt;code&gt;source&lt;/code&gt;, it doesn&amp;#39;t include compiled &lt;code&gt;my.math&lt;/code&gt; which is a dependency. Compiler didn&amp;#39;t actually compile &lt;code&gt;my.math&lt;/code&gt;, just analyzed it. If you try adding a typo, e.g. change &lt;code&gt;(my.math/triple 5)&lt;/code&gt; to &lt;code&gt;(my.math/truple 5)&lt;/code&gt; you&amp;#39;ll get an warning in console:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;Loading dependency {:name my.math, :path my/math}
WARNING: Use of undeclared Var my.math/truple at line 3

goog.provide(&amp;#39;my.test&amp;#39;);
goog.require(&amp;#39;cljs.core&amp;#39;);
goog.require(&amp;#39;my.math&amp;#39;);
my.math.truple.call(null,(5));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You see that source is still compiled with &lt;code&gt;truple&lt;/code&gt; but the compiler warned us that it haven&amp;#39;t found &lt;code&gt;truple&lt;/code&gt; function in &lt;code&gt;my.math&lt;/code&gt; namespace. Note that content of &lt;code&gt;my.math&lt;/code&gt; namespace doesn&amp;#39;t affect compilation of source in any way. We could even return an empty string for &lt;code&gt;my.math&lt;/code&gt;. In that case, &lt;code&gt;source&lt;/code&gt; would still be compiled the same way, but the compiler would warn us that we&amp;#39;re using undeclared functions.
&lt;br&gt;&lt;br&gt;
You can add more dependencies. For example &lt;code&gt;my.math&lt;/code&gt; might require additional namespaces and compiler will try to load them using the &lt;code&gt;load&lt;/code&gt; function we provided. Even if you require some standard namespaces like &lt;code&gt;clojure.string&lt;/code&gt; - compiler still asks us to provide the source. We can either load real source file from ClojureScript jar file or just return an empty string and ignore compiler warnings about calling undeclared functions &lt;code&gt;clojure.string&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;How about macros?&lt;/h3&gt;

&lt;p&gt;One really cool feature of self-hosted cljs is that it can compile and expand macros. Macros are an important part of Clojure/ClojureScript ecosystem and without this feature, self-hosted cljs can&amp;#39;t be truly self-hosted. Macros in self-hosted cljs work similar to regular ClojureScript: &lt;code&gt;source&lt;/code&gt; is a regular cljs file that contains definitions of functions, variables, calls functions from other namespaces and also may call macros. But it cannot define macros: if you add &lt;code&gt;defmacro&lt;/code&gt; to cljs source it will be ignored and you won&amp;#39;t be able to use it. Macros must be defined in separate &amp;quot;macros&amp;quot; namespaces. With regular ClojureScript you put macros in .clj files not .cljs. In self-hosted cljs it is similar but instead of .clj vs .cljs files there is macros vs regular namespaces. How does compiler load macros namespaces? Using the &lt;code&gt;load&lt;/code&gt; function we passed in compile options map. For macros namespaces, it adds &lt;code&gt;:macros true&lt;/code&gt; so we (implementors of &lt;code&gt;load&lt;/code&gt; function) can understand which type of namespaces compiler needs. Let&amp;#39;s see it in practice.
&lt;br&gt;&lt;br&gt;
We&amp;#39;re going to turn &lt;code&gt;triple&lt;/code&gt; function into a macro: it&amp;#39;s going to perform multiplication during compile time instead of runtime. This macro is going to work only if you pass a number. Code hasn&amp;#39;t changed much:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;&amp;#39;my.math&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;(ns my.math) (defmacro triple [x] (* 3 x))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.test (:require-macros my.math))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (def foo (my.math/triple 5))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Loading dependency&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;if-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dep-source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:clj&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dep-source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;js/Error.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Unknown namespace &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:load&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we now use &lt;code&gt;:require-macros&lt;/code&gt; instead of &lt;code&gt;:require&lt;/code&gt; in &lt;code&gt;my.test&lt;/code&gt; and &lt;code&gt;triple&lt;/code&gt; is now defined as &lt;code&gt;defmacro&lt;/code&gt;, not &lt;code&gt;defn&lt;/code&gt;. Console output:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;Loading dependency {:name my.math, :macros true, :path my/math}

goog.provide(&amp;#39;my.test&amp;#39;);
goog.require(&amp;#39;cljs.core&amp;#39;);
my.test.foo = (15);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Compiler applied &lt;code&gt;triple&lt;/code&gt; macro to number 5 during compilation and we got &lt;code&gt;15&lt;/code&gt; even without evaluating compiled code! Also take closer look at &lt;code&gt;Loading dependency {:name my.math, :macros true, :path my/math}&lt;/code&gt;. It now has &lt;code&gt;:macros true&lt;/code&gt; which wasn&amp;#39;t there before. This means that compiler asked us to load macros &lt;code&gt;my.math&lt;/code&gt; namespace, not a regular namespace. It is possible that same namespace is loaded &amp;quot;twice&amp;quot;: as macros and as regular namespace. But it doesn&amp;#39;t mean that we have to return the same source for both cases. On the contrary, usually &amp;quot;macros&amp;quot; namespace has, well, some &lt;code&gt;defmacro&lt;/code&gt; in it and regular namespaces has regular cljs functions. We&amp;#39;ll see such example in a little bit.
&lt;br&gt;&lt;br&gt;
How does cljs apply macros? Roughly the process is following: the compiler compiles macros namespace to js, &lt;code&gt;defmacro&lt;/code&gt; becomes js functions with additional properties, then it uses these freshly evaluated js function whenever it finds macro calls. So far we&amp;#39;ve seen only final compiled js from &lt;code&gt;source&lt;/code&gt;, but under the hood the compiler also compiles &lt;code&gt;my.math&lt;/code&gt; namespace because now it&amp;#39;s macro namespace. Is there a way to see it so we can better understand how it works? Fortunately, there is. You can add &lt;code&gt;:verbose true&lt;/code&gt; to compile options and it will enable internal debug logs. It is super useful if you&amp;#39;re trying to debug some issue with compilation in dependencies. Let&amp;#39;s see what we get:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:load&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:verbose&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Console output:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;Namespace side effects for my.test
Processing :use-macros for my.test
Processing :require-macros for my.test
Loading my.math macros namespace
Loading dependency {:name my.math, :macros true, :path my/math}
Evaluating my.math
Namespace side effects for my.math
Processing :use-macros for my.math
Processing :require-macros for my.math

goog.provide(&amp;quot;my.math$macros&amp;quot;);
my.math$macros.triple = (function my$math$macros$triple(_AMPERSAND_form,_AMPERSAND_env,x){
return ((3) * x);
});
my.math$macros.triple.cljs$lang$macro = true;

goog.provide(&amp;#39;my.test&amp;#39;);
goog.require(&amp;#39;cljs.core&amp;#39;);
my.test.foo = (15);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It might be somewhat noisy but take a look at the last 2 chunks of code. The first defines &lt;code&gt;my.math$macros&lt;/code&gt; namespace which is our macros namespace that compiler used under the hood. You can see that it has special &lt;code&gt;$macros&lt;/code&gt; suffix that helps to keep it separate from regular namespaces. The last chunk of code is compiled &lt;code&gt;source&lt;/code&gt; which we already saw, so nothing interesting here. With &lt;code&gt;:verbose&lt;/code&gt; output compiler prints all code it compiles and evaluates which is cool.
&lt;br&gt;&lt;br&gt;
Let&amp;#39;s try now load the same namespace twice: as macro and as regular namespace. We&amp;#39;re going to fix &lt;code&gt;triple&lt;/code&gt; macro so it does following: if the argument is a number - perform multiplication during compile time, otherwise (if it is a variable or call to other function) defer calculation to &lt;code&gt;triple-fn&lt;/code&gt; function. In order to do that, we need to fix our &lt;code&gt;load-inlined&lt;/code&gt; function. Right now it is dumb and cannot distinguish between macros and regular namespaces, but in real life you should distinguish between these two cases. Actually, &lt;a href=&quot;https://github.com/cljsinfo/cljs-api-docs/blob/catalog/refs/cljs.js/STARload-fnSTAR.md&quot;&gt;documentation&lt;/a&gt; for &lt;code&gt;*load-fn*&lt;/code&gt; suggests that when loading macros namespace you should use only .clj or .cljc files and for regular namespaces .cljs or .cljc files. In our case, we&amp;#39;re going to have 2 maps of inlined namespaces: &lt;code&gt;deps-macros&lt;/code&gt; and &lt;code&gt;deps-regular&lt;/code&gt;. Here it is:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;deps-macros&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;my.math&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.math)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (defmacro triple [x]&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;    (if (number? x)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      (* 3 x)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      `(my.math/triple-fn ~x)))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;deps-regular&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;my.math&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;(ns my.math) (defn triple-fn [x] (* 3 x))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.test (:require my.math) (:require-macros my.math))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (def five 5)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (+ (my.math/triple 5) (my.math/triple five))&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Loading dependency&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:macros&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;deps-macros&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;deps-regular&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:lang&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:clj&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;js/Error.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Unknown namespace &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:load&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-inlined&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;:verbose&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Console output (debug info omitted):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;Loading dependency {:name my.math, :macros nil, :path my/math}
Loading dependency {:name my.math, :macros true, :path my/math}

goog.provide(&amp;quot;my.test&amp;quot;);
my.test.five = (5);
((15) + my.math.triple_fn.call(null,my.test.five));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It worked! You can see that &lt;code&gt;my.math&lt;/code&gt; was loaded twice. First as regular namespace and second time as macro namespaces. From compiled code we see that the first call to &lt;code&gt;triple&lt;/code&gt; was calculated in-place while the second was deferred to &lt;code&gt;triple-fn&lt;/code&gt;. Just like we expected. But to be honest, this example is not complete because even though &lt;code&gt;my.math&lt;/code&gt; was loaded twice, the compiler compiled only macro namespace and didn&amp;#39;t compile regular namespace, just analyzed it. To make it fully work replace &lt;code&gt;cjs/compile-str&lt;/code&gt; with &lt;code&gt;cjs/eval-str&lt;/code&gt; in &lt;code&gt;compile&lt;/code&gt; function and now it should fully compile and evaluate each namespace and produce &amp;quot;30&amp;quot; in console output. Also, with &lt;code&gt;verbose&lt;/code&gt; output you should see all 3 namespaces being compiled under the hood.
&lt;br&gt;&lt;br&gt;
Initially, I wanted to make this example more elegant by making &lt;code&gt;triple&lt;/code&gt; both macro and function. This way we can use &lt;code&gt;triple&lt;/code&gt; anywhere. Where possible compiler precomputes and where it is not possible - defers it to runtime &lt;code&gt;triple&lt;/code&gt; function. I tried following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defmacro &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;triple&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;number?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;my.math/triple&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But the problem here that when compiler processes &lt;code&gt;(my.math/triple five)&lt;/code&gt; - it thinks that it is macro and expands it to &lt;code&gt;(my.math/triple five)&lt;/code&gt; and ... expands it again. And again. And again. And many more times until we&amp;#39;re out of stack. Basically, the compiler doesn&amp;#39;t know if we use &lt;code&gt;my.math/triple&lt;/code&gt; as macro or function. One way hack I found is to make &amp;quot;function&amp;quot; call look more like js call and not regular clojure:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defmacro &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;triple&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;number?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.triple&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js/my.math&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This way the compiler doesn&amp;#39;t try to expand result as macro. But it doesn&amp;#39;t look clojurish and I decided to go with more clunky &lt;code&gt;triple-fn&lt;/code&gt; instead. I don&amp;#39;t know if there is a better way to do it.
&lt;br&gt;&lt;br&gt;
That&amp;#39;s all for today. We learned how to compile both regular cljs and macros in self-hosted cljs! In the &lt;a href=&quot;/2016/03/11/getting-started-with-self-hosted-cljs-part-3.html&quot;&gt;next article&lt;/a&gt;, I&amp;#39;ll show how to optimize compilation using cache.&lt;/p&gt;
</description>
      <pubDate>Mon, 07 Mar 2016 00:00:00 -0800</pubDate>
      <link>http://nbeloglazov.com/2016/03/07/getting-started-with-self-hosted-cljs-part-2.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2016/03/07/getting-started-with-self-hosted-cljs-part-2.html</guid>
    </item>
    
    <item>
      <title>Getting Started with Self-Hosted ClojureScript. Part 1.</title>
      <description>&lt;ul&gt;
&lt;li&gt;Part 1&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2016/03/07/getting-started-with-self-hosted-cljs-part-2.html&quot;&gt;Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2016/03/11/getting-started-with-self-hosted-cljs-part-3.html&quot;&gt;Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ClojureScript is a compiler for Clojure that targets JavaScript. About &lt;a href=&quot;https://groups.google.com/forum/#!searchin/clojurescript/1.7.28/clojurescript/Z6xD9UthbvQ/gsLMbURGAgAJ&quot;&gt;7 months ago&lt;/a&gt; it got a nice feature that allows you to compile ClojureScript code using ClojureScript: self-hosting. That means that we can now compile ClojureScript fully in browser! That&amp;#39;s pretty cool for creating various interactive in-browser tutorials/repls/workspaces/whatever. I&amp;#39;ve been working on compiling Quil using self-hosted cljs (including macros) and decided to write basic tutorial of how to work with self-hosted cljs. This tutorial uses vanilla cljs without any additional libraries or features like reading files from disk, sending XHR so all you need is to understand basic ClojureScript syntax. In these articles I&amp;#39;ll be using latest ClojureScript currently available: 1.7.228.&lt;/p&gt;

&lt;h3&gt;Prepare&lt;/h3&gt;

&lt;p&gt;Let&amp;#39;s start with creating a basic cljs project.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash language-bash&quot; data-lang=&quot;bash&quot;&gt;git clone https://github.com/nbeloglazov/blog-projects.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;blog-projects/self-hosted-cljs
lein cljsbuild auto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Open &lt;code&gt;index.html&lt;/code&gt; in your browser. Alternatively you can create or reuse any existing cljs project your have.&lt;/p&gt;

&lt;h3&gt;Your first compile&lt;/h3&gt;

&lt;p&gt;Let&amp;#39;s start with standard &amp;quot;Hello, world&amp;quot;. If you cloned my project the code is already there:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;ns &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my.main&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cljs.js&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cljs.pprint&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:refer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enable-console-print!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cjs/empty-state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cjs/eval-str&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&amp;quot;(.log js/console \&amp;quot;Hello, world\&amp;quot;)&amp;quot;&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&amp;quot;bla&amp;quot;&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;nv&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Reload the page and you should see &amp;quot;Hello, world&amp;quot; in console. So let&amp;#39;s see what&amp;#39;s going on here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Require &lt;code&gt;cljs.js&lt;/code&gt; namespace. That namespace contains all self-hosting-related functions.&lt;/li&gt;
&lt;li&gt;Define &lt;code&gt;state&lt;/code&gt; variable that is initialized with empty state. Tbh I don&amp;#39;t know what state can contain so I usually pass empty state to all eval/compile functions.&lt;/li&gt;
&lt;li&gt;Calling &lt;code&gt;eval-str&lt;/code&gt; to eval cljs code. It takes quite a few of arguments. But the important ones for us here is second (source) and fourth (opts) arguments. Other are &amp;quot;default&amp;quot; and we can ignore them for now. If curious - check &lt;a href=&quot;https://github.com/cljsinfo/cljs-api-docs/blob/catalog/refs/cljs.js/eval-str.md&quot;&gt;docs&lt;/a&gt; to see what each argument is. In options map we provide a function that is used to evaluated compiled js. Cljs compiler doesn&amp;#39;t have default eval function so we have to provide it explicitly all the time. If you take a look at &lt;a href=&quot;https://github.com/cljsinfo/cljs-api-docs/blob/catalog/refs/cljs.js/js-eval.md&quot;&gt;&lt;code&gt;js-eval&lt;/code&gt;&lt;/a&gt; function you&amp;#39;ll see that it is plain old javascript &lt;code&gt;eval()&lt;/code&gt; (as name implies), no magic here.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Evaluation is good, but it would be more interesting to see compiled code before it is evaluated. It helps to understand how it works and makes it easier to debug. To see compiled code of &lt;code&gt;eval-str&lt;/code&gt; we&amp;#39;ll be using &lt;code&gt;compile-str&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cjs/compile-str&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;
                 &lt;span class=&quot;s&quot;&gt;&amp;quot;(.log js/console \&amp;quot;Hello, world\&amp;quot;)&amp;quot;&lt;/span&gt;
                 &lt;span class=&quot;s&quot;&gt;&amp;quot;bla&amp;quot;&lt;/span&gt;
                 &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                 &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And output in logs:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello, world&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last (fifth) argument is changed from &lt;code&gt;identity&lt;/code&gt; to &lt;code&gt;#(println (:value %))&lt;/code&gt;. This argument is a callback function that will be invoked once cljs finished compiling. The result will be passed to the provided callback. In the first example with &lt;code&gt;eval-str&lt;/code&gt; we didn&amp;#39;t really care about the result, we just wanted &lt;code&gt;console.log&lt;/code&gt; to be evaluated. But now we use &lt;code&gt;compile-str&lt;/code&gt; and we want to see result of compilation, so we pass a function that takes that result and prints it to console.
&lt;br&gt;&lt;br&gt;
Now let&amp;#39;s compile real namespace with multiple functions. Also I&amp;#39;m going to introduce helper &lt;code&gt;compile&lt;/code&gt; function to omit default arguments:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cjs/compile-str&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;bla&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (ns my.test)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (defn triple [x] (* x 3))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  (triple 5)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:eval&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cjs/js-eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And result is following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;js language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;goog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;provide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my.test&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;goog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;cljs.core&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;triple&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;my$test$triple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;triple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Compiled code readable and you can pretty easily relate cljs source with compiled js. It has some &lt;code&gt;goog.provide&lt;/code&gt; and &lt;code&gt;goog.require&lt;/code&gt; magic which comes from Google Closure compiler used by ClojureScript, but it is quite simple: compiled code declares namespace &lt;code&gt;my.test&lt;/code&gt; and uses namespace &lt;code&gt;cljs.core&lt;/code&gt;. Everything else is standard javascript.
&lt;br&gt;&lt;br&gt;
Thats all for now. Now we can compile basic cljs namespaces. In &lt;a href=&quot;/2016/03/07/getting-started-with-self-hosted-cljs-part-2.html&quot;&gt;the next article&lt;/a&gt; we&amp;#39;ll be compiling code consisting from multiple namespaces/files and using macros.&lt;/p&gt;
</description>
      <pubDate>Sat, 05 Mar 2016 00:00:00 -0800</pubDate>
      <link>http://nbeloglazov.com/2016/03/05/getting-started-with-self-hosted-cljs-part-1.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2016/03/05/getting-started-with-self-hosted-cljs-part-1.html</guid>
    </item>
    
    <item>
      <title>Live Reloading in Quil Cljs</title>
      <description>&lt;p&gt;Quil supported live reloading since forever and it has been one of its coolest features. But only in Clojure. ClojureScript version lacked the support until now. Latest Quil release (2.2.6) fixes the problem. Now if you use plugins for live coding in ClojureScript such as &lt;a href=&quot;https://github.com/bhauman/lein-figwheel&quot;&gt;figwheel&lt;/a&gt; - you&amp;#39;ll be able to reload Quil functions (draw, update, key handlers) on fly without reloading the browser. Here is 3 steps instructions how to do it:&lt;/p&gt;

&lt;p&gt;1 Create new Quil cljs project: &lt;code&gt;lein new quil-cljs hello&lt;/code&gt; and go to &lt;code&gt;hello&lt;/code&gt; folder.&lt;br&gt;
2 Setup figwheel in &lt;code&gt;project.clj&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:plugins&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lein-cljsbuild&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.0.6&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lein-figwheel&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;0.3.3&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:cljsbuild&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:builds&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:source-paths&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                          &lt;span class=&quot;ss&quot;&gt;:figwheel&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;
                          &lt;span class=&quot;ss&quot;&gt;:compiler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;3 Start figwheel: &lt;code&gt;lein figwheel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s all. Now open &lt;code&gt;index.html&lt;/code&gt; and you should see a ball rotating around the center of the sketch. When you update &lt;code&gt;core.clj&lt;/code&gt; and save it - the updates will be reflected in the browser. For example change rotation direction by modifying &lt;code&gt;update&lt;/code&gt; function: replace plus with minus: &lt;code&gt;(- (:angle state) 0.1)&lt;/code&gt; and save it. The ball will start rotating in counter-clockwise direction.&lt;/p&gt;

&lt;p&gt;Auto-reloading is supported only in &lt;code&gt;defsketch&lt;/code&gt;. If you use &lt;code&gt;sketch&lt;/code&gt; function - it won&amp;#39;t work (the same as in Clojure version). When &lt;code&gt;defsketch&lt;/code&gt; macro is used, all functions (draw, update, etc) are wrapped into anonymous functions so they&amp;#39;re called by name rather than by value. This allows for reloading to work: when &lt;code&gt;hello.core/draw&lt;/code&gt; is reloaded by figwheel, quil will call the anonymous function wrapper which in turn calls &lt;code&gt;hello.core/draw&lt;/code&gt;. It adds some overhead so use &lt;code&gt;sketch&lt;/code&gt; instead of &lt;code&gt;defsketch&lt;/code&gt; in &amp;quot;production&amp;quot;.&lt;/p&gt;
</description>
      <pubDate>Mon, 15 Jun 2015 00:00:00 -0700</pubDate>
      <link>http://nbeloglazov.com/2015/06/15/live-reloading-in-quil-cljs.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2015/06/15/live-reloading-in-quil-cljs.html</guid>
    </item>
    
    <item>
      <title>Trees, Quil and Random</title>
      <description>&lt;p&gt;&lt;img src=&quot;/images/trees/tree-0694.png&quot; style=&quot;display: block; margin: auto;&quot; alt=&quot;First tree&quot;/&gt;&lt;/p&gt;

&lt;p&gt;Last week I&amp;#39;ve been playing with random tree generation in Quil. Idea is simple: generate a tree that resembles a real tree and doesn&amp;#39;t make you think that it was generated by computer. Suprisingly it&amp;#39;s not that hard to do. Tree is represented as a collection of branches. A branch consists of 3 components: start point, angle (from 0 to 2π) and length. Each branch can have 0, 1 or 2 sub-branches. Algorithm for generating sub-branches from a branch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each branch can have up to 2 sub-branches. Probability of each sub-branch is 90%.&lt;/li&gt;
&lt;li&gt;For each sub-ranch start point is calculated as end point of parent branch.&lt;/li&gt;
&lt;li&gt;Sub-branch lengths are randomly selected from [0.7L, 1.0L], where L is parent&amp;#39;s length.&lt;/li&gt;
&lt;li&gt;Sub-branch angles are randomly selected from [α-¼π, α+¼π], where α is parent&amp;#39;s angle.&lt;/li&gt;
&lt;li&gt;Add sub-branches to the tree.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, having the function for generating sub-branches, tree generation is easy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create root: the first branch with angle ½π.&lt;/li&gt;
&lt;li&gt;Branch-off each branch on previous level.&lt;/li&gt;
&lt;li&gt;Repeat step 2 as many times as needed. My trees have 14 levels.&lt;/li&gt;
&lt;li&gt;Concat all levels into single collection and draw them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Last part is especially easy to do in clojure and each step corresponds to one line:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;generate-tree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;root &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;iterate &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mapcat &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;branch-off&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&amp;#39;s it. Now more trees!&lt;/p&gt;

&lt;div style=&quot;display: flex; flex-wrap: wrap; justify-content: space-around;&quot;&gt;
  &lt;img src=&quot;/images/trees/tree-3649.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
  &lt;img src=&quot;/images/trees/tree-5551.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
  &lt;img src=&quot;/images/trees/tree-6173.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
  &lt;img src=&quot;/images/trees/tree-16160.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
&lt;/div&gt;

&lt;p&gt;White trees on black background look especially cool:&lt;/p&gt;

&lt;div style=&quot;display: flex; flex-wrap: wrap; justify-content: space-around;&quot;&gt;
  &lt;img src=&quot;/images/trees/tree-0890.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
  &lt;img src=&quot;/images/trees/tree-4042.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
  &lt;img src=&quot;/images/trees/tree-4509.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
  &lt;img src=&quot;/images/trees/tree-5177.png&quot; style=&quot;margin: 5px 0px;&quot; alt=&quot;Tree&quot;/&gt;
&lt;/div&gt;

&lt;h3&gt;Quil tips&lt;/h3&gt;

&lt;p&gt;I&amp;#39;ve shown only static images of trees, but in reality they&amp;#39;re animated so you can see how tree grows from a single root to a full tree with thousands of branches.&lt;/p&gt;

&lt;p&gt;Initially I used a simple approach and was redrawing all branches on each frame. It works well when you have small number of branches but tree with 14 levels has 7000-10000 branches and drawing 10000 elements on each frame is well... slow. FPS drops from 60 to 10. So I optimized it a little, removed clearing background and changed &lt;code&gt;draw-branch&lt;/code&gt; function to skip branches that are already fully drawn. That helped drastically bringing FPS back to 60. The big drawback that you can&amp;#39;t do nice transformations now that may require redrawing everything. For example after tree is drawn I wanted to zoom into smallest branch and start drawing new tree from that branch, but it requires redrawing everything during zoom and I gave up this idea.&lt;/p&gt;

&lt;p&gt;Another trick I did is around fading background color into tree color (see animations below). The idea is that screen background gradually turns to the same color as tree essentially clearing the tree. To achieve this the tree is drawn on a separate &lt;a href=&quot;http://quil.info/api/image/rendering#create-graphics&quot;&gt;graphics&lt;/a&gt; object. Graphics object is transparent and when you copy it to main screen you can see background. With this technique &lt;code&gt;draw&lt;/code&gt; function looks like the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;; Clear screen using calculated background screen. Background depends&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;; on tree state: if tree is fully drawn it gradually changes to match the&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;; tree color.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;q/background&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;calculate-background-color&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;; Draw active branches on graphics object. Note that we don&amp;#39;t erase&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;; existing branches, draw-tree only draws active branches. &lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;q/with-graphics&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:buffer&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;draw-tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;; Copy buffer graphics to main screen.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;q/image&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:buffer&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And finally endless trees:&lt;/p&gt;

&lt;script src=&quot;/scripts/trees.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;canvas id=&quot;tree&quot;/&gt;&lt;/p&gt;

&lt;script&gt;
  (function() {
    var width = document.querySelector(&quot;.post&quot;).offsetWidth;
    var height = 0.7 * width;
    trees.start_tree(&quot;tree&quot;, [width, height]);
  })();
&lt;/script&gt;

&lt;p&gt;Controls (tree must have focus):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;r - regenerate tree;&lt;/li&gt;
&lt;li&gt;up/down - change number of levels;&lt;/li&gt;
&lt;li&gt;i - toggle stats;&lt;/li&gt;
&lt;li&gt;s - save as image (opens in new tab);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find source code on &lt;a href=&quot;https://github.com/nbeloglazov/blog-projects/tree/master/trees&quot;&gt;GitHub&lt;/a&gt; or try it online on &lt;a href=&quot;http://quil.info/sketches/show/example_tree&quot;&gt;quil.info&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Mon, 18 May 2015 00:00:00 -0700</pubDate>
      <link>http://nbeloglazov.com/2015/05/18/trees-quil-and-random.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2015/05/18/trees-quil-and-random.html</guid>
    </item>
    
    <item>
      <title>Mongo Backup Using Clojure</title>
      <description>&lt;p&gt;In this post I&amp;#39;ll show a simple tool that creates Mongo backup and uploads it to &lt;a href=&quot;https://cloud.google.com/storage/&quot;&gt;Google Cloud Storage&lt;/a&gt;. Suppose you have a small webproject that uses mongo. The project runs on a single machine on some cloud provider. And you want to have periodic mongo backups. Potentially you can achieve it using features of your provider like disk snapshots, but it may require shutting down the machine or unmounting disk and it feels heavy and not fun. Instead we&amp;#39;ll create our own tool that periodically creates backups and uploads them to a file hosting service like Dropbox or Google Drive or (in my case) Google Cloud Storage. I use Google Cloud Storage because I&amp;#39;m already using &lt;a href=&quot;https://cloud.google.com/&quot;&gt;Google Cloud Platform&lt;/a&gt; as hosting for &lt;a href=&quot;http://hatnik.com&quot;&gt;Hatnik&lt;/a&gt; so why not to use available services?&lt;/p&gt;

&lt;p&gt;The tool is relatively small and consists of 2 parts: backup creation and uploading.&lt;/p&gt;

&lt;h3&gt;Create backup&lt;/h3&gt;

&lt;p&gt;Assumptions: mongo instance doesn&amp;#39;t require authentication and OS is linux.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clojure.java&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;shell&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:refer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;with-sh-dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;io&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:refer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clean&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Removes old dump from current folder if exists.&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;rm&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;-r&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;dump&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;rm&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;dump.zip&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;create-dump&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Creates dump and pack it into dump.zip file in current folder.&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;mongodump&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;zip&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;-r&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;dump.zip&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;dump&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;archive-name&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Generates name for dump file. That&amp;#39;s how it will be saved in Cloud Storage.&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;java.text.SimpleDateFormat.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;yyyy-MM-dd_kk-mm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;java.util.Date.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.zip&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see it is pretty trivial. We use &lt;code&gt;mongodump&lt;/code&gt; utility for creating dump from running mongo instance. Mongo &lt;a href=&quot;http://docs.mongodb.org/manual/core/backups/#backup-with-mongodump&quot;&gt;docs&lt;/a&gt; say that it should be used only for small deployments as it hurts performance.&lt;/p&gt;

&lt;h3&gt;Uploading to cloud&lt;/h3&gt;

&lt;p&gt;Now we&amp;#39;re going to jump through Google API hoops in order to upload single zip file. First of all you should setup &lt;a href=&quot;https://cloud.google.com/storage/docs/authentication#service_accounts&quot;&gt;service account&lt;/a&gt; that will allow the tool to upload to the storage. It will generate an email address and private key that will be used for authentication. Now let&amp;#39;s go to code. To simplify things we will be using official java library for working with Google Cloud Storage (&lt;a href=&quot;https://developers.google.com/resources/api-libraries/documentation/storage/v1/java/latest/&quot;&gt;javadocs&lt;/a&gt;). In the code I omit all imports as there are quite a few of them and you can get them from github project at the end of the post.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;email-address&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;lt;YOUR SERVICE ACCOUNT EMAIL HERE&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;p12-file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;lt;PATH TO PRIVATE KEY FILE&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bucket-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;mongo-backups&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;app-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;lt;YOUR GOOGLE CLOUD PROJECT NAME&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; not sure if it&amp;#39;s actually needed&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;authorize&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Authorizes app and returns credentials object that will be used to&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  create storage object.&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.. &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GoogleCredential$Builder.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setTransport&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GoogleNetHttpTransport/newTrustedTransport&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setJsonFactory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JacksonFactory/getDefaultInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setServiceAccountId&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;email-address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setServiceAccountScopes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;StorageScopes/DEVSTORAGE_FULL_CONTROL&lt;/span&gt;
                                &lt;span class=&quot;nv&quot;&gt;StorageScopes/DEVSTORAGE_READ_ONLY&lt;/span&gt;
                                &lt;span class=&quot;nv&quot;&gt;StorageScopes/DEVSTORAGE_READ_WRITE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setServiceAccountPrivateKeyFromP12File&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;p12-file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;get-storage&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Authorizes and creates storage object.&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.. &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Storage$Builder.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;http-transport&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;json-factory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;authorize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setApplicationName&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;app-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;upload-zip-file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;zip-file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get-storage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doto &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StorageObject.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.setName&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.setContentType&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;application/zip&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FileContent.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;application/zip&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;zip-file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.. &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;client&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bucket-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And finally glue both parts together:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;create-and-upload-dump&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with-sh-dir&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;/tmp&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create-dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;upload-zip-file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;archive-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;/tmp/dump.zip&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; main method needed to run the tool from command line&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;-main&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create-and-upload-dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&amp;#39;s all. You can test the tool by executing &lt;code&gt;create-and-upload-dump&lt;/code&gt; function from repl.&lt;/p&gt;

&lt;h3&gt;Create cron job&lt;/h3&gt;

&lt;p&gt;Now we can generate executable jar using &lt;code&gt;lein uberjar&lt;/code&gt;, copy it to some directory on the server together with private key file and create daily cron job by creating script in &lt;code&gt;/etc/cron.daily&lt;/code&gt; folder. My cron job looks like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Daily mongo backups&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;WORKING_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/nbeloglazov/backup
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$WORKING_DIR&lt;/span&gt;
java -jar &lt;span class=&quot;nv&quot;&gt;$WORKING_DIR&lt;/span&gt;/backup.jar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I suspect that if Dropbox or something else is used instead of Google Cloud Storage then code should be simpler. Authentication in Google APIs is kinda messy and it&amp;#39;s not easy to find correct combination and order of methods to call to make it work.&lt;/p&gt;

&lt;p&gt;For reference here is a complete working version of the tool: &lt;a href=&quot;https://github.com/nbeloglazov/hatnik/tree/master/tools/backup&quot;&gt;project on GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Mon, 15 Dec 2014 00:00:00 -0800</pubDate>
      <link>http://nbeloglazov.com/2014/12/15/backup-mongodb-using-clojure.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2014/12/15/backup-mongodb-using-clojure.html</guid>
    </item>
    
    <item>
      <title>GitHub Actions in Hatnik</title>
      <description>&lt;p&gt;&lt;a href=&quot;http://hatnik.com&quot;&gt;Hatnik&lt;/a&gt; is a tool that allows you to track library releases: you want to know when new version of ClojureScript released - you go to Hatnik, setup an action and next time ClojureScript released the action will be performed. Initially only email action was supported. Happy to announce that now we support GitHub Issue and Pull Request actions.&lt;/p&gt;

&lt;h3&gt;Issue Action&lt;/h3&gt;

&lt;p&gt;This action is pretty trivial: create an issue in selected repo when library is released. You can customize repo (obviously), issue title and body. Title and body support template variables: for example &amp;quot;{{library}} {{version}} released&amp;quot; will be rendered as &amp;quot;org.clojure/clojurescript 0.0-2371 released&amp;quot;.&lt;/p&gt;

&lt;p&gt;Issue action might be useful, for example, for library maintainers. Usually there are quite a few tasks you need to do when you release new version: update wiki, tutorials, some post-release testing. It is quite easy to forget something so Issue action can help with that: for each task create an issue and then later you or someone else can pick it up and do whatever needed to be done.&lt;/p&gt;

&lt;h3&gt;Pull Request Action&lt;/h3&gt;

&lt;p&gt;Pull Request action modifies public repo and opens pull request. Each modification operation is a find-and-replace operation and consists of 3 fields: file to be modified, regex and replacement. Regex and replacement fields support template variables.&lt;/p&gt;

&lt;p&gt;Pull request can be used to keep dependencies of you project up-to-date: just create an action that updates version of dependency X in &lt;code&gt;project.clj&lt;/code&gt; each time X is released. It is especially cool when you have CI (e.g. &lt;a href=&quot;https://travis-ci.org/&quot;&gt;Travis&lt;/a&gt;) that runs tests on pull requests: you can immediately see if new version breaks your application and if it doesn&amp;#39;t break - simply merge it. To keep your application up-to-date you need just one click! Another use case is for library maintainers: usually library README includes latest version of the library so users can simply copy-paste it to &lt;code&gt;project.clj&lt;/code&gt; and start using it. But these versions sometime become out-of-date as maintainers forget to update README. Pull Request action can help with that. For example I set up a few actions for Quil that update versions in README, examples and lein templates. Here is an &lt;a href=&quot;https://github.com/quil/quil-templates/pull/4&quot;&gt;example&lt;/a&gt; of such pull request. Final note about pull requests - if pull request action doesn&amp;#39;t change anything in repo (for example file moved or version in README has been already updated) - you&amp;#39;ll get an email that describes why Hatnik couldn&amp;#39;t open a pull request.&lt;/p&gt;

&lt;h3&gt;TODO&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Import build files. Currently Hatnik doesn&amp;#39;t provide options to import build files like &lt;code&gt;project.clj&lt;/code&gt;. So if a project has a lot of dependencies it becomes tiring to create actions for each dependency one by one. Hatnik should support import capabilites.&lt;/li&gt;
&lt;li&gt;Allow to use temporary accounts to create restricted set of actions and decide whether to use Hatnik or not. Currently you have to login via GitHub in order to try it out.&lt;/li&gt;
&lt;li&gt;Support more languages. Currently only maven-compatible libraries are supported (Java, Clojure, Scala, Groovy). We should support more.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Contributing&lt;/h3&gt;

&lt;p&gt;Hatnik is an open source project. Take a look at the &lt;a href=&quot;https://github.com/nbeloglazov/hatnik&quot;&gt;repo&lt;/a&gt;. Bug reports and pull requests are very welcome!&lt;/p&gt;
</description>
      <pubDate>Mon, 24 Nov 2014 00:00:00 -0800</pubDate>
      <link>http://nbeloglazov.com/2014/11/24/github-actions-in-hatnik.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2014/11/24/github-actions-in-hatnik.html</guid>
    </item>
    
    <item>
      <title>Introducing Hatnik</title>
      <description>&lt;p&gt;Yet another blog post about a ClojureCup 2014 project. But this time from me. About Hatnik!&lt;/p&gt;

&lt;h3&gt;Don&amp;#39;t miss a release&lt;/h3&gt;

&lt;p&gt;Hatnik is a web app we created during ClojureCup weekend. It can notify you about new library releases (currently via email only). It supports Clojure/Maven libraries which are hosted on Clojars or Maven Central. How to use it: sign in, create an action in which you specify which library you want to watch and template for the email and that&amp;#39;s all. Next the library is released we&amp;#39;ll send you an email. Try it out: &lt;a href=&quot;http://hatnik.clojurecup.com&quot;&gt;hatnik.clojurecup.com&lt;/a&gt;. If you don&amp;#39;t like signing in unfamiliar websites which you might never visit again, here is a screenshots-demonstration:&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
Initial page after you logged in&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/hatnik/hatnik_0.png&quot; alt=&quot;Initial page&quot;&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;br&gt;
Create new action&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/hatnik/hatnik_1.png&quot; alt=&quot;Create new action&quot;&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;br&gt;
Action created&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/hatnik/hatnik_2.png&quot; alt=&quot;The action created&quot;&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;br&gt;
Libraries used by Hatnik&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/hatnik/hatnik_3.png&quot; alt=&quot;All libraries&quot;&gt;&lt;/p&gt;

&lt;p&gt;You can also group actions to projects. Projects is just a named group of actions. Each user by default has &amp;quot;Default&amp;quot; project (see screenshots) so you might ignore it.&lt;/p&gt;

&lt;h3&gt;Future plans&lt;/h3&gt;

&lt;p&gt;We did the project over 2 days so obviously there are a lot of things to improve.&lt;/p&gt;

&lt;h4&gt;More actions&lt;/h4&gt;

&lt;p&gt;Currently Hatnik supports only email notifications. We&amp;#39;re planning to add more. Here is the initial list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Noop - does nothing. Might be useful for creating dashboard-like project that simply displays latest versions.&lt;/li&gt;
&lt;li&gt;GitHub Issue - creates an issue on GitHub repo.&lt;/li&gt;
&lt;li&gt;GitHub Wiki Page - changes GitHub wiki page using simple find-and-replace mechanism.&lt;/li&gt;
&lt;li&gt;GitHub Pull Request - creates pull request that modifies some files using find-and-replace mechanism.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Cleanup&lt;/h4&gt;

&lt;p&gt;We developed Hatnik in hurry so there is some technical debt.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improve web client. We used Om for the web client but we didn&amp;#39;t know it good enough so in some places code is not Om-like at all. For example we spend few hours at the end of the contest trying to fix a bug, which made library textfield read-only. Looks like the bug is described in &lt;a href=&quot;https://github.com/swannodette/om/wiki/Basic-Tutorial#dealing-with-text-input-fields&quot;&gt;tutorial&lt;/a&gt;, but even using the tutorial we couldn&amp;#39;t make it work. So we ended up with horrible hack that sets value to textfield using &lt;code&gt;setTimeout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add more validation. Currently REST API is not strict, it does very little validation. It should do more. We&amp;#39;re looking at Prismatic &lt;a href=&quot;https://github.com/Prismatic/schema&quot;&gt;schema&lt;/a&gt; for that.&lt;/li&gt;
&lt;li&gt;Add core.typed. At work I&amp;#39;m using Google Closure Compiler quite heaviliy. Among other features it introduces type system to JavaScript. It makes much easier to write correct code. So I&amp;#39;d like to try core.typed for same reasons and see whether it helps or not me.&lt;/li&gt;
&lt;li&gt;Add tests. Currently we have some DB tests. We should add integration-like tests for API and ideally sending emails, creating github issues. Tests for client side would be nice, may be something WebDriver-based.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Other plans&lt;/h4&gt;

&lt;p&gt;Hatnik currently supports only maven-compatible libraries. Nothing stops it from supporting libraries from other languages/platforms, like Ruby, JavaScript, Python. I think most tools in other languages also use HTTP for downloading libraries from central repository, so it should be pretty easy to implement in Clojure.&lt;/p&gt;

&lt;p&gt;Currently all actions have to be created manually one by one. It would be cool to be able to provide a link to &lt;code&gt;project.clj&lt;/code&gt; and it will be parsed automatically. Again, nothing prevents us from supporting other projects files like &lt;code&gt;pom.xml&lt;/code&gt;, &lt;code&gt;build.sbt&lt;/code&gt;, &lt;code&gt;Gemfile&lt;/code&gt;. Some of them just harder to parse as they&amp;#39;re written in DSL, but still, should be fun task to do.&lt;/p&gt;

&lt;h3&gt;Afterwords&lt;/h3&gt;

&lt;p&gt;Few words about the project name. Hatnik is a house spirit in Slavic folklore. There are different versions of what he does and whether he good or not, but in my environment Hatnik is a good grandpa-looking-like spirit which helps with household. So we wanted the app to do the same - help with some simple tasks which help to keep project dependencies or documentation in order. I hope it will be useful for you. If you liked Hatnik you can &lt;a href=&quot;https://clojurecup.com/#/apps/hatnik&quot;&gt;vote for us&lt;/a&gt;. Also have a look at &lt;a href=&quot;https://clojurecup.com/#/apps&quot;&gt;other projects&lt;/a&gt;, they&amp;#39;re pretty interesting. And they also needs votes ;)&lt;/p&gt;

&lt;p&gt;Hatnik is open-sourced and here is &lt;a href=&quot;https://github.com/nbeloglazov/hatnik&quot;&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Wed, 01 Oct 2014 00:00:00 -0700</pubDate>
      <link>http://nbeloglazov.com/2014/10/01/introducing-hatnik.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2014/10/01/introducing-hatnik.html</guid>
    </item>
    
    <item>
      <title>Halfway Through ClojureCup</title>
      <description>&lt;h3&gt;Hatnik&lt;/h3&gt;

&lt;p&gt;As you might have guessed, this year I&amp;#39;m participating in &lt;a href=&quot;http://clojurecup.com&quot;&gt;ClojureCup&lt;/a&gt;. We (&lt;a href=&quot;https://github.com/nbeloglazov&quot;&gt;me&lt;/a&gt; and &lt;a href=&quot;https://github.com/norgat&quot;&gt;Maksim&lt;/a&gt;) are working on a project called Hatnik. It&amp;#39;s a web app which aims to help you to track library releases. The idea is pretty simple: setup actions to be performed once some library is released. An action consists of 2 parts: library to watch and an instruction to perform. Example: send email to &lt;code&gt;me@nbeloglazov.com&lt;/code&gt; when &lt;code&gt;org.clojure/clojurescript&lt;/code&gt; releases. It is somewhat similar to &lt;a href=&quot;https://ifttt.com/&quot;&gt;IFTTT&lt;/a&gt; (but more specialized) and pretty similar to &lt;a href=&quot;https://www.artifact-listener.org/&quot;&gt;Artifact Listener&lt;/a&gt; (but obviously cooler!). We have plans to support following actions: email, github issue, github pull request, change wiki on github. Initially we&amp;#39;re going to support only email and add others if we have enough time during the contest.
&lt;br&gt;&lt;br&gt;
Organizers provided quite a few additional services like private github repo, a server for hosting app, CI servers, error-tracking utility, team chat and some other stuff. We&amp;#39;ve been using only few of them: github repo, server for hosting app and Flowdock for communication: it has integration with github and trello so we can see everything that happens in repo or task list in realtime. Though other services looked intersting I felt we&amp;#39;d spent too much time setting them up instead of working on the project.&lt;/p&gt;

&lt;h3&gt;Architecture&lt;/h3&gt;

&lt;p&gt;The app consists of 3 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web client - that&amp;#39;s what user sees and interacts with.&lt;/li&gt;
&lt;li&gt;Web server - provides API for web client and stores data to DB.&lt;/li&gt;
&lt;li&gt;Worker server - periodically checks versions of all registered libraries and performs actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I work on servers while Maksim works on the web client. For the web client we decided to use ClojureScript + Om and Twitter Bootstrap for fancy styling. Server side libraries are pretty standard: ring, compojure, monger and few other libs for emails, github api, and other stuff. You can find more details about the project in &lt;a href=&quot;https://docs.google.com/document/d/1-Ad0h22qkmLARB7T8TfokJYonOlPZzZ-cuDzz6tW7hU/edit?usp=sharing&quot;&gt;design doc&lt;/a&gt; which we prepared beforehand so we can concentrate on coding!&lt;/p&gt;

&lt;h3&gt;What we have so far&lt;/h3&gt;

&lt;p&gt;I would say we have quite enough:&lt;/p&gt;

&lt;h4&gt;Web client&lt;/h4&gt;

&lt;p&gt;Client can load and display projects together with actions. You can add new projects. What&amp;#39;s left to do: actions adding/modifying, login (everything is ready, only need to add buttons), nice &amp;quot;About&amp;quot; page that describes how to use Hatnik.&lt;/p&gt;

&lt;h4&gt;Web server&lt;/h4&gt;

&lt;p&gt;Web server is mostly done. REST API is implemented, everything is stored in DB. DB is represented as a protocol that has 2 implementations: in-memory and mongo. It might be overkill but I found it&amp;#39;s quite useful to be able to run everything in memory. I even had time to add tests for DB! I used &lt;a href=&quot;https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en&quot;&gt;Postman&lt;/a&gt; for testing REST API. It is quite cool as it allows you to save requests and reuse them later. I probably should have added some tests for REST instead but due to the time limit I decided to go with Postman: it is easier to setup and use.&lt;/p&gt;

&lt;h4&gt;Worker server&lt;/h4&gt;

&lt;p&gt;Currently worker server can only submit emails on user request: when you create an action you have an option to test it, the test request is sent to the worker server to perform the action. What&amp;#39;s left to do: add logic for checking versions of all registered libraries and perform actions for updated libraries, invoke this logic periodically.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;I&amp;#39;m having a lot of fun! I don&amp;#39;t remember when I wrote so much code last time. Lately I&amp;#39;ve been coding less at work so ClojureCup came just in time. Especially when you have an excuse to not write tons of tests and just code for the sake of coding. If you&amp;#39;re interested in what we have so far - check our &lt;a href=&quot;https://github.com/clojurecup2014/hatnik/&quot;&gt;github repo&lt;/a&gt;. And of course check out our app when the contest is over.&lt;/p&gt;
</description>
      <pubDate>Sat, 27 Sep 2014 00:00:00 -0700</pubDate>
      <link>http://nbeloglazov.com/2014/09/27/halfway-through-clojurecup.html</link>
      <guid isPermaLink="true">http://nbeloglazov.com/2014/09/27/halfway-through-clojurecup.html</guid>
    </item>
    
  </channel>
</rss>
