<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Category: web | Sebastian Wilzbach]]></title>
  <link href="https://seb.wilzba.ch/categories/web/atom.xml" rel="self"/>
  <link href="https://seb.wilzba.ch/"/>
  <updated>2023-12-18T00:13:39+01:00</updated>
  <id>https://seb.wilzba.ch/</id>
  <author>
    <name><![CDATA[]]></name>
    <email><![CDATA[admin@wilzbach.me]]></email>
  </author>

  
  <entry>
    <title type="html"><![CDATA[Rock JS with Defaultdict]]></title>
    <link href="https://seb.wilzba.ch/b/2016/02/defaultdict-in-js/"/>
    <updated>2016-02-05T06:05:43+01:00</updated>
    <id>https://seb.wilzba.ch/b/2016/02/defaultdict-in-js</id>
    <content type="html"><![CDATA[<p>Have you ever missed any of Python’s neat packages like <code class="language-plaintext highlighter-rouge">defaultdict</code> when coding
in JavaScript?
Unfortunately this reflection functionality wasn’t given in JavaScript.</p>

<p>However now thanks to the <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy">Proxy API</a> we can intercept <em>property lookups</em> and build a native <code class="language-plaintext highlighter-rouge">defaultdict</code> in JS.
Proxies are part of the ECMAScript 6 standard and are already implemented in 
Edge, Firefox and Chrome (&gt;= 49) (more <a href="https://kangax.github.io/compat-table/es6/">details</a>).</p>

<h2 id="starting-simple">Starting simple</h2>

<p>I have built a pure <a href="https://github.com/wilzbach/defaultdict2"><code class="language-plaintext highlighter-rouge">defaultdict</code></a> JS/Node package for which I will show 
why it’s so pleasant to finally have <em>reflection</em> in JavaScript.
In contrast to other implementations, one doesn’t need to use any special getter
and it really can be used like it’s Python “brother”. Detailed instructions
for its Browsers or Node.Js use are provided on <a href="https://github.com/wilzbach/defaultdict2">github</a>.</p>

<p>For a start let’s consider this very simply example:</p>

<p><figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">defaultdict</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="nx">d</span><span class="p">.</span><span class="nx">a</span><span class="o">++</span><span class="p">;</span> 
<span class="nx">d</span><span class="p">.</span><span class="nx">b</span><span class="o">++</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">d</span><span class="p">);</span>
<span class="c1">// { a: 1, b: 1 }</span></code></pre></figure></p>

<p>And its similar Python version:</p>

<p><figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">d</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
<span class="n">d</span><span class="p">[</span><span class="err">“</span><span class="n">a</span><span class="err">”</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">d</span><span class="p">[</span><span class="err">“</span><span class="n">b</span><span class="err">”</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">print</span><span class="p">(</span><span class="n">d</span><span class="p">)</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">h1</span> <span class="nb">id</span><span class="o">=</span><span class="s">"defaultdictclass-int-b-1-a-1"</span><span class="o">&gt;</span><span class="n">defaultdict</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="k">class</span> <span class="err">‘</span><span class="nc">int</span><span class="err">’</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;,</span> <span class="p">{</span><span class="err">‘</span><span class="n">b</span><span class="err">’</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="err">‘</span><span class="n">a</span><span class="err">’</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span><span class="o">&lt;/</span><span class="n">h1</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span></code></pre></figure></p>

<h2 id="coding-with-defaultdict-is-fun">Coding with Defaultdict is fun!</h2>

<p>Our first example wasn’t very fascinating as we need for the direct assignment (<code class="language-plaintext highlighter-rouge">d.a=1</code>) 
the same amount of characters (if whitespaces are removed).</p>

<p>However coding with <code class="language-plaintext highlighter-rouge">defaultdict</code> is a lot of fun!
Let’s consider building a 2-kmers counting matrix.</p>

<p>Traditionally we would have written this in JavaScript:</p>

<p><figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="kd">var</span> <span class="nx">seq</span> <span class="o">=</span> <span class="err">“</span><span class="nx">AGAGACGAG</span><span class="err">”</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&amp;</span><span class="nx">lt</span><span class="p">;</span> <span class="nx">seq</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">){</span>
	<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">d</span><span class="p">[</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="p">]]</span> <span class="o">===</span> <span class="err">“</span><span class="kc">undefined</span><span class="err">”</span><span class="p">){</span>
		<span class="nx">d</span><span class="p">[</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="p">]]</span> <span class="o">=</span> <span class="p">{}</span>
	<span class="p">}</span>
	<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">d</span><span class="p">[</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="p">]][</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span> <span class="o">===</span> <span class="err">“</span><span class="kc">undefined</span><span class="err">”</span><span class="p">){</span>
		<span class="nx">d</span><span class="p">[</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="p">]][</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="nx">d</span><span class="p">[</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="p">]][</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">d</span><span class="p">);</span>
<span class="c1">// { A: { G: 3, C: 1 }, G: { A: 3 }, C: { G: 1 } }</span></code></pre></figure></p>

<p>Now let’s have a look at this neat version with <code class="language-plaintext highlighter-rouge">defaultdict</code>.
Note that we can save both ifs with which we have to check for the existence and initialization.</p>

<p><figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="kd">var</span> <span class="nx">seq</span> <span class="o">=</span> <span class="err">“</span><span class="nx">AGAGACGAG</span><span class="err">”</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">defaultdict</span><span class="p">(()</span><span class="o">=&amp;</span><span class="nx">gt</span><span class="p">;</span><span class="nx">defaultdict</span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&amp;</span><span class="nx">lt</span><span class="p">;</span> <span class="nx">seq</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">){</span>
	<span class="nx">d</span><span class="p">[</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="p">]][</span><span class="nx">seq</span><span class="p">[</span><span class="nx">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">d</span><span class="p">);</span>
<span class="c1">// { A: { G: 3, C: 1 }, G: { A: 3 }, C: { G: 1 } }</span></code></pre></figure></p>

<p>Even the Python code is a bit longer!</p>

<p><figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">seq</span> <span class="o">=</span> <span class="err">“</span><span class="n">AGAGACGAG</span><span class="err">”</span><span class="p">;</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">int</span><span class="p">))</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">seq</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">):</span>
    <span class="n">d</span><span class="p">[</span><span class="n">seq</span><span class="p">[</span><span class="n">i</span><span class="p">]][</span><span class="n">seq</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">print</span><span class="p">({</span><span class="n">k</span><span class="p">:</span><span class="nb">dict</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">d</span><span class="p">.</span><span class="n">items</span><span class="p">()})</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">h1</span> <span class="nb">id</span><span class="o">=</span><span class="s">"g-a-3-c-g-1-a-g-3-c-1"</span><span class="o">&gt;</span><span class="p">{</span><span class="err">‘</span><span class="n">G</span><span class="err">’</span><span class="p">:</span> <span class="p">{</span><span class="err">‘</span><span class="n">A</span><span class="err">’</span><span class="p">:</span> <span class="mi">3</span><span class="p">},</span> <span class="err">‘</span><span class="n">C</span><span class="err">’</span><span class="p">:</span> <span class="p">{</span><span class="err">‘</span><span class="n">G</span><span class="err">’</span><span class="p">:</span> <span class="mi">1</span><span class="p">},</span> <span class="err">‘</span><span class="n">A</span><span class="err">’</span><span class="p">:</span> <span class="p">{</span><span class="err">‘</span><span class="n">G</span><span class="err">’</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="err">‘</span><span class="n">C</span><span class="err">’</span><span class="p">:</span> <span class="mi">1</span><span class="p">}}</span><span class="o">&lt;/</span><span class="n">h1</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span></code></pre></figure></p>

<h2 id="where-to-go">Where to go</h2>

<p>Proxies are already implemented in Edge, Firefox and Chrome (&gt;=49) and for
Node.js one can shim them.</p>

<p>↪ Have fun <a href="https://github.com/wilzbach/defaultdict2">coding</a> or check out the <a href="http://jsbin.com/fiqecu/edit?js,console">live demo</a>!</p>

]]></content>
  </entry>
  
</feed>
