<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title><![CDATA[PhiLhoSoft Technical Blog]]></title>
  
  <link href="/atom.xml" rel="self"/>
  <link href="http://PhiLhoSoft.github.io/"/>
  <updated>2016-06-04T22:18:49.173Z</updated>
  <id>http://PhiLhoSoft.github.io/</id>
  
  <author>
    <name><![CDATA[Philippe Lhoste (aka. PhiLho, PhiLhoSoft for GitHub & Twitter)]]></name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title><![CDATA[Multi-selection in lists]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/Multi-selection-in-lists/"/>
    <id>http://PhiLhoSoft.github.io/Programming/Multi-selection-in-lists/</id>
    <published>2016-05-14T16:08:00.000Z</published>
    <updated>2016-06-04T22:18:49.173Z</updated>
    <content type="html"><![CDATA[<h1 id="multi-selection-in-lists">Multi-selection in lists</h1>
<p>Having to implement range selection in lists in an application at work, I did a little survey of what is done, and was surprised that while the bases are the same for all lists, the more advanced selection modes vary a lot.</p>
<p>Note: by &#x201C;list&#x201D;, I mean the control displaying a list of items, not some kind of collection / data structure.</p>
<img src="/images/Multi-selection.png" title="Multi-selection in Windows Explorer " alt="Multi-selection in Windows Explorer">
<a id="more"></a>
<p>In our AngularJS application, we often display lists of things, in the form of rows of items, spawning several columns, each column showing some specific information from the item.<br>
For this, we use the ag-Grid component.<br>
Sometime, we need to select several items (lines) at once.<br>
Surprisingly, ag-Grid support, out of the box, is quite lacunar: we can select several items, one by one, with Ctrl+click.<br>
By default, we cannot even deselect an item! We have to activate an option for that.<br>
And we cannot do a range selection&#x2026;</p>
<p>Fortunately, the grid has a rather rich selection API, so it is quite easy to supply the missing feature.<br>
And in an <a href="https://github.com/ceolter/ag-grid/issues/369">issue of the ag-Grid repository</a>, somebody provided a base implementation of the range selection feature.</p>
<p>I was a bit surprised to see the implementation was a bit lacunar and doing some things in a surprising way. So I checked how it is done in a number of popular applications, and found out the implementations differed a lot! And that implementation was actually mimicking the behavior of Qt lists.</p>
<h2 id="a-quick-survey">A quick survey</h2>
<p>The applications I checked are:</p>
<ul>
<li>The standard Windows list view component, the one I am the most familiar with. Used as SysListView32 in a number of applications, including the former Windows Explorer. This one now uses a more modern component, but still react the same.</li>
<li>The list of mails in Thunderbird.</li>
<li>The list of changelists in the P4V application: the Perforce visual editor, written in Qt. Not sure if it is typical of Qt in general, or if it uses an implementation specific to Perforce. Well, I found out that VLC shows its playlist in a similar component (QtWidget) and behaves the same.</li>
<li>The HTML multi-selection <code>select</code> tag, showing a list: tested on latest Firefox, Chrome and in IE9-11, on Windows.</li>
</ul>
<p>Reminder about the latter: it looks like</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">select</span> <span class="attribute">name</span>=<span class="value">&quot;select&quot;</span> <span class="attribute">multiple</span> <span class="attribute">size</span>=<span class="value">10</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="title">option</span> <span class="attribute">value</span>=<span class="value">&quot;v1&quot;</span>&gt;</span>Value A<span class="tag">&lt;/<span class="title">option</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="title">option</span> <span class="attribute">value</span>=<span class="value">&quot;v2&quot;</span> <span class="attribute">selected</span>&gt;</span>Value B<span class="tag">&lt;/<span class="title">option</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="title">option</span> <span class="attribute">value</span>=<span class="value">&quot;v3&quot;</span>&gt;</span>Value C<span class="tag">&lt;/<span class="title">option</span>&gt;</span></span><br><span class="line">  ...</span><br><span class="line">  <span class="tag">&lt;<span class="title">option</span> <span class="attribute">value</span>=<span class="value">&quot;v12&quot;</span>&gt;</span>Value L<span class="tag">&lt;/<span class="title">option</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">select</span>&gt;</span><span class="tag">&lt;/<span class="title">select</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>and can be tested in sites like <a href="http://jsFiddle.net">jsFiddle.net</a>.</p>
<p>Things all lists implement the same:</p>
<ul>
<li>Single click: deselect all, select clicked row</li>
<li>Ctrl+click: add clicked row to selection, if deselected; otherwise, remove it from the selection.</li>
</ul>
<p>Shift+click: this is where things start to diverge! It always select the range of lines between the last click and the currently clicked row. But:</p>
<ul>
<li>in Windows Explorer (WExp), it starts by deselecting all other rows. Idem in the multiple select implementation of all browsers and Thunderbird.</li>
<li>in Qt (Perforce / VLC), it adds the new range to the existing selection. It was also the behavior of the implementation I found.</li>
</ul>
<p>Ctrl+Shift+click is not universally implemented. Actually, I did a little survey in a programmer group on Google+, and with over 80 answers (OK, that&#x2019;s not much), 20 % of them told they don&#x2019;t know how to use Ctrl+Shift+click&#x2026;<br>
In Qt, it just works as Shift+click.<br>
In Thunderbird, Firefox&#x2019; implementation of multiple select, and Chrome&#x2019;s one too, it selects the range too, but it is added to the current selection. Just like the previous ones&#x2026;</p>
<p>In Windows Explorer and multiple select in IE, it does that, too. But not only. If your last click (a Ctrl+click, necessarily) deselected an item, then the Ctrl+Shift+click deselects the range, instead of selecting it.<br>
It is powerful and flexible!</p>
<h2 id="keyboard-behavior">Keyboard behavior</h2>
<p>I haven&#x2019;t implemented yet, but I also checked the possibilities of selection with the keyboard: it is important for accessibility purpose, but it can be also useful in general.</p>
<p>When the list has the focus, all implementations move the selection with up &amp; down arrows (UDA).<br>
Likewise, all of them extends the selection from the current position with Shift+UDA.</p>
<p>Now, if you do Ctrl+UDA, WExp, Qt, Firefox and Thunderbird moves the focus, highlighting the current row (with focus) with a small border.<br>
Chrome just deselects all and selects the target row, ie. it ignores the Ctrl modifier.<br>
Curiously, IE behaves differently than WExp, for once: it keeps the selection unchanged, but moves the scrollbar (if any).</p>
<p>The implementations moving the focus then allow to select or deselect the current row with Ctrl+space. Or even just space in some cases.<br>
Upon doing Ctrl+Shift+UDA, only Firefox extends the selection from the current position to the new one.<br>
Curiously, Windows Explorer extends the selection to the new position.<br>
Qt just moves the focus.</p>
<h2 id="implementation">Implementation</h2>
<p>The implementation is rather simple, actually.<br>
Note I give it as it was done, with the ag-Grid API, but in the main function, I abstracted away some of it, and the remainder is easy to understand, so the logic can be adapted to another API.</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// gridOptions are specific to ag-Grid.</span></span><br><span class="line"><span class="comment">// handleCtrlShift: if true (default), handle Ctrl+Shift+click as described above.</span></span><br><span class="line"><span class="comment">// Otherwise, only reacts to Ctrl+click and Shift+click</span></span><br><span class="line"><span class="comment">// exclude, if defined, is a function telling if the given row tells if the click must be handled as a selection.</span></span><br><span class="line">service.addShiftRangeSelect = <span class="function"><span class="keyword">function</span><span class="params">(gridOptions, handleCtrlShift, exclude)</span></span><br><span class="line"></span>{</span><br><span class="line">    <span class="keyword">if</span> (handleCtrlShift === <span class="literal">undefined</span>)</span><br><span class="line">    {</span><br><span class="line">        handleCtrlShift = <span class="literal">true</span>; <span class="comment">// Let&apos;s make it the default! More powerful... :-)</span></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// One time init, depending on ag-Grid version (3 or 4)</span></span><br><span class="line">    service._buildPortableSelectApi(gridOptions);</span><br><span class="line">    <span class="comment">// Sets to options consistent with the wanted result</span></span><br><span class="line">    gridOptions.rowSelection = <span class="string">&apos;multiple&apos;</span>;</span><br><span class="line">    gridOptions.suppressRowClickSelection = <span class="literal">true</span>; <span class="comment">// No interferences</span></span><br><span class="line">    <span class="comment">// The core logic</span></span><br><span class="line">    gridOptions.onRowClicked = <span class="function"><span class="keyword">function</span><span class="params">(row)</span></span><br><span class="line">    </span>{</span><br><span class="line">        <span class="keyword">if</span> (_.isFunction(exclude) &amp;&amp; exclude(row))</span><br><span class="line">            <span class="keyword">return</span>; <span class="comment">// Don&apos;t handle this click (eg. on editable cells)</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (gridOptions.customSelection.isSelected === <span class="literal">undefined</span>)</span><br><span class="line">        {</span><br><span class="line">            <span class="comment">// One time init, use row&apos;s API to tell the version to use</span></span><br><span class="line">            gridOptions.customSelection.selectVersion(row);</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// Keep track of last click</span></span><br><span class="line">        <span class="keyword">var</span> lastSelectedRow = gridOptions.customSelection.lastSelectedRow;</span><br><span class="line">        <span class="keyword">var</span> shiftKey = row.event.shiftKey,</span><br><span class="line">            ctrlKey = row.event.ctrlKey;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// If modifier keys aren&apos;t pressed then only select the row that was clicked</span></span><br><span class="line">        <span class="keyword">if</span> (!shiftKey &amp;&amp; !ctrlKey)</span><br><span class="line">        {</span><br><span class="line">            gridOptions.customSelection.setSelected(row.node, <span class="literal">true</span>, <span class="literal">true</span>);</span><br><span class="line">            gridOptions.customSelection.select = <span class="literal">true</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// If modifier keys are used and there was a previously selected row</span></span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (lastSelectedRow !== <span class="literal">undefined</span> || ctrlKey &amp;&amp; !shiftKey)</span><br><span class="line">        {</span><br><span class="line">            <span class="comment">// Select a block of rows</span></span><br><span class="line">            <span class="keyword">if</span> (shiftKey &amp;&amp; !ctrlKey)</span><br><span class="line">            {</span><br><span class="line">                <span class="keyword">if</span> (handleCtrlShift)</span><br><span class="line">                {</span><br><span class="line">                    gridOptions.api.deselectAll();</span><br><span class="line">                }</span><br><span class="line">                gridOptions.customSelection.setRangeSelected(row.rowIndex, lastSelectedRow.rowIndex, <span class="literal">true</span>);</span><br><span class="line">                gridOptions.customSelection.select = <span class="literal">true</span>;</span><br><span class="line">            }</span><br><span class="line">            <span class="comment">// Select one more row</span></span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (ctrlKey &amp;&amp; !shiftKey)</span><br><span class="line">            {</span><br><span class="line">                <span class="keyword">if</span> (gridOptions.rowDeselection)</span><br><span class="line">                {</span><br><span class="line">                    <span class="keyword">var</span> select = !gridOptions.customSelection.isSelected(row.node);</span><br><span class="line">                    gridOptions.customSelection.setSelected(row.node, select);</span><br><span class="line">                    gridOptions.customSelection.select = select;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                {</span><br><span class="line">                    gridOptions.customSelection.setSelected(row.node, <span class="literal">true</span>);</span><br><span class="line">                    gridOptions.customSelection.select = <span class="literal">true</span>;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (handleCtrlShift)</span><br><span class="line">            {</span><br><span class="line">                gridOptions.customSelection.setRangeSelected(row.rowIndex, lastSelectedRow.rowIndex, gridOptions.customSelection.select);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// Store the recently clicked row for future use</span></span><br><span class="line">        gridOptions.customSelection.lastSelectedRow = row;</span><br><span class="line">    };</span><br><span class="line">    gridOptions.onBeforeSortChanged = <span class="function"><span class="keyword">function</span><span class="params">()</span></span><br><span class="line">    </span>{</span><br><span class="line">        <span class="comment">// Be sure to clear out the row selections on sort change since row indexes will change</span></span><br><span class="line">        gridOptions.api.deselectAll();</span><br><span class="line">        gridOptions.customSelection.lastSelectedRow = <span class="literal">undefined</span>;</span><br><span class="line">    };</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>The compatibility layer.</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Make the above code to work with current (v4) or previous (v3) version of ag-Grid.</span></span><br><span class="line">service._buildPortableSelectApi = <span class="function"><span class="keyword">function</span>(<span class="params">gridOptions</span>)</span><br><span class="line"></span>{</span><br><span class="line">    gridOptions.customSelection = {};</span><br><span class="line"></span><br><span class="line">    gridOptions.customSelection.selectVersion = <span class="function"><span class="keyword">function</span>(<span class="params">node</span>)</span><br><span class="line">    </span>{</span><br><span class="line">        <span class="keyword">if</span> (node.isSelected) <span class="comment">// v.4 specific</span></span><br><span class="line">        {</span><br><span class="line">            gridOptions.customSelection.isSelected = gridOptions.customSelection.forV4.isSelected;</span><br><span class="line">            gridOptions.customSelection.setSelected = gridOptions.customSelection.forV4.setSelected;</span><br><span class="line">            gridOptions.customSelection._setRangeSelected = gridOptions.customSelection.forV4._setRangeSelected;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">        {</span><br><span class="line">            gridOptions.customSelection.isSelected = gridOptions.customSelection.forV3.isSelected;</span><br><span class="line">            gridOptions.customSelection.setSelected = gridOptions.customSelection.forV3.setSelected;</span><br><span class="line">            gridOptions.customSelection._setRangeSelected = gridOptions.customSelection.forV3._setRangeSelected;</span><br><span class="line">        }</span><br><span class="line">    };</span><br><span class="line"></span><br><span class="line">    gridOptions.customSelection.setRangeSelected = <span class="function"><span class="keyword">function</span>(<span class="params">startIndex, endIndex, selected</span>)</span><br><span class="line">    </span>{</span><br><span class="line">        <span class="comment">// Get our start and end indexes correct</span></span><br><span class="line">        <span class="keyword">if</span> (startIndex &gt; endIndex)</span><br><span class="line">        {</span><br><span class="line">            <span class="keyword">var</span> si = startIndex;</span><br><span class="line">            startIndex = endIndex;</span><br><span class="line">            endIndex = si;</span><br><span class="line">        }</span><br><span class="line">        gridOptions.customSelection._setRangeSelected(startIndex, endIndex, selected);</span><br><span class="line">    };</span><br><span class="line"></span><br><span class="line">    gridOptions.customSelection.forV4 =</span><br><span class="line">    {</span><br><span class="line">        isSelected: <span class="function"><span class="keyword">function</span>(<span class="params">node</span>) </span>{ <span class="keyword">return</span> node.isSelected(); },</span><br><span class="line">        setSelected: <span class="function"><span class="keyword">function</span>(<span class="params">node, selected, clearSelection</span>)</span><br><span class="line">        </span>{</span><br><span class="line">            node.setSelected(selected, clearSelection);</span><br><span class="line">        },</span><br><span class="line">        _setRangeSelected: <span class="function"><span class="keyword">function</span>(<span class="params">startIndex, endIndex, selected</span>)</span><br><span class="line">        </span>{</span><br><span class="line">            gridOptions.api.forEachNode(<span class="function"><span class="keyword">function</span> <span class="title">__handleNode</span>(<span class="params">node</span>)</span><br><span class="line">            </span>{</span><br><span class="line">                <span class="keyword">if</span> (node.rowIndex &gt;= startIndex &amp;&amp; node.rowIndex &lt;= endIndex)</span><br><span class="line">                {</span><br><span class="line">                    gridOptions.api.selectNode(node, selected, node.rowIndex &lt; endIndex);</span><br><span class="line">                }</span><br><span class="line">            });</span><br><span class="line">        },</span><br><span class="line">    };</span><br><span class="line"></span><br><span class="line">    gridOptions.customSelection.forV3 =</span><br><span class="line">    {</span><br><span class="line">        isSelected: <span class="function"><span class="keyword">function</span>(<span class="params">node</span>) </span>{ <span class="keyword">return</span> gridOptions.api.isNodeSelected(node); },</span><br><span class="line">        setSelected: <span class="function"><span class="keyword">function</span>(<span class="params">node, selected, clearSelection</span>)</span><br><span class="line">        </span>{</span><br><span class="line">            <span class="keyword">if</span> (selected)</span><br><span class="line">            {</span><br><span class="line">                gridOptions.api.selectNode(node, !clearSelection);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">            {</span><br><span class="line">                gridOptions.api.deselectNode(node);</span><br><span class="line">            }</span><br><span class="line">        },</span><br><span class="line">        _setRangeSelected: <span class="function"><span class="keyword">function</span>(<span class="params">startIndex, endIndex, selected</span>)</span><br><span class="line">        </span>{</span><br><span class="line">            <span class="keyword">var</span> operation = (selected ? gridOptions.api.selectIndex : gridOptions.api.deselectIndex).bind(gridOptions.api);</span><br><span class="line">            <span class="comment">// (De)select all the rows between the previously clicked row and the newly clicked row</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">var</span> i = startIndex; i &lt;= endIndex; i++)</span><br><span class="line">            {</span><br><span class="line">                operation(i, <span class="literal">true</span>, i &lt; endIndex); <span class="comment">// multi &amp; suppressEvents: on last row, we let the event to pop up</span></span><br><span class="line">            }</span><br><span class="line">        },</span><br><span class="line">    };</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>Here is an example of <code>exclude</code> function definition:</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">excludeEditableCells</span><span class="params">(row)</span></span><br><span class="line"></span>{</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">isEditable</span><span class="params">(className)</span></span><br><span class="line">    </span>{</span><br><span class="line">        <span class="keyword">return</span> className === <span class="string">&apos;ag-grid-editable&apos;</span>;</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">if</span> (row.event.target.tagName === <span class="string">&apos;OPTION&apos;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>; <span class="comment">// User clicked on an option of the drop-down in Firefox and IE: don&apos;t take this in account, to avoid deselecting rows.</span></span><br><span class="line">    <span class="keyword">var</span> editableCell = _.some(row.event.target.classList, isEditable); <span class="comment">// One of the classes is the mark of an editable cell</span></span><br><span class="line">    <span class="keyword">if</span> (editableCell)</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>; <span class="comment">// We don&apos;t select when clicking on an editable cell, as the click triggers the editing mode</span></span><br><span class="line">    <span class="comment">// Check with parent, if clicking on span or select, etc.</span></span><br><span class="line">    editableCell = _.some(row.event.target.parentNode.classList, isEditable);</span><br><span class="line">    <span class="keyword">return</span> editableCell;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
]]></content>
    <summary type="html">
    <![CDATA[How to do multi-selection in a list of items]]>
    
    </summary>
    
      <category term="Component" scheme="http://PhiLhoSoft.github.io/tags/component/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/tags/javascript/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="UI" scheme="http://PhiLhoSoft.github.io/tags/ui/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="UI" scheme="http://PhiLhoSoft.github.io/categories/programming/ui/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[How I use MobX 2 in an AngularJS 1 application]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/AngularJS-1-and-MobX-2/"/>
    <id>http://PhiLhoSoft.github.io/Programming/AngularJS-1-and-MobX-2/</id>
    <published>2016-04-29T22:00:00.000Z</published>
    <updated>2016-06-04T22:17:08.564Z</updated>
    <content type="html"><![CDATA[<h1 id="how-i-use-mobx-2-in-an-angularjs-1-application">How I use MobX 2 in an AngularJS 1 application</h1>
<p>MobX is a library simplifying state management by using functional reactive principles.<br>
It manages dependencies between values, somehow like a spreadsheet does with its cells: if the value of a cell changes, other cells depending on the first one can change too, in a cascading way.</p>
<p>The manual of MobX can be read at <a href="https://mobxjs.github.io/mobx/refguide/">MobX, Simple, scalable state management</a>.<br>
It is a comprehensive guide, rather dense (worth reading again after experimenting with the library&#x2026;) but clear and informative.</p>
<p>I used it in an AngularJS 1 application, to manage state of controllers (components), so in a rather local and isolated way.<br>
That&#x2019;s just one way of using it, which I explain below.</p>
<img src="/images/MobX_logo.png" title="MobX logo" alt="MobX">
<a id="more"></a>
<h2 id="why-i-needed-something-like-mobx">Why I need(ed) something like MobX</h2>
<p>On my second AngularJS project (the third made in the company), we have some quite complex state management: we have a main view / controller showing a graph (nodes with relations), with a toolbar, whose buttons are disabled depending on user actions (changing the graph), data loading (fetching graph data), state in the data (is graph processed on server side), etc.<br>
We also have two dialog boxes (one calling the other) with controls and buttons, also interacting, depending on user choices, state of / in data, etc.<br>
We have to enable / disable these controls, and also set tooltips or messages explaining why they are disabled, so that user can do proper actions.<br>
All this led to a rather complex state management, done in a classical way, with booleans and intermediary data structures, and functions called to update dependencies between these variables.<br>
We managed this state with a bunch of booleans (is this control disabled?) set on the fly in a ad hoc way (uh, I need this flag, let&#x2019;s create it there) on the scope (the controller instance), and by calling functions to show appropriate tooltips / messages in all places where the state changes.<br>
Note: by &#x201C;show tooltips / messages&#x201D;, I actually mean &#x201C;change their values&#x201D;, as AngularJS&#x2019; binding is managing to display them.</p>
<p>At the end, the code was a bit messy, with state changing everywhere, forgotten cases, having to track usage to add the missing ones, sometime inconsistent or unclear usage, etc.</p>
<p>Then I saw a tweet mentioning MobX. I had a look at the site, and the description looked like a good fit to my problem.<br>
A superficial look could lead to think it was made for React with an ES6 syntax, but reading on, I found they are actually framework-agnostic (React-specific stuff is separate) and totally compatible with ES5.</p>
<h2 id="context">Context</h2>
<p>I use the &#x201C;controller as&#x201D; pattern in this Angular application, and I assign <code>this</code> to the <code>ctrl</code> variable at the start of the controllers.<br>
So I refer to <code>ctrl.xyz</code> for the controller variables, those visible from the related template.<br>
I also have some variables with same lifetime than the controller, but not needing to be visible on the view. By convention, we name them <code>ctrl._xyz</code>, the underscore meaning &#x201C;private&#x201D;&#x2026;<br>
If you don&#x2019;t use &#x201C;controller as&#x201D; pattern (but you should!), you can mentally replace <code>ctrl</code> with <code>$scope</code>.</p>
<p>I tend to name functions that are traditionally anonymous, like iteratees of Lodash functions, callbacks defined in function calls, etc.<br>
Ie. instead of doing <code>_.map(circles, function (c) { return TWO_PI * c.radius; ];</code> I write <code>_.map(circles, function __toPerimeter(c) { return TWO_PI * c.radius; ];</code>.<br>
This is generally a good practice, as it shows the intent of the transformation, and these names can show up in stack traces in debuggers, etc.<br>
It is even more important with MobX, because it keeps track of these names and this allows an easier debugging of its mechanisms.<br>
I use a double underscore as prefix to help distinguishing these small functions from the others when my IDE (Atom) lists them.</p>
<h2 id="my-usage-of-mobx">My usage of MobX</h2>
<p>I have two objects on the controller, related to the view, ie. referenced in the template:</p>
<ul>
<li>As input, <code>ctrl.viewModel</code> contains the models of form inputs (text input, radio-buttons, check boxes, select / drop-down, etc.), referenced by <code>ng-model</code> directives. Ie. they display their current value and can be changed by the user.</li>
<li>As output, <code>ctrl.view</code> contains the read-only view values, used in the template to display these values.</li>
</ul>
<p>Between them, I can have some intermediary objects, eg. <code>ctrl._model</code> for data structures, <code>ctrl._internal</code> for flags, etc.<br>
These objects, and <code>ctrl.viewModel</code>, are observable by wrapping them in a <code>mobx.observable</code> call.<br>
MobX transforms (recursively) each field (property) of these objects to observable values: that&#x2019;s simpler than calling <code>observable</code> on each field.<br>
If you use a more OOP approach, as described in the docs, you might want finer control on how some fields are observable and some are not.<br>
Here, I just use these plain objects to group together observable values.</p>
<p>These observables can be simple values set by the code (string, number, boolean); or arrays (each value is observed), or objects (each property is observed). It is, by default, recursive: an array of objects has each field observed.<br>
Observable values are replaced by MobX by a pair of accessors, ES5&#x2019;s getters and setters, or specialized objects, like ObservableArray, mimicking the behavior of real arrays, but observing each entry and operation (like <code>splice</code>).<br>
If the property of an observable object is assigned a new value, MobX makes it observable too.<br>
It doesn&#x2019;t do it for added properties, so they must be declared from the start, which is a good thing: no more variables added &#x201C;on the fly&#x201D; in the middle of the code.<br>
If you use an object is a map (values indexed by string keys), MobX provides an observable map to get you covered.</p>
<p>In some cases, I observe arrays to watch insertions / deletions: I don&#x2019;t change the objects it has inside, which generally doesn&#x2019;t change anyway. To improve performances (and memory consumption) and ease debugging, I use the <code>asFlat</code> modifier.</p>
<p>The observed values can be also be functions without parameters: they are called when the field is read.<br>
The function acts as a getter, and can compute a value from other values.<br>
If some of these values are observables, MobX invokes their getter, which in turn can invoke other getters, etc.</p>
<p>Instead of a direct computation from other values, the function can call a transformer, created via&#x2026; <code>mobx.createTransformer</code>.<br>
A transformer takes one (and only one) observable value as entry, and must return a new value computed from the parameter, and possibly from other observable values.<br>
As we use properties from observables, we invoke their getters. MobX then keeps track of these sub-observable objects.<br>
When a setter is invoked on one (or more) these objects, MobX knows it has to recompute the result of the transformer.<br>
Otherwise, since input hasn&#x2019;t changed, it knows output didn&#x2019;t change either&#x2020;, so it can return the previous value, said to be memoized. This results in a much faster response, particularly if the operation iterates on large collections.<br>
&#x2020; Obviously, the function must be deterministic (pure, as <a href="/Programming/Functional-programming-introduction/">functional programming</a> aficionados say): for a given input, it always returns the same output. Don&#x2019;t put <code>random()</code>, <code>getTime()</code> or I/O result in there!</p>
<p>The above is an over-simplified description how MobX works. The exact mechanism is described in the article <a href="https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254">Becoming fully reactive: an in-depth explanation of MobX</a>. MobX has optimizations making all this working very fast&#x2026;<br>
Beside, as the core mechanism is based on accessors, it is intrinsically static: no need to scan all the observed variables / entries / properties regularly to check if there is a change, the sole fact to get or set a value is enough to trigger the mechanism. The other advantage is synchronicity and atomicity: changes don&#x2019;t have to wait for a &#x201C;digest&#x201D; cycle, and all changes are applied at once: no inconsistent intermediary state.</p>
<p>Back to my implementation: <code>ctrl.view</code> is not an observable. It is already watched / bound by Angular, and I prefer to keep it &#x201C;static&#x201D;, assigning new values if their dependencies change.<br>
For this, I use <code>mobx.autorun</code> which is used to do side-effects when an observable value inside it changes.<br>
My side-effects here are to assign a new value to <code>ctrl.view</code> properties&#x2026; I do that only for computation-intensive value evaluations (extracting data from collections, etc.), using transformers to memoize the results.<br>
Actually, it corresponds to described side effects, like disabling a control, selecting an entry in a list, etc. Because it is Angular, instead of calling <code>control.setEnabled(true / false)</code> or <code>combo.select(index)</code>, we assign the values to bound variables: <code>ctrl.control.enabled = true / false</code> or <code>combo.selection = combo.model[index]</code>. But basically, that&#x2019;s the same thing.</p>
<p>As <code>createTransformer</code> is a bit heavy-handed (needs some boilerplate code, accepts only one parameter), for lighter evaluations (no iterations) I use the ES5 getter syntax, function evaluated each time the property is read: <code>var o = { get foo() { return someValue * 2; } }; var x = o.foo; // Calls the getter and returns twice someValue</code><br>
I formerly used <code>mobx.computed</code> for that, but I am not sure if it brings any advantage here&#x2026;</p>
<p>In other words, I went from</p>
<pre><code>ctrl.view =
{
    saveDisabled: mobx.computed(function saveDisabled()
    {
        return ctrl._internal.noItems || !ctrl._internal.hasCommonStuff || ctrl._internal.isStarted;
    }),
};
</code></pre>
<p>to</p>
<pre><code>ctrl.view =
{
    get saveDisabled()
    {
        return ctrl._internal.noItems || !ctrl._internal.hasCommonStuff || ctrl._internal.isStarted;
    },
};
</code></pre>
<p>Note: transformations must be used inside a reaction like <code>@observer</code> or <code>autorun</code>. They also work if they are part of the dependency graph pulled from an <code>autorun</code>, as done above (view depending on observable objects).<br>
Maybe the <code>computed</code> version allows such triggering, if needed.</p>
<h2 id="potential-issues-points-to-be-aware-of">Potential issues / points to be aware of</h2>
<h3 id="avoid-to-assign-null-to-observables">Avoid to assign null to observables</h3>
<p>That&#x2019;s a general advice in computing: instead of using <code>null</code>, use a &#x201C;null object&#x201D;, a real &#x201C;inert&#x201D; object . Like an empty object <code>{}</code>, an empty array <code>[]</code> or similar.<br>
MobX will throw when you assign <code>null</code> to an observable, and will tell you that you have an infinite loop in your dependencies, so these null objects are better here.</p>
<h3 id="mobx-observable-array">MobX observable array</h3>
<p>It is a special object mimicking JS arrays, but observing each entry and watching each operation. It is a bit annoying to examine when debugging, but that&#x2019;s a minor issue.</p>
<p>One problem is that some libraries will choke on this &#x201C;false&#x201D; array. For example, [Lodash]/Programming/Using-Lodash-for-fun-and-profit/)&apos;s <code>_.clone</code> or <code>_.cloneDeep</code> fails to work on it.<br>
For the former, you can do <code>observableArray.slice(0)</code> which makes a plain array copy of the array. But the objects inside are still those observed in the original array, and thus are still observable.</p>
<p>In my case, I observed the array only to see if it is not empty, which is a bit overkill&#x2026;</p>
<pre><code>ctrl._model = mobx.observable(
{
    stuffList: [],
});
</code></pre>
<p>Easy way out: I tell MobX not to observe the objects themselves.</p>
<pre><code>ctrl._model = mobx.observable(
{
    stuffList: mobx.asFlat([]), // Observe array, not objects inside it
});
</code></pre>
<p>Assigning later the real array to <code>stuffList</code> preserved the <code>asFlat</code> modifier.</p>
<p>Basically, if you are interested in changes in the array (add / remove items), but not in the objects inside them (which might not change at all!), <code>asFlat</code> is good to use (can even improve performance / reduce memory usage, which doesn&#x2019;t hurt&#x2026;).</p>
<h2 id="conclusion">Conclusion</h2>
<p>It might seem strange to use MobX with AngularJS, whereas the latter can <code>$watch</code> value changes or invoke functions from the template.<br>
MobX has two advantages here:</p>
<ul>
<li>It is synchronous, while AngularJS computes watches only in a digest cycle. This ensures there is no &#x201C;dirty&#x201D; state, with intermediary values, or values changed and not yet updated in the display.</li>
<li>It can memoize results. This avoids complex collection processing on each cycle, these are done only when the collections actually change.</li>
</ul>
<p>This avoids explicit <code>$watch</code> (I never use them in controllers anyway), evaluation of functions in templates (like <code>ng-disabled=&quot;vm.isFooDisabled()&quot;</code>) or manual calls to <code>ctrl.updateState()</code> in the controller code, which can be forgotten or done too much.<br>
MobX allows to describe a graph of dependencies, and to ensure it is always up to date.</p>
<p>For complex changes, like changing several values in an array, we can also use transactions, minimizing the recalculations by batching them and computing the result at the end.</p>
<p>MobX is a mature library, used in large applications, and it proved to be very efficient.<br>
It is flexible: some applications use it to implement the Flux architecture, centralizing all data in one or more data stores, shared among the components; and myself used it locally, in only some controllers, to do a little part of the UI logic.<br>
In other words, it is not an &#x201C;in your face, do it as I said&#x201D; library that imposes its vision of the world (centralized, immutable, with flat data, and so on). It works the way you are familiar with, and it is easy to use for most users, using mutable data, invisible accessors, etc.</p>
]]></content>
    <summary type="html">
    <![CDATA[Presenting MobX 2 in a concrete use case with AngularJS 1]]>
    
    </summary>
    
      <category term="Functional programming" scheme="http://PhiLhoSoft.github.io/tags/functional-programming/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/tags/javascript/"/>
    
      <category term="Library" scheme="http://PhiLhoSoft.github.io/tags/library/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="Reactive programming" scheme="http://PhiLhoSoft.github.io/tags/reactive-programming/"/>
    
      <category term="Tutorial" scheme="http://PhiLhoSoft.github.io/tags/tutorial/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/categories/programming/javascript/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Git .gitignore rules]]></title>
    <link href="http://PhiLhoSoft.github.io/Software/Git-gitignore-rules/"/>
    <id>http://PhiLhoSoft.github.io/Software/Git-gitignore-rules/</id>
    <published>2016-01-08T10:34:00.000Z</published>
    <updated>2016-01-13T23:11:38.628Z</updated>
    <content type="html"><![CDATA[<h1 id="git-gitignore-rules">Git .gitignore rules</h1>
<img src="/images/Git_logo.png" title="Git logo" alt="Git">
<p>The rules are defined in <a href="http://git-scm.com/docs/gitignore">http://git-scm.com/docs/gitignore</a><br>
I won&#x2019;t repeat them here, nor test them all. I will only explore some corner cases, not well explained in the said document&#x2026;</p>
<a id="more"></a>
<h2 id="test">Test</h2>
<p>List all candidates to tracking with <code>git status -u</code>.<br>
x means &#x2018;shown by status&#x2019;, empty means &#x2018;ignored&#x2019;.</p>
<table>
<thead>
<tr>
<th></th>
<th><code>foo</code></th>
<th><code>/foo</code></th>
<th><code>foo/</code></th>
<th><code>f*</code></th>
<th><code>f*/</code></th>
<th><code>*.y</code></th>
<th><code>foo/c.x</code></th>
<th><code>foo/*.y</code></th>
<th><code>**/foo/*.y</code></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>bar/b.y</code></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
<td>x</td>
<td>x</td>
<td>?</td>
</tr>
<tr>
<td><code>bar/foo/a.y</code></td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td>x?</td>
<td></td>
</tr>
<tr>
<td><code>bar/foo/c.x</code></td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td>?</td>
<td>x</td>
<td>?</td>
</tr>
<tr>
<td><code>bar/foo/d.y</code></td>
<td></td>
<td>x</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td>x?</td>
<td></td>
</tr>
<tr>
<td><code>baz/f.y</code></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
<td>x</td>
<td></td>
<td>x</td>
<td>x</td>
<td>?</td>
</tr>
<tr>
<td><code>baz/foo</code></td>
<td></td>
<td>x</td>
<td>x</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>?</td>
</tr>
<tr>
<td><code>baz/nf.x</code></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>foo/a.x</code></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>foo/b.y</code></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td></td>
<td></td>
</tr>
<tr>
<td><code>foo/c.x</code></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>x</td>
<td></td>
<td>x</td>
<td>x</td>
</tr>
</tbody>
</table>
<p>A bit surprised by the <code>foo/c.x</code> and <code>foo/*.y</code> patterns, I can&#x2019;t see in the doc where they say that a pattern with slash and joker is anchored to top.<br>
The last one is probably barely legal. One should keep things simple&#x2026;<br>
Now, let&#x2019;s see the combination of exclude and re-include.</p>
<table>
<thead>
<tr>
<th></th>
<th><code>foo</code></th>
<th><code>bar</code>(1)</th>
<th><code>bar</code></th>
<th><code>bar/*</code></th>
<th><code>bar/foo/*</code></th>
<th><code>bar/foo/*</code></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td><code>!bar/foo</code></td>
<td><code>!bar/foo</code></td>
<td><code>!bar/foo/*</code></td>
<td><code>!bar/foo</code></td>
<td><code>!bar/foo/c.x</code></td>
<td><code>!bar/foo/*.y</code></td>
</tr>
<tr>
<td><code>bar/b.y</code></td>
<td>x</td>
<td></td>
<td>x?</td>
<td></td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>bar/foo/a.y</code></td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td></td>
<td>x</td>
</tr>
<tr>
<td><code>bar/foo/c.x</code></td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td><code>bar/foo/d.y</code></td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td></td>
<td>x</td>
</tr>
<tr>
<td><code>baz/f.y</code></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>baz/foo</code></td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>baz/nf.x</code></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>foo/a.x</code></td>
<td></td>
<td>x</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>foo/b.y</code></td>
<td></td>
<td>x</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
<tr>
<td><code>foo/c.x</code></td>
<td></td>
<td>x</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
</tr>
</tbody>
</table>
<p>(1) and <code>/bar</code> and <code>bar/</code></p>
<p>I was confused by the re-include behavior, the post at <a href="http://stackoverflow.com/questions/2820255/how-do-negated-patterns-work-in-gitignore">http://stackoverflow.com/questions/2820255/how-do-negated-patterns-work-in-gitignore</a> clarified the issue.<br>
We need to add a joker to the exclude path so that re-include paths are examined.<br>
Recursively:</p>
<table>
<thead>
<tr>
<th></th>
<th><code>bar/*</code></th>
<th><code>bar/foo/*</code></th>
<th><code>bar/foo/*</code></th>
<th><code>bar/*</code></th>
<th><code>bar/foo/*</code></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td><code>!bar/foo</code></td>
<td><code>!bar/foo/c.x</code></td>
<td><code>!bar/foo/*.y</code> (2)</td>
<td><code>!bar/foo</code></td>
<td><code>!bar/foo/*.y</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td><code>bar/foo/*</code></td>
<td><code>!bar/foo/zab/</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td><code>!bar/foo/zab</code></td>
<td><code>bar/foo/zab/*</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><code>!bar/foo/zab/*.y</code></td>
</tr>
<tr>
<td><code>bar/b.y</code></td>
<td></td>
<td>x</td>
<td>x</td>
<td></td>
<td>x</td>
</tr>
<tr>
<td><code>bar/foo/a.y</code></td>
<td>x</td>
<td></td>
<td>x</td>
<td></td>
<td>x</td>
</tr>
<tr>
<td><code>bar/foo/c.x</code></td>
<td>x</td>
<td>x</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><code>bar/foo/d.y</code></td>
<td>x</td>
<td></td>
<td>x</td>
<td></td>
<td>x</td>
</tr>
<tr>
<td><code>bar/foo/zab/e.x</code></td>
<td>x</td>
<td>x</td>
<td></td>
<td>x</td>
<td></td>
</tr>
<tr>
<td><code>bar/foo/zab/f.y</code></td>
<td>x</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
</tr>
</tbody>
</table>
<p>(2) and <code>!bar/foo/**/*.y</code> and <code>!bar/foo/zab/*.y</code></p>
]]></content>
    <summary type="html">
    <![CDATA[Exploration of some points of .gitignore rules]]>
    
    </summary>
    
      <category term="Command line" scheme="http://PhiLhoSoft.github.io/tags/command-line/"/>
    
      <category term="Git" scheme="http://PhiLhoSoft.github.io/tags/git/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/tags/software/"/>
    
      <category term="Tool" scheme="http://PhiLhoSoft.github.io/tags/tool/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/categories/software/"/>
    
      <category term="Development tools" scheme="http://PhiLhoSoft.github.io/categories/software/development-tools/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[MessagEase (Android keyboard) review]]></title>
    <link href="http://PhiLhoSoft.github.io/Software/MessagEase-Android-keyboard-review/"/>
    <id>http://PhiLhoSoft.github.io/Software/MessagEase-Android-keyboard-review/</id>
    <published>2015-12-17T09:56:00.000Z</published>
    <updated>2016-01-13T23:11:38.678Z</updated>
    <content type="html"><![CDATA[<h1 id="messagease-android-keyboard-review">MessagEase (Android keyboard) review</h1>
<img src="/images/MessagEase_Keyboard.png" width="150" height="150" title="My MessagEase keyboard as exported by the app" alt="MessagEase keyboard">
<p>Most Android keyboards suffer from the same flaw: they mimic traditional typewriter / computer keyboards.<br>
The (only?) advantage is that most users are familiar with it.<br>
The inconveniences are numerous:</p>
<ul>
<li>These keyboards were designed to slow down typing&#x2026; (well, multi-finger typing, but still, they are not intuitive).</li>
<li>People are trained / used to type with several fingers, while on Android you are limited to two, at best.</li>
<li>These keyboards often lack arrow keys, Delete key and multi-key / finger combinations, like shifting to capital, Ctrl+C / Ctrl+V, Ctrl+Backspace to delete a word, etc. To reach some keys (accented chars) and go back to regular typing, you might have to type three or four keys.</li>
<li>Keys are small, particularly on small phones.</li>
</ul>
<p>I thought of a squarish / circular design around a central point, where letters surrounding it would change to make more accessible the letters more likely to follow the previous ones (for a given dictionary).<br>
Idea with a number of caveats, like not relying on muscle memory and needing to know the context in the edited text.</p>
<p>So I searched alternatives (they are numerous!), tried some (disliked swipe-based ones, liked Hacker&#x2019;s Keyboard in its classical category) and finally stumbled upon MessagEase.<br>
I felt it was the right one, even if I expected some learning curve&#x2026; It was close of my idea, but with a fixed layout (for a given language), and it makes the most common letters easier to type than the rarest ones.</p>
<p>Its square design make it look huge, but in practice, with its 4x4 keys, it is not much bigger than a four row traditional keyboard. And you can easily adjust its size to fit your taste / capabilities.<br>
It is very flexible, with tons of settings to adjust finely the look and feel of the keyboard, to adapt it to the needs and tastes of the users. Yet, it has sensible defaults, so it is good out of the box.</p>
<a id="more"></a>
<h1 id="principle">Principle</h1>
<img src="/images/MessagEase_screenshot.png" title="MessagEase keyboard screenshot in the Jota+ editor" alt="MessagEase keyboard screenshot">
<p>The main area of the keyboard is a 3x3 square of keys. Each key (sub-square) has the nine most used letters of the chosen language (aniuortes for French, not far for English). They are typed with a simple tap on them.<br>
The four next most used letters (hbdc) are obtained by sweeping from the central square to a side square. For the next four, the move is from the center to the corners. Then come the reverse moves, from sides or corners to center, providing the eight next letters. The last letter is obtained with a sweep between two sides. Other side to side or to corner moves provide accented letters and punctuation signs.<br>
With some logic making them easier to memorize: lower signs (,.:;) are at the bottom of the keyboard while higher ones (`^&#xB4;) are at the top, and the move follows the direction of the sign.<br>
Numbers are obtained by a special keyboard (or a long press).<br>
Special moves allow to easily reach capital letters: a circular move over the main letters, and a sweep and back for the others. Plus autocapitalization at the beginning of sentences.</p>
<p>The keyboard also provides very convenient special keys: you can cut, copy or paste with a single sweep. A side sweep on the space bar moves the caret by one character. Sweep and back to move by a whole word.<br>
Tap on the backspace to delete the char on left of caret. Sweep to left and back to delete from caret to start of word. Sweep to right to delete the char on right of caret (idem Delete key), sweep and back to right to delete to end of word.</p>
<p>Some characters are obtained via a combination key: oe plus the key gives &#x153;; &lt;&lt; and the key gives &#xAB; (French quote). Etc. `^&#xB4; keys are automatically merged if the previous letter accepts accents (eg. E and &#xB4; gives &#xC9;). Backspace cancels the merging.</p>
<p>There are other shortcuts, like defining sentences to enter with a special gesture, etc.</p>
<p>You can have an area displaying suggesting words completing the one you are typing. For your selected language, of course. You have to install the languages separately.<br>
These are only suggestions, you can ignore them or tap on one to autocomplete the current word. No stupid autocorrection causing so often confusion, embarrassment and fun&#x2026; at your depends! :-)</p>
<h1 id="remarks">Remarks</h1>
<p>The keyboard layout is, by default, adapted to the chosen language, depending on the most often found letters of the language. But as I type as much English than French, I chose to use the same keyboard for both, because learning to use efficiently the keyboard involves memorizing the letter placements and using muscle memory. So having two keyboard layouts would be rather couter-productive (unless you have a better brain than mine&#x2026;), at least for similar languages (eg. latin-based). Of course, English vs. Arabic, for example, is a different problem.<br>
I chose the French keyboard, as it has the accents I need. I don&#x2019;t mind to have a less optimal character layout for English, the frequency of letters isn&#x2019;t so different it makes a huge difference&#x2026; Of course, I have the two dictionaries (for autocompletion) and I appreciate the ease of switching them and the different color coding.</p>
<p>The keyboard has been designed by <a href="https://www.exideas.com/ME/index.php">Edideas</a>.</p>
<h2 id="the-good-parts">The good parts</h2>
<p>When I discovered MessagEase, I thought: &#x201C;Ah! That&#x2019;s the one I was looking for!&#x201D;&#x2026;<br>
It is an ideal keyboard both for typing text and for programmers.</p>
<p>With traditional keyboards, I despised to have to hit three keys to enter a capital, a number or a punctuation sign. And editing capabilities were non-existent, beside trying to tap the caret between two letters.</p>
<p>Despite the initial learning curve, I love to be able to move the caret, delete the char or word on right, delete the previous word, paste quickly&#x2026;</p>
<p>And most characters used in programming are just a sweep away: {} $ [] &amp;| etc. Even the tab character is readily available!<br>
Idem for accented letters, always just a sweep away.</p>
<p>The app is free, without ads. They ask for support, which is well deserved. They also give a free game with various goals, allowing to train, measuring speed, errors and progresses. After some training, I reached a decent speed (much higher than with default keyboard). After some months of using this keyboard (typing articles such as this one in public transports on my tiny old phone), I tried the game again. And I found out I outperformed all my previous results by a large margin! Practice make it perfect. Note that pure speed is really a goal in itself (except for the challenge, of course): I don&#x2019;t type very fast (still reaching the top level of the games), but I don&#x2019;t care as I frequently stop to think what I will type next&#x2026; The real goal is to let the fingers to find the letter gestures by themselves, to avoid hunt-and-type each letter. Ideally, one should be able to type without even seeing the letters on the keyboard. MessagEase has even a &#x201C;blind&#x201D; mode, with a grid without letters&#x2026;</p>
<p>Note: I typed most of the articles of this site on my small phone (a Samsung Galaxy Ace 2) with this keyboard. I doubt I would have managed to do this with a classical keyboard!</p>
<h2 id="the-parts-needing-improvements">The parts needing improvements</h2>
<p>Aka. nitpicking&#x2026; Aka. personal message / remarks to the MessagEase team!</p>
<ul>
<li>There are two shortcuts on the drag up movement on the hand: resize the keyboard and toggle the autocompletion area (word prediction). This is confusing! Actually, the behavior depends if the area is displayed or not. This is not really well explained in the otherwise detailed documentation.</li>
<li>If I type a word with a punctuation sign on the right (eg. adding some words at the end of a sentence), auto-completion is off. Word prediction should ignore characters (in general) after the caret.</li>
<li>Should auto-capitalize after an ellipsis (three dots) or dot following a parenthesis, etc.<br>
Also if there are only spaces, signs (dashes, dots, stars, parentheses, etc.) and number after the start of the line: these probably mark list items.</li>
<li>I appreciate that autocompletion adds a space after the word, but is smart enough to put a punctuation sign typed immediately after against the word. But there are some caveats:
<ul>
<li>It doesn&#x2019;t work with the closing parenthesis.</li>
<li>It doesn&#x2019;t work with ellipsis. &#x2026;</li>
<li>In French, we put a space between a word and a double punctuation sign: colon, semi-colon, double quote (the French variants: &#xAB;&#xBB;), interrogation and exclamation point. It would be nice to change the behavior if we use the French dictionary (see above why keyboard detection wouldn&#x2019;t work).<br>
(Note: I found the setting to handle the closing parenthesis case; still would be nice to make this a default, and to make this setting (list of characters) depending on dictionary.)</li>
</ul>
</li>
<li>When I navigate deeply in the (excellent) help, I would like to have a quick way to go back to the text I edit, instead of having to hit Back several times. Perhaps change the behavior of the top-right icon, which isn&#x2019;t much useful currently.</li>
<li>The MessagEase game should allow using any keyboard: that would allow to compare old speed with new one. Of course, results with other keyboards should be kept separate of MessagEase&#x2019;s results.</li>
<li>Word prediction / autocompletion: as said, it is quite good. I still have two suggestions, if these gestures are possible there: a drag up would complete the chosen word with the plural form (ideally the correct one for the current language, otherwise the default regular one for this language); a drag down would complete the word without space after it, allowing to complete it faster than browsing through a long list of words with this prefix. Eg. I type <em>sugg</em>, I choose autocompletion without space to <em>suggest</em>, I type a <em>i</em> to get the final <em>suggesting</em> proposal which otherwise would need lot of sweeping to reach.</li>
</ul>
<h3 id="typos-in-help">Typos in Help</h3>
<p>Seen:<br>
indecated<br>
commends<br>
more then two keys</p>
]]></content>
    <summary type="html">
    <![CDATA[a review of the MessagEase keyboard for Android]]>
    
    </summary>
    
      <category term="Android" scheme="http://PhiLhoSoft.github.io/tags/android/"/>
    
      <category term="Keyboard" scheme="http://PhiLhoSoft.github.io/tags/keyboard/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/tags/software/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/categories/software/"/>
    
      <category term="Android" scheme="http://PhiLhoSoft.github.io/categories/software/android/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[GitHub Atom review]]></title>
    <link href="http://PhiLhoSoft.github.io/Software/GitHub-Atom-review/"/>
    <id>http://PhiLhoSoft.github.io/Software/GitHub-Atom-review/</id>
    <published>2015-12-15T09:40:00.000Z</published>
    <updated>2016-05-17T11:15:00.000Z</updated>
    <content type="html"><![CDATA[<h1 id="github-atom-review">GitHub Atom review</h1>
<p>&#x201C;A hackable text editor for the 21st Century&#x201D;</p>
<p><a href="https://atom.io/">https://atom.io/</a></p>
<img src="/images/Atom_logo.png" title="Atom logo" alt="Atom">
<h2 id="disclaimer">Disclaimer</h2>
<p>I came to Atom with a prejudice&#x2026;<br>
The long closed-source / beta period, the fact the &#x201C;hackable&#x201D; editor isn&#x2019;t coded in JavaScript but in CoffeeScript, the need to add plugins for everything (according to some reviews), the reported slowness and memory hungriness, made me to hesitate to try it&#x2026; I was also a happy user of <a href="/Software/Adobe-Brackets-review">Adobe Brackets</a>, with no compelling need to change.<br>
But, Brackets accumulated a number of little annoyances, making me wanting to try other editors.<br>
The test of Visual Studio Code was brief, as it didn&#x2019;t have the base (semi-advanced if you want) features I use all the time: drag&#x2019;n&#x2019;drop of code, and column selection.<br>
So I tested Atom, with a critical eye. Spoiler: I was seduced, and it becomes my favorite Web IDE&#x2026;</p>
<p>That&#x2019;s the problem with information found on Internet: it quickly becomes stale&#x2026;<br>
The Atom team improved memory consumption, have an eye on responsiveness (I was impressed by their TimeCop package, and the fact they report for each package the time they add to loading), ship lot of plugins with the base editor: delegating to packages is part of their vision of modularity, but they made official packages for the most essential features, and you don&#x2019;t need to hunt every package implementing base features, saving time.</p>
<p>I appreciate the clean interface and the attention to details they have bring to the project.</p>
<a id="more"></a>
<h2 id="quick-review">Quick review</h2>
<p>I downloaded the installer. It is big! Of the IDEs I tried, it is among the biggest:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Version</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td>Brackets</td>
<td>1.5</td>
<td>37 MB</td>
</tr>
<tr>
<td>Visual Studio Code</td>
<td>0.10.3</td>
<td>43 MB</td>
</tr>
<tr>
<td>Light Table</td>
<td>0.7.2</td>
<td>48 MB</td>
</tr>
<tr>
<td>Atom</td>
<td>1.3.1</td>
<td>88 MB</td>
</tr>
<tr>
<td>WebStorm</td>
<td>9</td>
<td>140MB</td>
</tr>
</tbody>
</table>
<p>Really heavy for a so-called &#x201C;text editor&#x201D;.</p>
<p>I installed Atom (v. 1.3.1 on Windows 7 with 8 GB of memory).<br>
It doesn&#x2019;t ask where to install, it goes arbitrarily at <code>C:\Users\&lt;user name&gt;\AppData\Local\atom</code>. I would prefer to install it beside my other programs, to locale it easily. And I would appreciate it asks me before installing something on the desktop (I have no icons there!) or on the start menu (I no longer care about this one, but still&#x2026;).<br>
It is a bit &#x201C;all over the place&#x201D;, as it also has a <code>C:\Users\&lt;user name&gt;\AppData\Roaming\Atom</code> folder (for cache?), and a <code>C:\Users\&lt;user name&gt;\.atom folder</code> (settings, packages&#x2026;).<br>
Note on icons: in the Quick Start menu, and in the context menu of files, they use the path to the .exe file to give the icon. But this path changes on every auto-update! And they don&#x2019;t update it&#x2026; Simple fix: replace this path with %USERPROFILE%\AppData\Local\atom\app.ico which is provided with the editor&#x2026;</p>
<p>I opened it, it starts rather quickly.<br>
It has a dark UI, which I don&#x2019;t like, but I quickly found where to change this to the default light theme. Good point than several themes are bundled by default: no need to hunt for them, at least at start. The default light UI theme is rather nice. I also chose the <em>One Light</em> syntax theme among four. A bit too pale (low contrast) for my taste, I will eventually see if I can tweak it.</p>
<p>As I feared (I searched a bit before, given the Visual Studio Code deception), drag&#x2019;n&#x2019;drop of code isn&#x2019;t available out of the box. Actually, I saw several plugins activating it. That&#x2019;s one of the problems with this editor: there is a plethora of plugins, which can be nice, but it is confusing to choose one&#x2026; And I still think such feature should be built-in in the editor.<br>
Same for column (rectangular) selections! Later, I found out Atom supports out of the box column selection (Ctrl+Alt+Up / Down, extend only, allows rectangular selection with Shift+Left / Right) and multiple carets (Ctrl+click).<br>
I find a bit unsettling to have to install lot of plugins to get base editor features. I have the same issue with Brackets, but it has at least these two features built-in (but D&#x2019;n&#x2019;D must be activated by a setting).<br>
That said, I found several features out of the box for which I had to install a plugin in Brackets:</p>
<ul>
<li>Jump to matching brace (bracket / parenthesis);</li>
<li>Gutter selection of lines;</li>
<li>Show whitespace / end of lines / indentation guides / right margin;</li>
<li>Selection to upper / lower case; and some more.</li>
<li>Change text in selection only; regular expressions for searching; limit searches to word only (something I rarely use but which is sometime useful).</li>
</ul>
<p>Two features I mentioned in the above article are also missing from Atom:</p>
<ul>
<li>Auto-fill of search field with text under caret (text has to be selected; Ctrl+D selects the current word, but I assign it to duplicate line instead; at least, it memorizes the last search);</li>
<li>Recall previous searches / replacements (something that SciTE (my all-purpose lightweight text editor of choice) does, which I find convenient);</li>
</ul>
<p>OK, I switched to Atom to type this text (in Markdown format). Good surprise: it has spell checking enabled out of the box. And it can suggest words, although I am not sure of the logic of suggestions (scanning existing buffers, apparently; nice point: it is not obtrusive). Little bug (or unwanted feature ;-) &#x2013; I see a misspelled word in the text (red underline), I right-click directly on it, and choose Correct spelling. It does nothing&#x2026; I found out I have to left-click first on the word to get spelling suggestions.<br>
I see no way to add words to a user dictionary (there is an issue for that, and another for other language dictionaries).</p>
<p>The Welcome Guide is nice, I just saw a way to customize the styling. Although it lacks concrete examples: eg. how do I change the color of titles in Markdown? (I avoid reddish colors, reserved to mark errors). Ah, I suppose I have to study an existing style, like <a href="https://github.com/atom/atom-light-syntax/blob/master/index.less">https://github.com/atom/atom-light-syntax/blob/master/index.less</a><br>
And I can see the actual styles by showing the developer tools (View &gt; Developer &gt; Toggle Developer Tools) and using it like Chrome DevTools.</p>
<h2 id="bugs-and-annoyances">Bugs and annoyances</h2>
<p>Bug: I have <em>Choose a Theme</em> and <em>Customize the Styling</em> opened in the Welcome Guide. I can&#x2019;t scroll back above <em>Install a Package</em>. I have to close one to see the top!<br>
And I can&#x2019;t scroll the list of packages (installed, to install, etc.) with keys (up / down / page up / page down).</p>
<p>Another bug or unwanted feature: it ensures there is an empty line at the end of a file when saving it, which can be nice (I generally want that), but if I have several lines, it removes the extra ones (which is annoying in a text file, because I want to keep my future paragraph empty lines). Will see if I can disable that.</p>
<p>Undo coalescing is a bit strange: when I type a word, then undo, it removes parts of the word, successively, instead of whole word.<br>
Apparently, it coalesces when there is a pause in typing. Half a good idea, bad for slow typists (not sure if this can be tweaked), not consistent. I prefer Scintilla&#x2019;s coalescing, based on keys: when an move key (eg. arrow) is typed, or when clicking somewhere.</p>
<p>Atom lacks a nice feature of Brackets: in an HTML file, Brackets can auto-complete the path of a resource (script, CSS file, etc.). Found a plugin for that, of course&#x2026; Although it is slightly less convenient.</p>
<p>Apparently, Atom has only &#x201C;duplicate-lines&#x201D;, not &#x201C;duplicate-selection&#x201D;, alas. Sometime, I want to duplicate the selection inside the same line, eg. to quickly add an additional parameter with its type.</p>
<p>Good idea: if I type something, the buffer is marked as dirty, of course. If I edit back to the initial state (eg. type a char, then Backspace), instead of using Undo, it sees the file as pristine again (as Git would do&#x2026;).</p>
<p>Annoyance: I can hit Ctrl+F in the Settings &gt; Package page (for example), but it doesn&#x2019;t find anything there (can be convenient to find a given package by something else than its name).</p>
<p>Command palette: good idea to highlight searched terms, but on light theme, I get light gray highlight, nearly unreadable on very light gray background&#x2026; [EDIT] They fixed that!</p>
<p>Bug: column selection doesn&#x2019;t skip wrapped part of lines. Ie. if lines are wrapped, and if we extend a column selection beyond a wrapped line, the wrapped part is also taking the selection.<br>
<a href="https://github.com/atom/atom/issues/10234">https://github.com/atom/atom/issues/10234</a><br>
Bad idea: I can do a column selection with Ctrl+Alt+Up / Down. BUT, they thought it was a good idea to extend in both directions&#x2026; So there is no way to reduce the selection if we overshot! In general, I don&#x2019;t start in the middle of my selection, I am either at the top or bottom line, then I go from there. So I expect, if I go in the reverse direction (of the initial choice), to reduce the selection.</p>
<p>Bug, or annoyance (as I am used to a different behavior for other editors): if I hit Ctrl+Delete at the start of an indented line, I expect the editor to remove only the indentation characters, ie. to remove spaces or tabs up to the first non-whitespace character. But it eats also the beginning of the significant line, ie. the first word or the first symbols.<br>
Relevant issue with a workaround: <a href="https://github.com/atom/atom/issues/4026">https://github.com/atom/atom/issues/4026</a></p>
<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">&apos;atom</span>-workspace atom-text-editor&apos;:</span><br><span class="line">  <span class="symbol">&apos;ctrl</span>-backspace&apos;: <span class="symbol">&apos;editor</span>:delete-<span class="keyword">to</span>-previous-word-boundary&apos;</span><br><span class="line">  <span class="symbol">&apos;ctrl</span>-delete&apos;: <span class="symbol">&apos;editor</span>:delete-<span class="keyword">to</span>-next-word-boundary&apos;</span><br></pre></td></tr></table></figure>
<p>In general, I am annoyed by a different behavior on managing whitespace. Example: when I delete a word, I am used* to see the following (or preceding) space(s) to be removed as well. So I can delete several words quickly. Here, I have to delete the intermediary spaces as well.<br>
I also would be appreciate that Home key sends to start of line (column 0) instead of start of text (after indentation). That&#x2019;s the things I can set up in SciTE&#x2026;</p>
<ul>
<li>With editors like SciTE (based on Visual Studio behavior), Eclipse, Brackets and Plunker, for example. The last two use the CodeMirror library / component, which is very good. Atom seems to use a self-made one, which is lacking on lot of small details.</li>
</ul>
<p>Auto-indent is broken. Particularly when I paste a code snippet: it indents the already indented code, resulting with double indenting!<br>
I just activate the &#x201C;keep indentation level&#x201D; setting, which some time misses a level&#x2026;<br>
<a href="https://discuss.atom.io/t/normalize-indent-on-paste-doesnt-work-as-expected/3503/12">https://discuss.atom.io/t/normalize-indent-on-paste-doesnt-work-as-expected/3503/12</a></p>
<p>Annoyance: there is no way to set the setting tabs vs. spaces per buffer.<br>
<a href="https://discuss.atom.io/t/sometimes-tab-inserts-spaces-even-with-soft-tabs-off/3976/37">https://discuss.atom.io/t/sometimes-tab-inserts-spaces-even-with-soft-tabs-off/3976/37</a></p>
<p>Minor quibble: title and closing cross in inactive tabs are one or two pixels too low (one pixel lower than the active tab, at least). It &#x201C;hurts&#x201D; my sense of tidiness&#x2026; :-)</p>
<h2 id="conclusion">Conclusion</h2>
<p>Overall it is a good editor. It is reasonably fast for my usage (I don&#x2019;t open larges files, a known weakness of Atom).<br>
Well, almost. When Windows swaps out its memory (going to sleep), it is very slow to wake up.<br>
More annoying, it often displays a message on slowness (&#x201C;Editor not responding&#x201D;), I have to hit the button &#x201C;Keep Waiting&#x201D; to continue.<br>
<a href="https://github.com/atom/atom/issues/7275">https://github.com/atom/atom/issues/7275</a><br>
Even more annoying: the dialog stops everything. The same dialog in Chrome spontaneously disappears when the slowness is no longer detected. Here, the editor waits for clicking on Keep Waiting before resuming!<br>
<a href="https://discuss.atom.io/t/refinements-to-the-not-responding-keep-waiting-dialog/24375">https://discuss.atom.io/t/refinements-to-the-not-responding-keep-waiting-dialog/24375</a></p>
<p>The minor issues mentioned above doesn&#x2019;t prevent from using it: the good parts currently balance the bad ones.<br>
I will still recommend it. :-)</p>
<h2 id="installed-packages">Installed packages</h2>
<p>Good point: once a plugin / package is installed, no need to restart Atom to get it working.<br>
Note: list can be incomplete, and version numbers are indicative only: I won&#x2019;t update them on each package update!<br>
You can find a more complete list (when I back up my settings with sync-settings) at <a href="https://gist.github.com/PhiLhoSoft/b61b3e3d13ebd802bb08">https://gist.github.com/PhiLhoSoft/b61b3e3d13ebd802bb08</a><br>
I found an interesting list at the <a href="https://github.com/mehcode/awesome-atom">https://github.com/mehcode/awesome-atom</a> repository. I added some packages like <em>duplicate-line-or-selection</em> after reading it&#x2026;</p>
<ul>
<li>
<p>Sublime Style Column Selection<br>
Allow column selection with mouse.<br>
1.3.0 by bigfive<br>
<a href="https://atom.io/packages/Sublime-Style-Column-Selection">https://atom.io/packages/Sublime-Style-Column-Selection</a><br>
<a href="https://github.com/bigfive/atom-sublime-select">https://github.com/bigfive/atom-sublime-select</a></p>
</li>
<li>
<p>simple-drag-drop-text<br>
Enable classical drag&#x2019;n&#x2019;drop of text, with move (by default) or copy (with Ctrl).<br>
0.3.0 by mark-hahn<br>
<a href="https://atom.io/packages/simple-drag-drop-text">https://atom.io/packages/simple-drag-drop-text</a><br>
<a href="https://github.com/mark-hahn/simple-drag-drop-text">https://github.com/mark-hahn/simple-drag-drop-text</a></p>
</li>
<li>
<p>keyboard-localization<br>
Must have if you have a non-US keyboard; eg. a French one: I can&#x2019;t type } nor ] because I have to use AltGr (ie. RightCtrl+RightAlt) to reach them, and this makes interference with some Ctrl+Alt shortcuts.<br>
1.4.112 by andischerer<br>
<a href="https://atom.io/packages/keyboard-localization">https://atom.io/packages/keyboard-localization</a><br>
<a href="https://github.com/andischerer/atom-keyboard-localization">https://github.com/andischerer/atom-keyboard-localization</a></p>
</li>
<li>
<p>duplicate-line-or-selection<br>
Something that worries me in Atom from the start, as I have it in SciTE: we can duplicate the current line, but not the selection. This package fixes this problem.<br>
0.5.0 by nick<br>
<a href="https://atom.io/packages/duplicate-line-or-selection">https://atom.io/packages/duplicate-line-or-selection</a><br>
<a href="https://github.com/nick/duplicate-line-or-selection">https://github.com/nick/duplicate-line-or-selection</a></p>
</li>
<li>
<p>tree-view-open-files<br>
Shows opened files above the tree-view. Better than tabs when lot of files are opened.<br>
0.3.0 by postcasio<br>
<a href="https://atom.io/packages/tree-view-open-files">https://atom.io/packages/tree-view-open-files</a><br>
<a href="https://github.com/postcasio/tree-view-open-files">https://github.com/postcasio/tree-view-open-files</a></p>
</li>
<li>
<p>Atom Tabs Expos&#xFFFD;<br>
Quick tab overview of open files. Similar to Mac OSX Expos&#xFFFD; / Mission Control, Firefox Tab Group, Safari and Chrome Tab Overview, etc.<br>
0.11.1 by mrodalgaard<br>
<a href="https://atom.io/packages/expose">https://atom.io/packages/expose</a><br>
<a href="https://github.com/mrodalgaard/atom-expose">https://github.com/mrodalgaard/atom-expose</a></p>
</li>
<li>
<p>minimap<br>
Visual miniature representation of the content of the editor. Allows quick navigation.<br>
4.18.0 by atom-minimap<br>
<a href="https://atom.io/packages/minimap">https://atom.io/packages/minimap</a><br>
<a href="https://github.com/atom-minimap/minimap">https://github.com/atom-minimap/minimap</a></p>
</li>
<li>
<p>highlight-selected<br>
When a selection is done, corresponding words (must be whole words) in the same buffer are highlighted as well.<br>
0.11.1 by richrace<br>
<a href="https://atom.io/packages/highlight-selected">https://atom.io/packages/highlight-selected</a><br>
<a href="https://github.com/richrace/highlight-selected">https://github.com/richrace/highlight-selected</a></p>
</li>
<li>
<p>minimap-highlight-selected<br>
Shows highlights by the previous package in the minimap.<br>
4.3.1 by atom-minimap<br>
<a href="https://atom.io/packages/minimap-highlight-selected">https://atom.io/packages/minimap-highlight-selected</a><br>
<a href="https://github.com/atom-minimap/minimap-highlight-selected">https://github.com/atom-minimap/minimap-highlight-selected</a></p>
</li>
<li>
<p>autocomplete-paths<br>
Autocompletion for paths in the project, according to file system. With patch <a href="https://github.com/atom-community/autocomplete-paths/pull/51/files">https://github.com/atom-community/autocomplete-paths/pull/51/files</a> applied manually&#x2026;<br>
1.0.2 by atom-community<br>
<a href="https://atom.io/packages/autocomplete-paths">https://atom.io/packages/autocomplete-paths</a><br>
<a href="https://github.com/atom-community/autocomplete-paths">https://github.com/atom-community/autocomplete-paths</a></p>
</li>
<li>
<p>autoclose-html<br>
Automatically close HTML tags.<br>
0.19.0 by mattberkowitz<br>
<a href="https://atom.io/packages/autoclose-html">https://atom.io/packages/autoclose-html</a><br>
<a href="https://github.com/mattberkowitz/autoclose-html">https://github.com/mattberkowitz/autoclose-html</a></p>
</li>
<li>
<p>toggle-quotes<br>
Keyboard shortcut to switch between single and double quotes on the string the caret is in.<br>
1.0.0 by atom<br>
<a href="https://atom.io/packages/toggle-quotes">https://atom.io/packages/toggle-quotes</a><br>
<a href="https://github.com/atom/toggle-quotes">https://github.com/atom/toggle-quotes</a></p>
</li>
<li>
<p>atom-ternjs<br>
JavaScript code intelligence<br>
0.13.2 by tststs<br>
<a href="https://atom.io/packages/atom-ternjs">https://atom.io/packages/atom-ternjs</a><br>
<a href="https://github.com/tststs/atom-ternjs">https://github.com/tststs/atom-ternjs</a></p>
</li>
<li>
<p>linter<br>
Engine allowing to display lint information in real time in the editor. Need plugins for various languages.<br>
1.11.3 by atom-community<br>
<a href="https://atom.io/packages/linter">https://atom.io/packages/linter</a><br>
<a href="https://github.com/atom-community/linter">https://github.com/atom-community/linter</a></p>
</li>
<li>
<p>linter-eslint<br>
Linter for JavaScript.<br>
5.2.6  by AtomLinter<br>
<a href="https://atom.io/packages/linter-eslint">https://atom.io/packages/linter-eslint</a><br>
<a href="https://github.com/AtomLinter/linter-eslint">https://github.com/AtomLinter/linter-eslint</a></p>
</li>
<li>
<p>linter-htmlhint<br>
Linter for HTML.<br>
0.2.1 by AtomLinter<br>
<a href="https://atom.io/packages/linter-htmlhint">https://atom.io/packages/linter-htmlhint</a><br>
<a href="https://github.com/AtomLinter/linter-htmlhint">https://github.com/AtomLinter/linter-htmlhint</a></p>
</li>
<li>
<p>linter-stylelint<br>
Linter for CSS and Sass.<br>
1.9.1 by AtomLinter<br>
<a href="https://atom.io/packages/linter-stylelint">https://atom.io/packages/linter-stylelint</a><br>
<a href="https://github.com/AtomLinter/linter-stylelint">https://github.com/AtomLinter/linter-stylelint</a></p>
</li>
<li>
<p>minimap-linter<br>
Display linter markers on minimap.<br>
1.1.1 by AtomLinter<br>
<a href="https://atom.io/packages/minimap-linter">https://atom.io/packages/minimap-linter</a><br>
<a href="https://github.com/AtomLinter/atom-minimap-linter">https://github.com/AtomLinter/atom-minimap-linter</a></p>
</li>
<li>
<p>pigments<br>
Shows colors from various CSS notations (including named and computed colors). I prefer to display them as circles after the color definition.<br>
0.19.3 by abe33<br>
<a href="https://atom.io/packages/pigments">https://atom.io/packages/pigments</a><br>
<a href="https://github.com/abe33/atom-pigments">https://github.com/abe33/atom-pigments</a></p>
</li>
<li>
<p>atom-beautify<br>
Beaufity code, according to given rules. Not for my code (I always format as I want) but for foreign code pasted in mine&#x2026;<br>
0.28.19 by Glavin001<br>
<a href="https://atom.io/packages/atom-beautify">https://atom.io/packages/atom-beautify</a><br>
<a href="https://github.com/Glavin001/atom-beautify">https://github.com/Glavin001/atom-beautify</a></p>
</li>
<li>
<p>file-icons<br>
Add icons (depending on file type) in the tree view on the left.<br>
1.6.13 by DanBrooker<br>
<a href="https://atom.io/packages/file-icons">https://atom.io/packages/file-icons</a><br>
<a href="https://github.com/DanBrooker/file-icons">https://github.com/DanBrooker/file-icons</a></p>
</li>
<li>
<p>atom-easy-jsdoc<br>
JSDoc generation.<br>
4.2.0 by tgandrews<br>
<a href="https://atom.io/packages/atom-easy-jsdoc">https://atom.io/packages/atom-easy-jsdoc</a><br>
<a href="https://github.com/tgandrews/atom-easy-jsdoc">https://github.com/tgandrews/atom-easy-jsdoc</a></p>
</li>
<li>
<p>language-ejs<br>
EJS template support, to cleanly edit the Hexo theme I chose. Apparently only syntax highlighting support&#x2026;<br>
0.2.0 by darron<br>
<a href="https://atom.io/packages/language-ejs">https://atom.io/packages/language-ejs</a><br>
<a href="https://github.com/darron/language-ejs">https://github.com/darron/language-ejs</a></p>
</li>
<li>
<p>sync-settings<br>
Synchronization of Atom settings across computers, using a Gist to keep track of history of various files.<br>
0.6.0 by Hackafe<br>
<a href="https://atom.io/packages/sync-settings">https://atom.io/packages/sync-settings</a><br>
<a href="https://github.com/Hackafe/atom-sync-settings">https://github.com/Hackafe/atom-sync-settings</a></p>
</li>
<li>
<p>tree-ignore<br>
Allows to ignore paths in the project, hiding them in the tree-view.<br>
0.3.1 by leny<br>
<a href="https://atom.io/packages/atom-tree-ignore">https://atom.io/packages/atom-tree-ignore</a><br>
<a href="https://github.com/leny/atom-tree-ignore">https://github.com/leny/atom-tree-ignore</a></p>
</li>
<li>
<p>rest-client<br>
Simple Rest client to generate requests to servers.  Complement of RestClient on Firefox, Postman in Chrome.<br>
0.5.0 by ddavison<br>
<a href="https://atom.io/packages/rest-client">https://atom.io/packages/rest-client</a><br>
<a href="https://github.com/ddavison/rest-client">https://github.com/ddavison/rest-client</a></p>
</li>
<li>
<p>markdown-mindmap<br>
Shows headings of a Markdown text as a mindmap, allows to navigate.<br>
0.2.4 by dundalek<br>
<a href="https://atom.io/packages/markdown-mindmap">https://atom.io/packages/markdown-mindmap</a><br>
<a href="https://github.com/dundalek/atom-markdown-mindmap">https://github.com/dundalek/atom-markdown-mindmap</a></p>
</li>
<li>
<p>atom-perforce<br>
Support of the Perforce VCS (I use it at work). Has <a href="https://github.com/mattsawyer77/atom-perforce/issues/46">problems on Windows</a>, I fixed (some of) them.<br>
1.7.0 by mattsawyer77<br>
<a href="https://atom.io/packages/atom-perforce">https://atom.io/packages/atom-perforce</a><br>
<a href="https://github.com/mattsawyer77/atom-perforce">https://github.com/mattsawyer77/atom-perforce</a></p>
</li>
</ul>
<h2 id="not-used-to-see-later">Not used, to see later</h2>
<ul>
<li>
<p>project-plus<br>
Simply awesome project management in Atom.<br>
0.9.0 by mehcode<br>
<a href="https://atom.io/packages/project-plus">https://atom.io/packages/project-plus</a><br>
<a href="https://github.com/mehcode/atom-project-plus">https://github.com/mehcode/atom-project-plus</a></p>
</li>
<li>
<p>string-looper<br>
Change word case, number value and loop between keywords with the arrows of your keyboard.<br>
0.1.2 by leny<br>
<a href="https://atom.io/packages/string-looper">https://atom.io/packages/string-looper</a><br>
<a href="https://github.com/leny/atom-string-looper">https://github.com/leny/atom-string-looper</a></p>
</li>
<li>
<p>test-jumper<br>
To jump between main file and its unit test. Not used because it can&#x2019;t seem to fit in our project layout&#x2026; Still interesting.<br>
0.5.0 by danielcooper<br>
<a href="https://atom.io/packages/test-jumper">https://atom.io/packages/test-jumper</a><br>
<a href="https://github.com/danielcooper/test-jumper">https://github.com/danielcooper/test-jumper</a></p>
</li>
<li>
<p>git-time-machine<br>
Allows you to travel back in time! It shows visual plot of commits to the current file over time and you can click on it on the timeplot or hover over the plot and see all of the commits for a time range.<br>
1.3.0 by littlebee<br>
<a href="https://atom.io/packages/git-time-machine">https://atom.io/packages/git-time-machine</a><br>
<a href="https://github.com/littlebee/git-time-machine">https://github.com/littlebee/git-time-machine</a></p>
</li>
<li>
<p>merge-conflicts<br>
Resolve git conflicts within Atom<br>
1.4.2 by smashwilson<br>
<a href="https://atom.io/packages/merge-conflicts">https://atom.io/packages/merge-conflicts</a><br>
<a href="https://github.com/smashwilson/merge-conflicts">https://github.com/smashwilson/merge-conflicts</a></p>
</li>
</ul>
<h2 id="no-longer-used">No longer used</h2>
<ul>
<li>
<p>refactor<br>
Allows refactoring (basically, renaming of identifiers in context). Needs plugins per language.<br>
0.6.0 by hax<br>
<a href="https://atom.io/packages/refactor">https://atom.io/packages/refactor</a><br>
<a href="https://github.com/hax/refactor">https://github.com/hax/refactor</a></p>
</li>
<li>
<p>js-refactor<br>
Refactor plugin for JS (only rename variables and parameters).<br>
0.6.0 by hax<br>
<a href="https://atom.io/packages/js-refactor">https://atom.io/packages/js-refactor</a><br>
<a href="https://github.com/hax/js-refactor">https://github.com/hax/js-refactor</a></p>
</li>
</ul>
<h1 id="themes">Themes</h1>
<ul>
<li>
<p>gl-light-syntax<br>
2.1.1 by gouvinb<br>
<a href="https://atom.io/themes/gl-light-syntax">https://atom.io/themes/gl-light-syntax</a><br>
<a href="https://github.com/gouvinb/gl-light-syntax/tree/master/styles/languages">https://github.com/gouvinb/gl-light-syntax/tree/master/styles/languages</a></p>
</li>
<li>
<p>naturerainbow-light-syntax<br>
0.1.0 by fthiagogv<br>
<a href="https://atom.io/themes/naturerainbow-light-syntax">https://atom.io/themes/naturerainbow-light-syntax</a><br>
<a href="https://github.com/fthiagogv/naturerainbow-light-syntax">https://github.com/fthiagogv/naturerainbow-light-syntax</a></p>
</li>
</ul>
]]></content>
    <summary type="html">
    <![CDATA[a review of the GitHub Atom editor (IDE), at version 1.5.3]]>
    
    </summary>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/tags/ide/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/tags/software/"/>
    
      <category term="Tool" scheme="http://PhiLhoSoft.github.io/tags/tool/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/categories/software/"/>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/categories/software/ide/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Static Site Generators]]></title>
    <link href="http://PhiLhoSoft.github.io/Software/Static-site-generators/"/>
    <id>http://PhiLhoSoft.github.io/Software/Static-site-generators/</id>
    <published>2015-11-14T23:00:00.000Z</published>
    <updated>2016-01-13T23:11:38.725Z</updated>
    <content type="html"><![CDATA[<h1 id="static-site-generator">Static site generator</h1>
<p>So I want to write some new technical articles (like this one&#x2026;) on my latest discoveries.<br>
My previous host keeps <a href="http://Phi.Lho.free.fr">my old site</a> but has cut my FTP access, so I cannot update or add new stuff.</p>
<a id="more"></a>
<aside class="article-wip">
<img class="no-fancybox" src="/images/Work-in-Progress.svg" width="240" height="110" title="Work in Progress" alt="Work in Progress">
This is a work in progress: this article is unfinished and will be updated.
</aside>
<h2 id="static">Static</h2>
<p>I found out that GitHub Pages might be a good free host for technical content, but it won&#x2019;t allow a blog / CMS software (like WordPress) to run on it.<br>
Of course, it has Jekyll, but I wasn&#x2019;t seduced: the syntax is so-so (for me), it is a Ruby tool (slow and I have no control over it), etc.<br>
But it was a hint: no need for a full fledged blog software generating pages from scratch on each user request: these pages are mostly static so they can be coded once and for all, like I did in the previous century&#x2026;<br>
The most dynamic parts are the back-office, which I can live without, and managing user comments (with spam control). For the latter, I saw most solutions just use Disqus, a cross-platform comment service relying only on JS (and the related site / cloud host), so needing no server-side script or database. And I already use it (as a commenter), so it looks like the way to go.</p>
<p>So I need something more flexible, and / or something I could hack into my needs.</p>
<h2 id="listings">Listings</h2>
<p>A quick research shown, via two sites (<a href="https://www.staticgen.com/">Top Open-Source Static Site Generators - StaticGen</a> and <a href="https://staticsitegenerators.net/">Static Site Generators</a>) that there is literally a ton of static site generator softwares.<br>
Note / strong hint for those making such software: if you don&#x2019;t have a site to show of| what your tool can do, you are doing it wrong. No need to pay for a domain name, you can host it on a free site like <a href="http://GitHub.io">GitHub.io</a> or similar.</p>
<h2 id="hugo">Hugo</h2>
<p>I first tried <a href="http://gohugo.io/">Hugo</a>, which I discovered earlier: it has a nice site, which is an important point for this kind of software&#x2026; And a decent doc. And native binary is a promise of speed.<br>
But I quickly hit a limitation: the Markdown parser is quite rigid and not adapted to my needs. And since 1) I don&#x2019;t know Go, 2) I don&#x2019;t have much time for deep hacks, I want something working quickly, I looked elsewhere (it was a &#x201C;no Go&#x201D;&#x2026;).</p>
<h2 id="other-languages">Other languages</h2>
<p>I could use a generator written in Lua, which is a language I know and appreciate, but they seem quite confidential, used by the author and a dozen of users (guestimate&#x2026;), so I feared some issues&#x2026; (or too much work to adapt to my needs).</p>
<p>There are also PHP generators: it feels odd to use this language for off-line generation&#x2026; I can understand they appeal to those familiar with the language.</p>
<p>I can hack a Java-based generator, but I feared some heaviness.</p>
<p>I finally chose to explore JavaScript-based generators (via Node.js): I know well the language, and I know there is a rich ecosystem of Web-oriented tools.</p>
<h2 id="metalsmith">Metalsmith</h2>
<p>Another interesting generator is <a href="http://www.metalsmith.io/">Metalsmith</a>: it has a very small core, and delegate all tasks to plugins which it orchestrates. It results in flexibility: it can also generate eBooks, etc.</p>
<h2 id="build-tools">Build tools</h2>
<p>But, I thought, it looked like yet another build tool, like Webpack, Brunch or Gulp, only with more specialized plugins.<br>
I know web tools, I know how to transform Markdown to HTML, Sass to CSS, etc. I can surely leverage an existing build tool to do that, with even more flexibility. But as I haven&#x2019;t much time to spend on writing these tools (finding plugins, chaining the tasks into something sensible), I searched some kind of existing &#x201C;glue&#x201D;.</p>
<h3 id="antwar">AntWar</h3>
<p>I first tried <a href="http://antwarjs.github.io/">Antwar</a> which is based on Webpack and React.<br>
It has a good site with a tutorial, and an interesting flexibility.<br>
But I ran into some issues, like a rigid Markdown parser, so I looked elsewhere.</p>
<h3 id="akashacms">AkashaCMS</h3>
<p>Then I tried <a href="http://akashacms.com/">AkashaCMS</a>, still based on Webpack. The site is less sexy, but full of good information. It uses the Markdown-it parser, which is a good choice as it is very flexible.<br>
I have to write my own template, which is not a real problem, particularly if I use x as a starting point.<br>
But, out of the box, it uses the quite outdated EJS template system: the code is still in Google Code! The forum hadn&#x2019;t a new message in months. And the syntax is ugly and heavy, reminds of JSP / ASP, and includes JS code to do its stuff.<br>
Plus it uses Less to generate CSS, while I prefer Sass.<br>
Again, I can replace these parts if I want, the author explains how to change a renderer, but again I wanted something faster to use.</p>
<p>I skip over other generators I saw, like <a href="http://moonwave99.github.io/waffel/">Waffel</a> (based on Brunch), which seems promising, or <a href="https://github.com/gatsbyjs/gatsby">Gatsby</a> also interesting, based also on React.js, but written in CoffeeScript.</p>
<h2 id="hexo">Hexo</h2>
<p>Finally, I came back to <a href="https://hexo.io/">Hexo</a>, which I looked at several times before&#x2026;<br>
That&#x2019;s one of the tools with a nice site, good tutorials, and lot of support: it lists lot of plugins and themes, so it is easy to get started.</p>
<p>Alas, lot (if not all) of these themes are written in EJS (why is it so popular?) and Less&#x2026;</p>
<p>These were the initial choices of Hexo. Since v.3, they moved EJS and Stylus renderers to external plugins, and there are other plugins, but unless you are willing to make your own theme from scratch, you are stuck with these technologies.</p>
<p>I chose the <a href="http://blog.zhangruipeng.me/hexo-theme-icarus/">Icarus</a> theme, responsive, clean and nice, supporting Disqus and Google Analytics out of the box.<br>
I made some minor changes, mostly on the CSS side, to personalize it a bit.</p>
<h3 id="remarks">Remarks</h3>
<p>Once Hexo-cli is installed, if we do an <code>hexo</code> command in the project freshly cloned, it will complain, asking to install Hexo locally. Instead of that, you just have to do <code>npm install</code> to deploy Hexo locally and all needed plugins.</p>
]]></content>
    <summary type="html">
    <![CDATA[Making of this site]]>
    
    </summary>
    
      <category term="Blog" scheme="http://PhiLhoSoft.github.io/tags/blog/"/>
    
      <category term="Site generation" scheme="http://PhiLhoSoft.github.io/tags/site-generation/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/tags/software/"/>
    
      <category term="Tool" scheme="http://PhiLhoSoft.github.io/tags/tool/"/>
    
      <category term="Web" scheme="http://PhiLhoSoft.github.io/tags/web/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/categories/software/"/>
    
      <category term="Tools" scheme="http://PhiLhoSoft.github.io/categories/software/tools/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[RxJS distributions]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/RxJS-operators/"/>
    <id>http://PhiLhoSoft.github.io/Programming/RxJS-operators/</id>
    <published>2015-11-14T23:00:00.000Z</published>
    <updated>2015-12-23T09:20:14.845Z</updated>
    <content type="html"><![CDATA[<h1 id="rxjs-distributions">RxJS distributions</h1>
<h2 id="introduction">Introduction</h2>
<p>RxJS has several distributions:</p>
<ul>
<li>The Core distribution, with two sub-modules, is a minimal implementation;</li>
<li>The Main distribution is broken down between a main module and several sub-modules;</li>
<li>The Lite distribution is similar to the Main one, but with different assignments: it includes a big part of the binding library, and part of the async one, so it is more usable without including other modules;</li>
<li>The All distribution includes nearly everything, as the name implies.</li>
</ul>
<p>As this is a bit confusing, I made a table out of the <a href="https://github.com/Reactive-Extensions/RxJS/tree/master/doc">official doc</a>, including all mistakes found in this manually generated doc, some of which I point out here, to help tracking them down.</p>
<h2 id="the-distributions">The distributions</h2>
<p>Numbers are size in KB of .min.js as of 4.0.6 around October 2015. To be used only as comparison between versions.<br>
The file names with + are not in the documentation, I found them after installing RxJS. I guess they come from v.4, and that the doc is still about v.3.</p>
<table>
<thead>
<tr>
<th>File name</th>
<th>Id</th>
<th>Size (KiB)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Complete library</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>rx.all.js</td>
<td>A</td>
<td>139</td>
</tr>
<tr>
<td><strong>Lite libraries</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>rx.lite.js</td>
<td>L</td>
<td>81</td>
</tr>
<tr>
<td>rx.lite.aggregates.js</td>
<td>LAg</td>
<td>17</td>
</tr>
<tr>
<td>rx.lite.async.js</td>
<td>LAs</td>
<td>4</td>
</tr>
<tr>
<td>rx.lite.backpressure.js +</td>
<td></td>
<td>4</td>
</tr>
<tr>
<td>rx.lite.coincidence.js</td>
<td>LCo</td>
<td>7</td>
</tr>
<tr>
<td>rx.lite.experimental.js</td>
<td>LXp</td>
<td>8</td>
</tr>
<tr>
<td>rx.lite.extras.js</td>
<td>LEx</td>
<td>10</td>
</tr>
<tr>
<td>rx.lite.joinpatterns.js</td>
<td>LJp</td>
<td>5</td>
</tr>
<tr>
<td>rx.lite.testing.js</td>
<td>LTe</td>
<td>7</td>
</tr>
<tr>
<td>rx.lite.time.js</td>
<td>LTi</td>
<td>9</td>
</tr>
<tr>
<td>rx.lite.virtualtime.js</td>
<td>LVt</td>
<td>4</td>
</tr>
<tr>
<td><strong>Main library</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>rx.js</td>
<td>R</td>
<td>72</td>
</tr>
<tr>
<td>rx.aggregates.js</td>
<td>RAg</td>
<td>16</td>
</tr>
<tr>
<td>rx.async.js</td>
<td>RAs (needs RBi)</td>
<td>7</td>
</tr>
<tr>
<td>rx.backpressure.js +</td>
<td></td>
<td>8</td>
</tr>
<tr>
<td>rx.binding.js</td>
<td>RBi</td>
<td>7</td>
</tr>
<tr>
<td>rx.coincidence.js</td>
<td>RCo</td>
<td>7</td>
</tr>
<tr>
<td>rx.experimental.js</td>
<td>RXp</td>
<td>8</td>
</tr>
<tr>
<td>rx.joinpatterns.js</td>
<td>RJp</td>
<td>5</td>
</tr>
<tr>
<td>rx.sorting.js +</td>
<td></td>
<td>3</td>
</tr>
<tr>
<td>rx.testing.js</td>
<td>RTe (needs RVt)</td>
<td>7</td>
</tr>
<tr>
<td>rx.time.js</td>
<td>RTi</td>
<td>16</td>
</tr>
<tr>
<td>rx.virtualtime.js</td>
<td>RVt</td>
<td>4</td>
</tr>
<tr>
<td><strong>Core library</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>rx.core.js</td>
<td>C</td>
<td>15</td>
</tr>
<tr>
<td>rx.core.binding.js</td>
<td>CBi</td>
<td>10</td>
</tr>
<tr>
<td>rx.core.testing.js</td>
<td>CTe</td>
<td>14</td>
</tr>
</tbody>
</table>
<h2 id="included-observable-operators">Included Observable Operators</h2>
<h3 id="observable-methods">Observable Methods</h3>
<table>
<thead>
<tr>
<th>Method name</th>
<th>In All</th>
<th>Library id for Lite</th>
<th>Library id for Main</th>
<th>Library id for Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>amb</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>case</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>catch</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>concat</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>create</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>C</td>
</tr>
<tr>
<td>defer</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>empty</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>for</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>forkJoin</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>from</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>fromArray</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>fromCallback</td>
<td>A</td>
<td>L</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>fromEvent</td>
<td>A</td>
<td>L</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>fromEventPattern</td>
<td>A</td>
<td>L</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>fromNodeCallback</td>
<td>A</td>
<td>L</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>fromPromise</td>
<td>A</td>
<td>L</td>
<td>RAs (4)</td>
<td></td>
</tr>
<tr>
<td>generate</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>generateWithAbsoluteTime</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>generateWithRelativeTime</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>if</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>interval</td>
<td>A</td>
<td>L</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>just</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>merge</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>mergeDelayError</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>never</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>of</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>ofArrayChanges</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>ofWithScheduler</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>onErrorResumeNext</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>pairs</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>range</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>repeat</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>return</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>spawn</td>
<td>A</td>
<td>LAs</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>start</td>
<td>A</td>
<td>LAs</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>startAsync</td>
<td>A</td>
<td>LAs</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>throw</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>timer</td>
<td>A</td>
<td>L</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>toAsync</td>
<td>A</td>
<td>LAs</td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>toPromise</td>
<td></td>
<td></td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>using</td>
<td>A</td>
<td>LEx</td>
<td></td>
<td></td>
</tr>
<tr>
<td>when</td>
<td>A</td>
<td>LJp</td>
<td>RJp</td>
<td></td>
</tr>
<tr>
<td>while</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>wrap</td>
<td>A</td>
<td></td>
<td>RAs</td>
<td></td>
</tr>
<tr>
<td>zip</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="observable-instance-methods-prototype">Observable Instance Methods (prototype)</h3>
<p>(! marks functions also on object)</p>
<table>
<thead>
<tr>
<th>Method name</th>
<th>In All</th>
<th>Library id for Lite</th>
<th>Library id for Main</th>
<th>Library id for Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>aggregate</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>all</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>amb !</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>and</td>
<td>A</td>
<td>LJp</td>
<td>RJp</td>
<td></td>
</tr>
<tr>
<td>any</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>asObservable</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>average</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>buffer</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>bufferWithCount</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>bufferWithTime</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>bufferWithTimeOrCount</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>catch !</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>combineLatest</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>concat !</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>concatAll</td>
<td>A</td>
<td></td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>concatMap</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>connect</td>
<td>A</td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>controlled</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>count</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>debounce</td>
<td>A</td>
<td>L</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>defaultIfEmpty</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>delay</td>
<td>A</td>
<td>L</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>delaySubscription</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>dematerialize</td>
<td>A</td>
<td>L</td>
<td></td>
<td></td>
</tr>
<tr>
<td>distinct</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>distinctUntilChanged</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>do</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>doOnNext</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>doOnError</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>doOnCompleted</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>doWhile</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>elementAt</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>every</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>expand</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>extend</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>filter</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>finally / ensure</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>find</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>findIndex</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>first</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>flatMap</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>flatMapFirst</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>flatMapLatest</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>flatMapObserver</td>
<td>A</td>
<td></td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>flatMapWithMaxConcurrent</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>forkJoin !</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>groupBy</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>groupByUntil</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>groupJoin</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>ignoreElements</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>includes</td>
<td>A</td>
<td>LAg (5)</td>
<td>RAg (3)</td>
<td></td>
</tr>
<tr>
<td>indexOf</td>
<td></td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>isEmpty</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>join</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>last</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>lastIndexOf</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>let</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>manySelect</td>
<td>A</td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>map</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>max</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>maxBy</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>merge !</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>mergeAll</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>min</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>minBy</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>multicast</td>
<td>A</td>
<td>L</td>
<td></td>
<td></td>
</tr>
<tr>
<td>observeOn</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>onErrorResumeNext</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>pairwise</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>partition</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>pausable</td>
<td>A</td>
<td>(L)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>pausableBuffered</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>pluck</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>publish</td>
<td>A</td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>publishLast</td>
<td>A</td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>publishValue</td>
<td>A</td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>refCount</td>
<td>A</td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>reduce</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>repeat</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>replay</td>
<td>A</td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>retry</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>retryWhen</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>sample</td>
<td>A</td>
<td>L &amp; LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>scan</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>selectConcat</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>selectMany</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>selectManyObserver</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>sequenceEqual</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>selectSwitch</td>
<td></td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>selectSwitchFirst</td>
<td></td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>selectWithMaxConcurrent</td>
<td></td>
<td>LXp</td>
<td>RXp</td>
<td></td>
</tr>
<tr>
<td>share</td>
<td>A (1)</td>
<td></td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>shareLast</td>
<td></td>
<td></td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>shareReplay</td>
<td>A (1)</td>
<td></td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>shareValue</td>
<td>A (1)</td>
<td></td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>single</td>
<td>A</td>
<td>LAg</td>
<td>R &amp; RAg</td>
<td></td>
</tr>
<tr>
<td>singleInstance</td>
<td>A</td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>skip</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>skipLast</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>skipLastWithTime</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>skipUntil</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>skipUntilWithTime</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>skipWhile</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>slice</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>some</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>startWith</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>subscribe / forEach</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>subscribeOn</td>
<td>A</td>
<td>LEx</td>
<td>R (2)</td>
<td></td>
</tr>
<tr>
<td>subscribeOnNext</td>
<td></td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>subscribeOnError</td>
<td></td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>subscribeOnCompleted</td>
<td></td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>sum</td>
<td>A</td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>switch / switchLatest</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>switchFirst</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>take</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>takeLast</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>takeLastBuffer</td>
<td>A</td>
<td>LEx</td>
<td></td>
<td></td>
</tr>
<tr>
<td>takeLastBufferWithTime</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>takeLastWithTime</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>takeUntil</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>takeUntilWithTime</td>
<td>A</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>takeWhile</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>tap</td>
<td>A</td>
<td>L</td>
<td></td>
<td></td>
</tr>
<tr>
<td>tapOnNext</td>
<td>A</td>
<td>L</td>
<td></td>
<td></td>
</tr>
<tr>
<td>tapOnError</td>
<td>A</td>
<td>L</td>
<td></td>
<td></td>
</tr>
<tr>
<td>tapOnCompleted</td>
<td>A</td>
<td>L</td>
<td></td>
<td></td>
</tr>
<tr>
<td>thenDo</td>
<td></td>
<td>LJp</td>
<td>RJp</td>
<td></td>
</tr>
<tr>
<td>throttle</td>
<td>A</td>
<td>L</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>timeInterval</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>timeout</td>
<td>A</td>
<td>L &amp; LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>timeoutWithSelector</td>
<td></td>
<td>LTi</td>
<td></td>
<td></td>
</tr>
<tr>
<td>timestamp</td>
<td>A</td>
<td>L &amp; LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>toArray</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>toMap</td>
<td></td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>toPromise ?</td>
<td></td>
<td>L</td>
<td></td>
<td></td>
</tr>
<tr>
<td>toSet</td>
<td></td>
<td>LAg</td>
<td>RAg</td>
<td></td>
</tr>
<tr>
<td>transduce</td>
<td></td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>where</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>window</td>
<td>A</td>
<td>LCo</td>
<td>RCo</td>
<td></td>
</tr>
<tr>
<td>windowWithCount</td>
<td>A</td>
<td>LEx</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>windowWithTime</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>windowWithTimeOrCount</td>
<td>A</td>
<td>LTi</td>
<td>RTi</td>
<td></td>
</tr>
<tr>
<td>withLatestFrom</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>zip !</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>zipIterable</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="included-classes">Included Classes</h2>
<h3 id="core-objects">Core Objects</h3>
<table>
<thead>
<tr>
<th>Class name</th>
<th>In All</th>
<th>Library id for Lite</th>
<th>Library id for Main</th>
<th>Library id for Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rx.Observer</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>C</td>
</tr>
<tr>
<td>Rx.Observable</td>
<td></td>
<td></td>
<td>R</td>
<td>C</td>
</tr>
<tr>
<td>Rx.Notification</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>CTe</td>
</tr>
</tbody>
</table>
<h3 id="subjects">Subjects</h3>
<table>
<thead>
<tr>
<th>Class name</th>
<th>In All</th>
<th>Library id for Lite</th>
<th>Library id for Main</th>
<th>Library id for Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rx.AsyncSubject</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>CBi</td>
</tr>
<tr>
<td>Rx.BehaviorSubject</td>
<td></td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>Rx.ReplaySubject</td>
<td></td>
<td>L</td>
<td>RBi</td>
<td>CBi</td>
</tr>
<tr>
<td>Rx.Subject</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>CBi</td>
</tr>
</tbody>
</table>
<h3 id="schedulers">Schedulers</h3>
<table>
<thead>
<tr>
<th>Class name</th>
<th>In All</th>
<th>Library id for Lite</th>
<th>Library id for Main</th>
<th>Library id for Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rx.Scheduler</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>C</td>
</tr>
<tr>
<td>Rx.TestScheduler</td>
<td></td>
<td>LTe</td>
<td>RTe</td>
<td>CTe</td>
</tr>
<tr>
<td>Rx.VirtualTimeScheduler</td>
<td></td>
<td>LVt</td>
<td>RVt</td>
<td>CTe</td>
</tr>
<tr>
<td>Rx.HistoricalScheduler</td>
<td></td>
<td>LVt</td>
<td>RVt</td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="disposables">Disposables</h3>
<table>
<thead>
<tr>
<th>Class name</th>
<th>In All</th>
<th>Library id for Lite</th>
<th>Library id for Main</th>
<th>Library id for Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rx.CompositeDisposable</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>C</td>
</tr>
<tr>
<td>Rx.Disposable</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>C</td>
</tr>
<tr>
<td>Rx.RefCountDisposable</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td></td>
</tr>
<tr>
<td>Rx.SerialDisposable</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>C</td>
</tr>
<tr>
<td>Rx.SingleAssignmentDisposable</td>
<td>A</td>
<td>L</td>
<td>R</td>
<td>C</td>
</tr>
</tbody>
</table>
<h3 id="testing-classes">Testing classes</h3>
<table>
<thead>
<tr>
<th>Class name</th>
<th>In All</th>
<th>Library id for Lite</th>
<th>Library id for Main</th>
<th>Library id for Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rx.ReactiveTest</td>
<td></td>
<td>LTe</td>
<td>RTe</td>
<td>CTe</td>
</tr>
<tr>
<td>Rx.Recorded</td>
<td></td>
<td>LTe</td>
<td>RTe</td>
<td>CTe</td>
</tr>
<tr>
<td>Rx.Subscription</td>
<td></td>
<td>LTe</td>
<td>RTe</td>
<td>CTe</td>
</tr>
<tr>
<td>Rx.TestScheduler (see Schedulers above)</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>(XYz): not in the lists, but found in the description of the operator.<br>
(1): Out of order in the list at <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.complete.md">https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.complete.md</a><br>
Also some methods / classes are not in All?<br>
(2): Out of order in the list at <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.md">https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.md</a><br>
(3): Out of order in the list at <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.aggregates.md">https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.aggregates.md</a><br>
(4): Not in <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.async.md">https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/main/rx.async.md</a><br>
(5): Out of order in the list at <a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/lite/rx.lite.aggregates.md">https://github.com/Reactive-Extensions/RxJS/blob/master/doc/libraries/lite/rx.lite.aggregates.md</a></p>
]]></content>
    <summary type="html">
    <![CDATA[RxJS distributions and their operators]]>
    
    </summary>
    
      <category term="Functional programming" scheme="http://PhiLhoSoft.github.io/tags/functional-programming/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/tags/javascript/"/>
    
      <category term="Library" scheme="http://PhiLhoSoft.github.io/tags/library/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="Reactive" scheme="http://PhiLhoSoft.github.io/tags/reactive/"/>
    
      <category term="RxJS" scheme="http://PhiLhoSoft.github.io/tags/rxjs/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="General" scheme="http://PhiLhoSoft.github.io/categories/programming/general/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Functional Reactive Programming]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/Functional-Reactive-Programming/"/>
    <id>http://PhiLhoSoft.github.io/Programming/Functional-Reactive-Programming/</id>
    <published>2015-11-09T23:00:00.000Z</published>
    <updated>2016-06-04T22:25:54.819Z</updated>
    <content type="html"><![CDATA[<h1 id="functional-reactive-programming">Functional Reactive Programming</h1>
<p>FRP is a way to deal with events and asynchronous data in a functional style.<br>
Basically, it is an implementation of the Observer design pattern, coupled with the Iterator one, dealing with streams of data coming on a timeline with a fluid API.</p>
<h2 id="concept">Concept</h2>
<p>We saw, in the article about <a href="/Programming/Functional-programming-introduction/">functional programming</a>, powerful ways to process iterable data, by composing functions, with lazy evaluation able to deal with infinite data, etc.<br>
FRP does the same, but applied to streams of events, which introduces a new dimension: time.<br>
Events can be seen as some data coming at a given point in time.<br>
Data might come from user interaction: a keyboard key is pressed or released, the mouse moves, is pressed, dragged, released, etc.<br>
Data can also come from a server, after an asynchronous request. File system requests (asynchronous reading of file in Node.js, for example) are similar.<br>
It can also be a timer, delivering a timeout once or regularly.<br>
It can even come from static data (eg. content of an array): in this case, time is &#x201C;now&#x201D;.</p>
<a id="more"></a>
<aside class="article-wip">
<img class="no-fancybox" src="/images/Work-in-Progress.svg" width="240" height="110" title="Work in Progress" alt="Work in Progress">
This is a work in progress: this article is unfinished and will be updated.
</aside>
<p>In his seminal article <a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754">The introduction to Reactive Programming you&#x2019;ve been missing</a>, Andr&#xE9; Staltz wrote the &#x2018;mantra&#x2019;: &#x201C;Everything is a stream&#x201D;.<br>
It looks like a golden hammer seeing the world as nails to hit&#x2026; I prefer the less slogan-like &#x201C;Everything can be seen as a stream&#x201D;, or perhaps even more accurately, &#x201C;Everything can be put in a stream&#x201D;.<br>
After all, a stream is just a sequential collection (succession) of items disposed along a time axis, ie. with a timestamp.<br>
It can be applied in the real world, from trains coming to a station to persons lining up at a desk. Even the only time one person went to a concert can be seen as a stream&#x2026; with only one item.</p>
<p>So streams are a way to model &#x201C;the world&#x201D; from the point of view of moments in time, ordered along the time axis.</p>
<h2 id="implementations">Implementations</h2>
<h3 id="disclaimer">Disclaimer</h3>
<p>Purists of the FRP concept, those having coined the term, claim that the implementations I talk about here are not really FRP.</p>
<p>Let&#x2019;s agree on that and say that what we call FRP here is just a bastardized, simplified, with pragmatic compromises, that happens to use the same term, because it is just convenient&#x2026;</p>
<h3 id="javascript">JavaScript</h3>
<p>FRP has been implemented in various languages, particularly in functional languages like Haskell where it is a good fit to their paradigms. But it can be found also in Java, Scala, C#, etc.<br>
It is quite popular in JavaScript, rather functional in nature, where it solves a number of hard problems: avoiding callback hell (chained asynchronous calls), easing usage of promises and timeouts, handling successions of user input, etc.<br>
Thus we saw lot of FRP libraries to be created. RxJS is among the firsts. Bacon was created in reaction to the complexity of the former, Kefir was born because Bacon is slow and memory hungry, More.js is yet another library, etc.<br>
The <a href="http://xgrommx.github.io/rx-book/index.html">RxJS book</a> lists a number of them in its <a href="http://xgrommx.github.io/rx-book/content/resources/similar_libraries/index.html">Similar libraries</a> page.</p>
<p>The principles explained here can be applied to different languages and libraries, but to avoid being too abstract, I will give examples in JS, using a specific library.</p>
<h3 id="rxjs">RxJS</h3>
<p>I briefly explored some of the JS libraries, but finally settled on RxJS: it is one of the most complete implementation, it is backed by a corporation instead of being an experiment from an individual, it has good docs and good tutorials.<br>
Another advantage: its API has been defined by the <a href="http://reactivex.io/">ReactiveX</a> project, and it has been implemented in lot of languages: Java, C#, C++, Ruby, Python, Swift, Rust, and many JVM languages (often via RxJava). Plus some independently developed implementations, like Rx.PHP.<br>
So once you know the API for a language, using it in another language is rather trivial, needing mostly minor adaptations.<br>
One downside of RxJS is its size: it is a large API, so there is lot to learn, and the library is quite big, which can be annoying if you want a lean application (eg. for using on mobile devices).<br>
That said, a large part of the API can be ignored at first, a beginner needs to know only a few functions (called <em>operators</em> in RxJS).<br>
Moreover, the API has been split in various packages: the Core libraries contains only the vital minimum for Rx. The Lite libraries and the Main libraries have a base file with the objects and the essential operators, and other files split by theme: aggregates, async, time, etc. The difference between Main and Lite resides in the way the operators are grouped.<br>
The point is that a project can include only a base file, and add additional ones if a specific operator is needed. This can reduce the amount of code to include in a page.<br>
Or, for experimentations and convenience, just include the <code>rx.all.js</code> file and be done.</p>
<p>RxJS calls stream &#x201C;sequences&#x201D;, and since the point is to observe them and to react on what they content, they call them &#x201C;observable sequences&#x201D;. Older documents called them just &#x201C;observables&#x201D;, a bit ambiguous, so they adopted the longer term. I might still use the &#x201C;stream&#x201D; term too.</p>
<h2 id="creating-a-stream">Creating a stream</h2>
<p>You can create an Observable from scratch, but in most case, you just use one of the adapters wrapping common JavaScript entities in an observable sequence.</p>
<h3 id="wrapping-in-a-stream">Wrapping in a stream</h3>
<h3 id="creating-from-scratch">Creating from scratch</h3>
<p>You can create a new instance of the <code>Rx.Observable</code> object.</p>
<h2 id="subscribing-to-a-stream">Subscribing to a stream</h2>
<p>By subscribing to a stream, you create an Observer, which is, most of the time, a Disposable, which can clean up the observed resource automatically or on demand.</p>
<h3 id="hot-and-cold">Hot and cold</h3>
]]></content>
    <summary type="html">
    <![CDATA[Tutorial about the functional reactive programming paradigm, using RxJS as illustration]]>
    
    </summary>
    
      <category term="Functional programming" scheme="http://PhiLhoSoft.github.io/tags/functional-programming/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/tags/javascript/"/>
    
      <category term="Library" scheme="http://PhiLhoSoft.github.io/tags/library/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="Reactive" scheme="http://PhiLhoSoft.github.io/tags/reactive/"/>
    
      <category term="RxJS" scheme="http://PhiLhoSoft.github.io/tags/rxjs/"/>
    
      <category term="Tutorial" scheme="http://PhiLhoSoft.github.io/tags/tutorial/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="General" scheme="http://PhiLhoSoft.github.io/categories/programming/general/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Using Lodash for fun and profit]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/Using-Lodash-for-fun-and-profit/"/>
    <id>http://PhiLhoSoft.github.io/Programming/Using-Lodash-for-fun-and-profit/</id>
    <published>2015-09-30T22:00:00.000Z</published>
    <updated>2016-06-03T12:44:01.143Z</updated>
    <content type="html"><![CDATA[<h1 id="using-lodash-for-fun-and-profit">Using Lodash for fun and profit</h1>
<p>Lodash is a JavaScript utility library enabling a functional programming coding style.<br>
Lodash has general purpose functions, for type checking, string utilities, even functions to manipulate functions.<br>
More importantly, it has functions to manipulate collections. Collections is a general term covering arrays, objects (seen as maps) and even strings (seen as arrays of characters).</p>
<p>This allows to replace most <code>for</code> loops with powerful and succinct function calls, showing clearly the intent of the operation without having to analyze complex code.</p>
<img src="/images/Lodash_logo.png" title="Lodash logo" alt="Lodash">
<a id="more"></a>
<h2 id="history">History</h2>
<p>In the days of JavaScript before EcmaScript 5 (which added methods like map or filter), JS was mostly used as an imperative language.<br>
The Underscore library (created by Jeremy Ashkenas) changed that by introducing (in 2009) functions like map, filter or reduce to ease processing of arrays. Similarly to jQuery, which adds a global variable named <code>$</code> to be reachable from everywhere, Underscore adds a global variable named&#x2026; <code>_</code> to provide its functions.<br>
An Underscore contributer, John-David Dalton, tired of some limitations and inconsistencies of the library, forked it (in 2012) and named the project Lo-Dash (pun on &#x201C;low dash&#x201D;, ie. an underscore). Later, it just took the name Lodash. The library kept the <code>_</code> symbol, as it is intended to be a drop-in replacement of Underscore: replace one with the other, no other code change, and benefit from higher speed, more functions, more consistency and better documentation.<br>
Today, Lodash diverges from the Underscore API but maintains a compatibility build.<br>
Out of the box, Lodash is bigger than Underscore. Unless you start adding extensions to the latter to get functionalities available in Lodash&#x2026; And Lodash has a tool to create a build having only the functions you want. And if you use <code>require</code> on your functions, it will build automatically with only them.<br>
As said, EcmaScript 5 brought some functional features like map or filter on arrays. Underscore uses them if available, hoping their implementation will be someday faster than a manual implementation. Lodash generally prefers its hand-tuned implementations, much faster than current browser implementations. JD Dalton is performance-obsessed (he co-created a benchmark library and the JSPerf site) so he ensures the performance hit of using his library instead of hand-crafted for loops is very minor.</p>
<p>Personally, I started to use Underscore, but I found I needed to mutate an array, to avoid loosing AngularJS bindings. Underscore doesn&#x2019;t allow that, so I looked into its extensions. But the one allowing maybe to do that was poorly documented. I finally used Lodash and never looked back.<br>
I once made an issue (#2052) on Underscore to point out that some information was missing at one place and had to be found elsewhere. The issue was closed without change.<br>
In contrast, Lodash&#x2019;s doc repeats all the information needed to use a function in each entry. It might seem tiresome, but the user skips over these repetitions&#x2026; unless she really need the info! In this case, it is here. Great when jumping to a definition to refresh the memory&#x2026; or to discover it.<br>
Moreover, I made an issue to point out some little confusion. JD Dalton quickly asked for a pull request, and merged it verbatim within hours.</p>
<p>Note: the article is written for the v.3 of Lodash (more precisely, for v.3.10.1, the last of the v.3 series). Since then, JDD released v.4 of his library, with breaking changes, and lot of new functions. There is also the Lodash/fp version, with different parameter order, easying their currying for better composition.<br>
For now, I remain at v.3, of smaller scope. I might write a new article for v.4.</p>
<h2 id="functional-programming">Functional programming</h2>
<p>As said, Lodash has functions acting specifically on arrays, objects (aka. associative arrays, aka. maps) and strings (and more).<br>
But it also has functions that treat these three types as one: collection. They are taken as &#x201C;bag of items in variable number, ordered or not&#x201D;.<br>
These functions always take a collection as input, and generally a function, called <em>iteratee</em>, or <em>predicate</em> if it returns a boolean, that processes each item of the collection.<br>
There are functions to filter out items (or to keep only some of them), to map them to something else, to reduce them to a single value, to find an item, etc.<br>
With them, you will never need to write a for loop ever again&#x2026;</p>
<p>I wrote <a href="/Programming/Functional-programming-introduction/">an article explaining the base principles of functional programming</a> (FP) behind these functions. I invite you to read it before continuing here: although the article is language agnostic, it fully apply to Lodash and I cleverly used Lodash function names there&#x2026; Actually, most of them are relatively standard in the FP world and can be found in various libraries across various languages.</p>
<p>So here, I will concentrate on the specificities of Lodash, fully adapted to the needs of JavaScript.</p>
<h2 id="general-patterns-of-lodash-function-parameters">General patterns of Lodash function parameters</h2>
<p>As said, lot of Lodash functions take a collection as first parameter, and an iteratee as second one.<br>
Example:<br>
<code>var r = _.filter(list, function (v) { return v.name === someName; });</code><br>
You will find yourself to write frequently such simple predicate.<br>
So Lodash made a shortcut for this pattern:<br>
<code>var r = _.filter(list, &apos;name&apos;, someName);</code><br>
Even if you use ES6 and its arrow notation, it is still more concise&#x2026;</p>
<p>You can even omit the value:<br>
<code>var r = _.filter(list, &apos;name&apos;);</code><br>
In this case, Lodash will return the value of this property for each object, used here as a truthy or falsy value: here, it will keep out all objects without a name property (undefined), or with a null or empty value.<br>
If you replace <code>filter</code> with <code>map</code>, it returns all the name values of the list.</p>
<p>If you replace the property name with an object, Lodash will return <code>true</code> if the current item includes (deeply) all the properties of the given object with their values.<br>
For example:<br>
<code>var p = _.find(persons, { name: Bond&apos;, surname: &apos;James&apos; });</code><br>
will return the first person with these name and surname.</p>
<p>You will find these shortcuts in most Lodash functions, if applicable. The Lodash documentation re-explain them on each function supporting them.</p>
<p>Side note: the first form, <code>_.filter(list, &apos;name&apos;, someName);</code>, has been dropped in Lodash 4. So, to reduce the work for a possible update, I advise to systematically use the <code>_.filter(list, { name: someName });</code> form instead.</p>
<p>Most iteratees / predicates also share the same set of parameters: they are generally called with the current item, its index if the collection is an array or a string, or its key if that&#x2019;s a map (an object), and the collection itself.<br>
When a function has an iteratee (or other callback function), it also accepts an optional <code>thisArg</code> as last parameter. This allows to bind an object to the callback, to access its properties or methods. I haven&#x2019;t used it yet&#x2026; And it has been dropped in v.4!</p>
<p>Note that Lodash is robust against <code>undefined</code> or <code>null</code> input: it won&#x2019;t throw exceptions, but will do some kind of no-op, depending on function.</p>
<h2 id="reminder">Reminder</h2>
<p>In the article mentioned above (about functional programming), I talk about some common functions:<br>
forEach (each), forEachRight (eachRight), reduce (foldl, inject), reduceRight (foldr), range, filter (select), reject, find (detect), findLast, findIndex, findLastIndex, map (collect), take, takeWhile, takeRight, takeRightWhile, first (head), last, initial, rest (tail), drop, dropWhile, dropRight, dropRightWhile, every (all), some (any), zip, unzip, partial, ary, rearg, negate.<br>
The names between parentheses are aliases (some of them removed from v.4 &#x2013; avoid using them!).<br>
Except for consistency, I won&#x2019;t present them again here.</p>
<p>I won&#x2019;t present all the functions of Lodash, check the official documentation to have an up-to-date list and detailed presentations.<br>
They are numerous. I advice to quickly scan the list, to get an idea of what they do, what are the available tools, then later to check in depth the functions you need.</p>
<h2 id="chaining">Chaining</h2>
<p>Let say you want to filter an array, take only the last 10 elements and map them to something else.<br>
You can do that in three steps:</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> numbers = [ <span class="number">10</span>, <span class="number">55</span>, <span class="number">6</span>, <span class="number">98</span>, ... ];</span><br><span class="line"><span class="keyword">var</span> rf = _.filter(numbers, <span class="function"><span class="keyword">function</span> <span class="params">(n)</span></span><br><span class="line"></span>{</span><br><span class="line">  <span class="keyword">return</span> n &lt;= <span class="number">10</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> rt = _.take(rf, <span class="number">10</span>);</span><br><span class="line"><span class="keyword">var</span> r = _.map(rt, <span class="function"><span class="keyword">function</span> <span class="params">(n)</span> </span>{ <span class="keyword">return</span> n * <span class="number">10</span>; });</span><br></pre></td></tr></table></figure>
<p>This shows clearly each step, which can be nice for debugging, but it is a bit verbose and it creates variables &#x201C;polluting&#x201D; the current scope.<br>
Of course, you can nest the calls:</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> r = _.map(_.take(_.filter(numbers, <span class="function"><span class="keyword">function</span> <span class="params">(n)</span> </span>{ <span class="keyword">return</span> n &lt;=<span class="number">10</span>; }, <span class="number">10</span>), <span class="function"><span class="keyword">function</span> <span class="params">(n)</span> </span>{ <span class="keyword">return</span> n * <span class="number">10</span>; });</span><br></pre></td></tr></table></figure>
<p>No more intermediary variables, but it is a bit less readable, and the order of calls isn&#x2019;t obvious.<br>
Lodash allows to chain calls, leading to more readable code, and even to more efficient processing of data.</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> r = _.chain(numbers)</span><br><span class="line">  .filter(<span class="function"><span class="keyword">function</span> <span class="params">(n)</span> </span>{ <span class="keyword">return</span> n &lt;= <span class="number">10</span>; })</span><br><span class="line">  .take(<span class="number">10</span>)</span><br><span class="line">  .map(<span class="function"><span class="keyword">function</span> <span class="params">(n)</span> </span>{ <span class="keyword">return</span> n * <span class="number">10</span>; })</span><br><span class="line">  .value();</span><br></pre></td></tr></table></figure>
<p>Notice the call to <code>value()</code>.<br>
It is necessary because this chain is open-ended: you can add other functions after it. Eg. you can end it after the <code>take()</code>, and have two different values by ending the chain with two different <code>map</code>s.<br>
<code>value()</code> tells to end the chain and to evaluate it.<br>
This shows that this chaining is <em>lazy</em>: no processing is done until it is requested by <code>value()</code>. Moreover, this chaining is optimized, Lodash practices function fusion with shortcut: it doesn&#x2019;t create an intermediary result on each function call, but rather creates a compound function processing the whole input at once. And, of course, it will not map the data beyond the 10 selected by <code>take()</code>.<br>
There is a slightly shorter variant:</p>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">var r = _<span class="comment">(numbers)</span>.filter<span class="comment">(...)</span>...value<span class="comment">()</span>;</span><br></pre></td></tr></table></figure>
<p>They are basically the same, with a little difference: <code>value()</code> is not necessary if the final result is a primitive (string, number, &#x2026;). And it is slightly shorter, although less explicit.</p>
<h2 id="mutating-data">Mutating data</h2>
<p>We saw that FP privileges usage of immutable data,  returning a new structure instead of changing the given one.<br>
But Lodash is pragmatic, and provides functions that can mutate collections in-place: it might be more memory efficient, and it is useful when you must keep the reference to the data. It is named referential integrity.<br>
For example, if you bind a collection in AngularJS, you have to change it in-place; if you assign a new collection, the binding is broken.</p>
<p>We will distinguish below functions mutating data from those returning a new collection.</p>
<h2 id="collection-functions">Collection functions</h2>
<p>Reminder: <em>collection</em> is a generic term. Basically, it covers JS iterable structures: arrays, objects (seen as map, sometime called associative arrays) and strings (seen as a list of characters).<br>
The following functions work for these kinds of collections. Later, we will present functions more specific to each type.</p>
<p><code>_.includes(collection, target, [fromIndex=0])</code> (aliases: <code>include</code>, <code>contains</code>)<br>
Checks if <code>target</code> is in <code>collection</code>. If fromIndex is negative, it&#x2019;s used as the offset from the end of collection.<br>
In an array, searches the target for each entry. In an object, searches the target in the values. In a string, checks if target is in the string.</p>
<p><code>_.findWhere(collection, source)</code><br>
Performs a deep comparison between each element in <code>collection</code> and the <code>source</code> object, returning the first element that has equivalent property values (partial matching).</p>
<p><code>_.where(collection, source)</code><br>
Performs a deep comparison between each element in <code>collection</code> and the <code>source</code> object, returning an array of all elements that has equivalent property values (partial matching).</p>
<p><code>_.pluck(collection, path)</code><br>
Gets the property value of <code>path</code> from all elements in <code>collection</code>.<br>
In general, <code>collection</code> is an array of objects, and you want to get all the ids, names or other specific properties of these objects in a new array.</p>
<h2 id="array-functions">Array functions</h2>
<p>We already saw lot of functions that can be applied on arrays (among other iterable structures). Let&#x2019;s see some more specific.</p>
<h3 id="functions-mutating-arrays">Functions mutating arrays</h3>
<p><code>_.fill(array, value, [start=0], [end=array.length])</code><br>
Fills the given array with the given value in the given range (defaulting to full array).</p>
<p><code>_.pull(array, [values])</code><br>
Removes all provided values (as list of arguments) from the array.</p>
<p><code>_.pullAt(array, [indexes])</code><br>
Removes elements from the array at the given indexes (as list of arguments or array of indexes).<br>
Returns an array of removed values (null value if index is out of range).</p>
<p><code>_.remove(array, [predicate=_.identity], [thisArg])</code><br>
Removes all elements from array that predicate returns truthy for, and returns an array of removed values.<br>
Supports property shortcuts.</p>
<p><code>_.prototype.reverse()</code><br>
Reverses the wrapped array and returns the wrapped instance (for chaining).</p>
<h3 id="functions-returning-a-new-arrays">Functions returning a new arrays</h3>
<p><code>_.without()</code><br>
Same as <code>_.pull</code> but doesn&#x2019;t mutate the array.</p>
<p><code>_.at()</code><br>
Same as <code>_.pullAt</code> but doesn&#x2019;t mutate the array. Work on any collection.</p>
<p><code>_.filter()</code><br>
Same as <code>_.remove</code> but doesn&#x2019;t mutate the array. Work on any collection.</p>
<p><code>_.flatten(array, [isDeep])</code><br>
Some Lodash functions return an array of arrays. <code>flatten</code> put all values in the same array, linearly.</p>
<p><code>_.uniq(array, [isSorted], [iteratee], [thisArg])</code> (alias: unique)<br>
Eliminates duplicate entries from the given array, returning a new array.</p>
<p><code>_.union([array])</code><br>
Creates an array of unique values, in order, from all of the provided arrays.</p>
<p><code>_.difference(array, [values])</code><br>
Creates an array of unique values not included in the other provided arrays.</p>
<p><code>_.intersection([arrays])</code><br>
Creates an array of unique values that are included in all of the provided arrays.</p>
<p><code>_.xor([arrays])</code><br>
Creates an array of unique values that is the symmetric difference of the provided arrays.</p>
<h2 id="object-functions">Object functions</h2>
<h3 id="accessors">Accessors</h3>
<p>Objects in JS are dynamic: sometime, an information is optional or missing.<br>
For example, you might want to access <code>order.customer.addresses.shipping.zipCode</code>.<br>
The shipping address can be optional, eg. if it is the same than the customer&#x2019;s address.<br>
Plus we can have missing (<code>undefined</code>) information at any level.<br>
We can put the access in a try / catch block. But that&#x2019;s ugly.<br>
Or we can check each level up to the one we want:<br>
<code>if (order !== undefined &amp;&amp; order.customer !== undefined &amp;&amp; order.customer.addresses !== undefined &amp;&amp; ...)</code><br>
Tiresome and prone to errors. Idem for the shortcut version <code>order &amp;&amp; order.customer &amp;&amp; order.customer.addresses ...</code>.<br>
Lodash offers functions to access an arbitrary depth of nested objects without throwing errors.</p>
<p><code>_.get(object, path, [defaultValue])</code><br>
Accesses the property at the given path.<br>
Example: <code>var zip = _.get(order, &quot;customer.addresses.shipping.zipCode&quot;);</code><br>
gives the value if available, or <code>undefined</code> (or the default value, if provided) if one level is missing.</p>
<p><code>_.set(object, path, value)</code><br>
Is similar, except it sets the value at the given path, creating intermediary objects if needed.<br>
It mutates the object.</p>
<p><code>_.has(object, path)</code><br>
Checks if path is a direct property.</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var oo = { <span class="string">x:</span> <span class="string">&apos;foo&apos;</span>, <span class="string">y:</span> { <span class="string">z:</span> <span class="string">&apos;bar&apos;</span>, <span class="string">u:</span> undefined } };</span><br><span class="line">_has(oo, <span class="string">&apos;y.z&apos;</span>) <span class="comment">//=&gt; true</span></span><br><span class="line">_has(oo, <span class="string">&apos;y.u&apos;</span>) <span class="comment">//=&gt; true</span></span><br><span class="line">_has(oo, <span class="string">&apos;y.m&apos;</span>) <span class="comment">//=&gt; false</span></span><br></pre></td></tr></table></figure>
<p>Note that <code>path</code> can also be an array: <code>[ &apos;customer&apos;, &apos;addresses&apos;, ... ]</code><br>
It can include indexes of arrays: <code>&quot;customer.addresses[1].zipCode&quot;</code></p>
<h3 id="assign-merge-and-defaults">Assign, merge and defaults</h3>
<p>Elegant and flexible ways to merge objects and set default values to missing properties.<br>
These functions mutate the destination object, and return the result.<br>
It is not uncommon to give an empty object <code>{}</code> as destination, if we want to merge two objects but to leave them intact (or if one of them can be undefined).</p>
<p><code>_.assign(object, [sources], [customizer], [thisArg])</code> (alias: <code>extend</code>)<br>
Assign the (own) properties of source object(s) to the destination object, each additional source property overwriting the previous ones, including source properties set to undefined.</p>
<p><code>_.defaults(object, [sources])</code><br>
Assign the (own) properties of source object(s) to the destination object, only if the destination property is <code>undefined</code>. Once a property is assigned, it won&#x2019;t change.</p>
<p><code>_.defaultsDeep(object, [sources])</code><br>
Is like <code>_.defaults</code> but it recursively assigns default properties.</p>
<p><code>_.merge(object, [sources], [customizer], [thisArg])</code><br>
Overwrites deeply all (own) properties with successive values, except undefined source properties. Kind of deep <code>assign</code>.</p>
<p>Example:</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">var dest = { <span class="string">name:</span> <span class="string">&apos;Foo&apos;</span>, <span class="string">age:</span> <span class="number">25</span>, <span class="string">driver:</span> <span class="literal">true</span>,</span><br><span class="line"><span class="label">    id:</span> { <span class="string">driverLicense:</span> <span class="string">&apos;88-65&apos;</span>, <span class="string">ssn:</span> <span class="string">&apos;1-54-455&apos;</span>, <span class="string">other:</span> <span class="string">&apos;mango&apos;</span> }  };</span><br><span class="line">var src1 = { <span class="string">name:</span> <span class="string">&apos;Bar&apos;</span>, <span class="string">driver:</span> <span class="literal">false</span>, <span class="string">address:</span> <span class="string">&apos;Here and there&apos;</span>,</span><br><span class="line"><span class="label">    id:</span> { <span class="string">driverLicense:</span> undefined, <span class="string">ssn:</span> <span class="string">&apos;2-44-985&apos;</span>, <span class="string">pwd:</span> <span class="string">&apos;123&apos;</span> }  };</span><br><span class="line">var src2 = { <span class="string">name:</span> <span class="string">&apos;Moo&apos;</span>, <span class="string">maried:</span> <span class="literal">true</span>, <span class="string">age:</span> undefined, <span class="string">address:</span> <span class="string">&apos;Somewhere&apos;</span>,</span><br><span class="line"><span class="label">    id:</span> { <span class="string">driverLicense:</span> <span class="string">&apos;11-75&apos;</span>, <span class="string">ssn:</span> undefined, <span class="string">warcry:</span> <span class="string">&apos;Kowabunga&apos;</span> } };</span><br><span class="line"></span><br><span class="line">_.assign(dest, src1, src2)</span><br><span class="line"></span><br><span class="line">==&gt; {<span class="string">&quot;name&quot;</span>:<span class="string">&quot;Moo&quot;</span>,<span class="string">&quot;driver&quot;</span>:<span class="literal">false</span>,<span class="string">&quot;id&quot;</span>:{<span class="string">&quot;driverLicense&quot;</span>:<span class="string">&quot;11-75&quot;</span>,<span class="string">&quot;warcry&quot;</span>:<span class="string">&quot;Kowabunga&quot;</span>},<span class="string">&quot;address&quot;</span>:<span class="string">&quot;Somewhere&quot;</span>,<span class="string">&quot;maried&quot;</span>:<span class="literal">true</span>}</span><br><span class="line"></span><br><span class="line">_.merge(dest, src1, src2)</span><br><span class="line"></span><br><span class="line">==&gt; {<span class="string">&quot;name&quot;</span>:<span class="string">&quot;Moo&quot;</span>,<span class="string">&quot;age&quot;</span>:<span class="number">25</span>,<span class="string">&quot;driver&quot;</span>:<span class="literal">false</span>,<span class="string">&quot;address&quot;</span>:<span class="string">&quot;Somewhere&quot;</span>,<span class="string">&quot;maried&quot;</span>:<span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;id&quot;</span>:{<span class="string">&quot;driverLicense&quot;</span>:<span class="string">&quot;11-75&quot;</span>,<span class="string">&quot;ssn&quot;</span>:<span class="string">&quot;2-44-985&quot;</span>,<span class="string">&quot;other&quot;</span>:<span class="string">&quot;mango&quot;</span>,<span class="string">&quot;pwd&quot;</span>:<span class="string">&quot;123&quot;</span>,<span class="string">&quot;warcry&quot;</span>:<span class="string">&quot;Kowabunga&quot;</span>}}</span><br><span class="line"></span><br><span class="line">_.defaults(dest, src1, src2)</span><br><span class="line"></span><br><span class="line">==&gt; {<span class="string">&quot;name&quot;</span>:<span class="string">&quot;Foo&quot;</span>,<span class="string">&quot;age&quot;</span>:<span class="number">25</span>,<span class="string">&quot;driver&quot;</span>:<span class="literal">true</span>,<span class="string">&quot;address&quot;</span>:<span class="string">&quot;Here and there&quot;</span>,<span class="string">&quot;maried&quot;</span>:<span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;id&quot;</span>:{<span class="string">&quot;driverLicense&quot;</span>:<span class="string">&quot;88-65&quot;</span>,<span class="string">&quot;ssn&quot;</span>:<span class="string">&quot;1-54-455&quot;</span>,<span class="string">&quot;other&quot;</span>:<span class="string">&quot;mango&quot;</span>}}</span><br><span class="line"></span><br><span class="line">_.defaultsDeep(dest, src1, src2)</span><br><span class="line"></span><br><span class="line">==&gt; {<span class="string">&quot;name&quot;</span>:<span class="string">&quot;Foo&quot;</span>,<span class="string">&quot;age&quot;</span>:<span class="number">25</span>,<span class="string">&quot;driver&quot;</span>:<span class="literal">true</span>,<span class="string">&quot;address&quot;</span>:<span class="string">&quot;Here and there&quot;</span>,<span class="string">&quot;maried&quot;</span>:<span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;id&quot;</span>:{<span class="string">&quot;driverLicense&quot;</span>:<span class="string">&quot;88-65&quot;</span>,<span class="string">&quot;ssn&quot;</span>:<span class="string">&quot;1-54-455&quot;</span>,<span class="string">&quot;other&quot;</span>:<span class="string">&quot;mango&quot;</span>,<span class="string">&quot;pwd&quot;</span>:<span class="string">&quot;123&quot;</span>,<span class="string">&quot;warcry&quot;</span>:<span class="string">&quot;Kowabunga&quot;</span>}}</span><br></pre></td></tr></table></figure>
<h3 id="pick-a-card-any-card">Pick a card, any card</h3>
<p>A method I use often is <code>pick</code>: it allows to do a partial clone of an object, where you specify the properties to copy.<br>
<code>_.pick(object, [predicate], [thisArg])</code><br>
Predicate can be a function, a single key, a list of keys as parameters, or an array of keys.</p>
<p><code>_.omit(object, [predicate], [thisArg])</code><br>
Does the reverse of <code>pick</code>: it clones the object, removing the given properties.</p>
<h3 id="keys-and-values">Keys and values</h3>
<p><code>_.keys(object)</code><br>
Creates an array of the own enumerable property names of <code>object</code>.</p>
<p><code>_.values(object)</code><br>
Creates an array of the own enumerable property values of <code>object</code>.</p>
<p><code>_.mapKeys(object, [iteratee=_.identity], [thisArg])</code><br>
Creates an object with the same values as <code>object</code> and keys generated by running each own enumerable property of <code>object</code> through <code>iteratee</code>.</p>
<p><code>_.mapValues(object, [iteratee=_.identity], [thisArg])</code><br>
Creates an object with the same keys as <code>object</code> and values generated by running each own enumerable property of <code>object</code> through <code>iteratee</code>.</p>
<p><code>_.findKey(object, [predicate=_.identity], [thisArg])</code><br>
Finds the propoerty identified by the predicate, and returns its key.</p>
<h3 id="transform">Transform</h3>
<p><code>_.transform</code> is similar to <code>_.reduce</code>, just a bit simpler. Compare:</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">_.transform([ <span class="string">&apos;a&apos;</span>, <span class="string">&apos;b&apos;</span>, <span class="string">&apos;c&apos;</span> ], <span class="function"><span class="keyword">function</span> <span class="params">(acc, value, key)</span></span><br><span class="line"></span>{</span><br><span class="line">    acc.push(key + <span class="string">&apos; -&gt; &apos;</span> + value);</span><br><span class="line">})</span><br><span class="line">_.reduce([ <span class="string">&apos;a&apos;</span>, <span class="string">&apos;b&apos;</span>, <span class="string">&apos;c&apos;</span> ], <span class="function"><span class="keyword">function</span> <span class="params">(acc, value, key)</span></span><br><span class="line"></span>{</span><br><span class="line">    acc.push(key + <span class="string">&apos; -&gt; &apos;</span> + value);</span><br><span class="line">    <span class="keyword">return</span> acc;</span><br><span class="line">}, [])</span><br></pre></td></tr></table></figure>
<p>In both cases, we get<br>
<code>[&quot;0 -&gt; a&quot;,&quot;1 -&gt; b&quot;,&quot;2 -&gt; c&quot;]</code></p>
<p><code>_.reduce</code>&apos;s default value for the accumulator is the first value of the object, while <code>_.transform</code>&apos;s one is an empty array or object, depending on the type of the input. Actually uses the prototype of the object, so it really creates an object of same type.<br>
<code>_.transform</code>&#x2019; doesn&#x2019;t need to return the accumulator. Actually, if the return value is <code>false</code>, the iteration ends there.</p>
<h2 id="string-functions">String functions</h2>
<h3 id="case-changing-functions">Case-changing functions</h3>
<p>Reminder: case is a typographical style: uppercase (A) or lowercase (a).<br>
JavaScript allows to change case of a whole string: <code>s.toUpperCase()</code> and <code>s.toLowerCase()</code>.<br>
Language identifiers (and file names, etc.) can have various styles:</p>
<ul>
<li>UPPER_CASE (usually constants)</li>
<li>snake_case (one style of variables / functions)</li>
<li>camelCase (another style of variables / functions)</li>
<li>TitleCase (often classes and similar constructs, functions in Microsoft world&#x2026;)</li>
<li>kebab-case (CSS properties, often CSS class names too)<br>
and sentence styles:</li>
<li>Initial capital</li>
<li>Start Case</li>
</ul>
<p>Lodash offers a number of functions to convert from any style to one of these.</p>
<ul>
<li><code>_.camelCase</code>: <code>foo--bar-</code>, <code>__foo_bar</code>, <code>Foo Bar</code> =&gt; <code>fooBar</code></li>
<li><code>_.capitalize</code>: <code>foo bar</code> =&gt; <code>Foo bar</code></li>
<li><code>_.kebabCase</code>: <code>FooBar</code>,<code>_foo__bar_</code>, <code>foo Bar</code> =&gt; <code>foo-bar</code></li>
<li><code>_.snakeCase</code>: <code>foo bar</code>, <code>fooBar</code>, <code>Foo-Bar</code> =&gt; <code>foo_bar</code></li>
<li><code>_.startCase</code>: <code>foo bar</code>, <code>--Foo-bar</code>, <code>_foo_bar</code> =&gt; <code>Foo Bar</code></li>
</ul>
<h3 id="additional-functions">Additional functions:</h3>
<ul>
<li><code>_.deburr(&quot;&#xE7;a d&#xE9;j&#xE0; t&#xF4;t&quot;)</code> =&gt; <code>ca deja tot</code></li>
<li><code>_.startsWith(&quot;aaron&quot;, &quot;aa&quot;)</code> -&gt; <code>true</code></li>
<li><code>_.endsWith(&quot;file.txt&quot;, &quot;.txt&quot;)</code> =&gt; <code>true</code></li>
<li><code>_.repeat(&quot;=-&quot;, 3)</code> =&gt; <code>=-=-=-</code></li>
</ul>
<p>Plus some other functions too numerous to detail: see doc for more.<br>
A <code>template</code> function allowing string interpolation.<br>
Two escape functions to escape some characters in HTML and regexp. There is also an unescape function.<br>
Three pad functions to fit a length.<br>
Three trim functions to remove characters (spaces by default) from left, right or both sides of a string.<br>
<code>trunc</code> cutting a string at given length and separator, with a continuation string (ellipsis by default).<br>
<code>words</code> cutting a sentence in words.</p>
<h2 id="function-functions">Function functions</h2>
<p>Ie. functions manipulating functions, aka. <em>higher-order</em> functions.<br>
See the FP article on the use cases for the functions.</p>
<p>We saw <code>partial</code> to pre-fill arguments, <code>ary</code> to reduce the number of parameters, <code>rearg</code> to change their order, and <code>negate</code> to invert the result of a predicate.</p>
<h3 id="time-related-functions">Time-related functions</h3>
<p><code>_.debounce(func, [wait=0], [options])</code><br>
<code>_.throttle(func, [wait=0], [options])</code><br>
These two functions seem similar, but differ in effect (of course!) and usage.<br>
They are used when a function is called frequently at irregular intervals. A typical example is a callback on user input. These functions limit the number of calls effectively done, to limit the pressure on the process.</p>
<p><code>debounce</code> prevents calling the function unless it hasn&#x2019;t be called for some time.<br>
For example, we set a callback on key press in a text field. There, we want to do an Ajax call to search for the text input so far. But we don&#x2019;t want to do too frequent calls if the user types quickly: we can have a new character before the previous request response arrives.<br>
So we wait for a pause in the typing to issue the request: we prevent calling the function, but if the function hasn&#x2019;t been called for a given time, then we really call the function with the latest result.</p>
<p><code>throttle</code> allows calling the function only once in a given interval.<br>
It is typically used to regulate a great amount of calls, like mouse moves (dragging) or scroll events.<br>
It cuts time in windows of given interval, and it blocks all calls except the last one of the window (or the first one if specified by an option).<br>
So when you have a stream of events to process, it samples these events to reduce the amount of processing.</p>
<h2 id="various-other-functions">Various other functions</h2>
<p>Lodash offers a number of functions to check the type of a given value:</p>
<p>isUndefined, isNull,<br>
isObject, isArray, isFunction, isNative (function),<br>
isBoolean, isDate, isNumber, isRegexp, isString,<br>
isArguments, isError, isTypedArray, isElement (Dom element),<br>
isNaN, isFinite</p>
<p>Their name is explicit enough to dispense of a short description. See doc for details.<br>
They a particularly useful to ensure an argument has been passed to a function.</p>
<p><code>_.isEmpty</code> checks if the given value is empty. Can check for arrays, objects, strings and jQuery-like collections,<br>
<code>_.isEqual</code> does a deep comparison between two values to determine if they are equivalent. A customizer function allows some fuzzy logic (eg. case-insensitive comparison, etc.).<br>
<code>_.isMatch</code> does a deep comparison to determine if the given object includes all the properties of the source object. Ie. that&#x2019;s a partial <code>isEqual</code>, ignoring properties in given object not in source object. Also accepts a customizer function.</p>
<p><code>_.clone</code> and <code>_.cloneDeep</code> create respectively a shallow and a deep clone of the given value. Accepts a customizer.</p>
<h2 id="conclusion">Conclusion</h2>
<p>As said, Lodash is a very rich library of general purpose functions, particularly in the field of collection manipulations.<br>
It is very efficient, practical, and results in readable code.<br>
I invite you to explore the list of functions, to get familiar with them, to be able to pick up the right tool for the right job&#x2026;</p>
<p>Happy coding!</p>
]]></content>
    <summary type="html">
    <![CDATA[Presenting the JavaScript library Lodash]]>
    
    </summary>
    
      <category term="Functional programming" scheme="http://PhiLhoSoft.github.io/tags/functional-programming/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/tags/javascript/"/>
    
      <category term="Library" scheme="http://PhiLhoSoft.github.io/tags/library/"/>
    
      <category term="Lodash" scheme="http://PhiLhoSoft.github.io/tags/lodash/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="Tutorial" scheme="http://PhiLhoSoft.github.io/tags/tutorial/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/categories/programming/javascript/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Adobe Brackets review]]></title>
    <link href="http://PhiLhoSoft.github.io/Software/Adobe-Brackets-review/"/>
    <id>http://PhiLhoSoft.github.io/Software/Adobe-Brackets-review/</id>
    <published>2015-09-25T11:24:00.000Z</published>
    <updated>2016-01-13T23:11:38.609Z</updated>
    <content type="html"><![CDATA[<h1 id="adobe-brackets-ide-for-the-web">Adobe Brackets - IDE for the Web</h1>
<p>Integrated Development Environment oriented toward the Web technologies</p>
<p><a href="http://brackets.io/">http://brackets.io/</a></p>
<img src="/images/Brackets_logo.png" title="Brackets logo" alt="Brackets">
<h2 id="quick-review">Quick review</h2>
<p>I installed Brackets (v. 1.2 on Windows 7 with 8 GB of memory; currently at v.1.4), it went out quite smoothly, just asking for the directory where to install it.<br>
I opened it, it starts very fast.<br>
It has a dark UI but a light editing area. Not fan of dark theme, but I will try and keep it to see if it is effective to have a contrast between the UI and the editing area.<br>
Default syntax coloring theme looks OK so far. It can be changed with theme plugins.<br>
Actually, the UI theme cannot be changed easily, it needs a plugin to be able to modify it.<br>
There is no drag&#x2019;n&#x2019;drop of text by default, which is why I rejected this editor on my first try (before 1.0), because I use this operation a lot; but it has been introduced in this version, and the <a href="http://blog.brackets.io/2015/03/02/brackets-1-2-now-available/">blog post about this release</a> shows how to activate it.<br>
The editor is a bit primitive out of the box. You have to install several extensions to get things done efficiently&#x2026; That&#x2019;s OK because this keeps the application streamlined: no need to install CoffeeScript or Less extensions if you code only in JavaScript and use Sass&#x2026;<br>
There are not much settings either: you have to edit Json files to customize things. A bit less intuitive, but I am OK with that, as that&#x2019;s the way I customize ScITE, my favorite (general purpose) source code editor. And not having complex dialogs to set every option also keeps the application light.</p>
<p>After a few weeks of using Brackets, I appreciate it a lot: it is much less memory hungry than WebStorm or Eclipse, it is flexible and easy to use.<br>
I recommend it.</p>
<a id="more"></a>
<p>Still, I regret some base editor features are missing and must be fixed with extensions. Among them:</p>
<ul>
<li>Jump to matching brace (bracket / parenthesis);</li>
<li>Gutter selection of lines;</li>
<li>Recall previous searches / replacements;</li>
<li>Autofill of search field with text under caret (text has to be selected);</li>
<li>Show whitespace / end of lines / indentation guides / right margin;</li>
<li>Selection to upper / lower case; and some more.</li>
</ul>
<p>Some of these features has been addressed by adding extensions, but I feel these should be native.<br>
I will list here a number of these extensions I found useful.</p>
<p>I give the links to the GitHub projects, but the best way to install these extensions is to go to the Extension Manager in Brackets, to type (paste) the name of the extension and to install it from there. The manager also checks for updated and allows to install them easily.</p>
<h2 id="installed-extensions">Installed extensions</h2>
<h3 id="general-improvement">General improvement</h3>
<ul>
<li>
<p><strong>File Tree Exclude</strong></p>
<ul>
<li>Jon Wolfe (<a href="https://github.com/JonathanWolfe/">https://github.com/JonathanWolfe/</a>) - 0.6.3</li>
<li>Excludes folders (eg. containing generated stuff) from the file tree (less noise), find in files and quick open.</li>
<li><a href="https://github.com/JonathanWolfe/file-tree-exclude">https://github.com/JonathanWolfe/file-tree-exclude</a></li>
</ul>
</li>
<li>
<p><strong>Brackets Outline List</strong></p>
<ul>
<li>Jan Pilzer (<a href="https://github.com/Hirse">https://github.com/Hirse</a>) - 0.7.0</li>
<li>Display a list of the functions or definitions in the currently opened document.</li>
<li><a href="https://github.com/Hirse/brackets-outline-list">https://github.com/Hirse/brackets-outline-list</a></li>
</ul>
</li>
<li>
<p><strong>White Space Sanitizer</strong></p>
<ul>
<li>Miguel Castillo (<a href="https://github.com/MiguelCastillo">https://github.com/MiguelCastillo</a>) - 1.2.1</li>
<li>Help keep white spaces and tabs consistent. Also trims trailing whitespaces and ensures newline at end of file.</li>
<li><a href="https://github.com/MiguelCastillo/Brackets-wsSanitizer">https://github.com/MiguelCastillo/Brackets-wsSanitizer</a></li>
<li>See also <a href="https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences">https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences</a> to set up tab preferences per language</li>
</ul>
</li>
<li>
<p><strong>Show Whitespace</strong></p>
<ul>
<li>Dennis Kehrig (<a href="https://github.com/DennisKehrig">https://github.com/DennisKehrig</a>) - 2.0.1</li>
<li>Show indentation. Useful with the previous one&#x2026;</li>
<li><a href="https://github.com/DennisKehrig/brackets-show-whitespace">https://github.com/DennisKehrig/brackets-show-whitespace</a></li>
</ul>
</li>
<li>
<p><strong>Select Lines</strong></p>
<ul>
<li>Travis Almand (<a href="https://github.com/talmand">https://github.com/talmand</a>) - 1.3.0</li>
<li>Select lines by clicking / dragging in the gutter.</li>
<li><a href="https://github.com/talmand/Brackets-Select-Lines">https://github.com/talmand/Brackets-Select-Lines</a></li>
</ul>
</li>
<li>
<p><strong>Display Shortcuts</strong></p>
<ul>
<li>Randy Edmunds (<a href="https://github.com/redmunds">https://github.com/redmunds</a>) - 1.3.5</li>
<li>Display current keyboard shortcuts in a bottom panel that can be sorted and filtered.</li>
<li><a href="https://github.com/redmunds/brackets-display-shortcuts">https://github.com/redmunds/brackets-display-shortcuts</a></li>
<li>See also <a href="https://github.com/adobe/brackets/wiki/User-Key-Bindings">https://github.com/adobe/brackets/wiki/User-Key-Bindings</a> and <a href="https://github.com/adobe/brackets/blob/master/src/command/Commands.js">https://github.com/adobe/brackets/blob/master/src/command/Commands.js</a> to define (or change) your shortcuts.</li>
</ul>
</li>
<li>
<p><strong>Go to Matching Bracket</strong></p>
<ul>
<li>David Waterston (<a href="https://github.com/davidwaterston">https://github.com/davidwaterston</a>) - 2.1.0</li>
<li>Instantly locate and place the cursor on the matching bracket to the one under the cursor.</li>
<li>Shortcut: Ctrl+Alt+Right Arrow</li>
<li><a href="https://github.com/davidwaterston/goto-matching-bracket">https://github.com/davidwaterston/goto-matching-bracket</a></li>
</ul>
</li>
<li>
<p><strong>Rename JavaScript Identifier</strong></p>
<ul>
<li>Asger Feldthaus (<a href="https://github.com/asgerf">https://github.com/asgerf</a>) - 0.2.9</li>
<li>Intelligent renaming of JS variables.</li>
<li>Shortcut: Ctrl+R</li>
<li><a href="https://github.com/asgerf/bracket-rename">https://github.com/asgerf/bracket-rename</a></li>
</ul>
</li>
<li>
<p><strong>BracketstoIX</strong></p>
<ul>
<li>ApptoIX Limited (<a href="https://github.com/apptoix">https://github.com/apptoix</a>) - 3.2.0</li>
<li>Swiss knife toolset&#x2026; Useful: to upper or to lower case, single to double quote and back, RGB to hex colors and back, etc.</li>
<li>Shortcuts: use the Command Mapper to define them as you want. Use Display Shortcuts to see what is available or overridable.</li>
<li><a href="https://github.com/apptoix/bracketstoix">https://github.com/apptoix/bracketstoix</a> - <a href="http://www.apptoix.com/fr/bracketstoix.html">http://www.apptoix.com/fr/bracketstoix.html</a></li>
</ul>
</li>
</ul>
<h3 id="support-of-auto-completion-hinting-linting">Support of auto-completion, hinting &amp; linting</h3>
<ul>
<li>
<p><strong>Interactive Linter</strong></p>
<ul>
<li>Miguel Castillo (<a href="https://github.com/MiguelCastillo">https://github.com/MiguelCastillo</a>) - 1.0.5</li>
<li>Brings realtime JSHint/JSLint/CoffeeLint reports into Brackets as you work on your code, in form of margin indicators.</li>
<li><a href="https://github.com/MiguelCastillo/Brackets-InteractiveLinter">https://github.com/MiguelCastillo/Brackets-InteractiveLinter</a></li>
</ul>
</li>
<li>
<p><strong>SCSS Lint</strong></p>
<ul>
<li>chimo (<a href="https://github.com/chimo">https://github.com/chimo</a>) -  0.2.0</li>
<li>SCSS lint support.</li>
<li><a href="https://github.com/chimo/brackets-scss-lint">https://github.com/chimo/brackets-scss-lint</a></li>
</ul>
</li>
<li>
<p><strong>SASSHints</strong></p>
<ul>
<li>Konstantin Kobs (<a href="https://github.com/konstantinkobs">https://github.com/konstantinkobs</a>) - 1.1.0</li>
<li>Auto-completion for SASS/SCSS variables.</li>
<li><a href="https://github.com/konstantinkobs/brackets-SASShints">https://github.com/konstantinkobs/brackets-SASShints</a></li>
</ul>
</li>
<li>
<p><strong>Emmet</strong></p>
<ul>
<li>Sergey Chikuyonok (<a href="https://github.com/sergeche">https://github.com/sergeche</a>) - 1.2.2</li>
<li>Facilitates typing of HTML: div&gt;(header&gt;ul&gt;li*2&gt;a)+footer&gt;p + Tab key procures a div with a header and a footer, the former with a list inside.</li>
<li><a href="https://github.com/emmetio/brackets-emmet">https://github.com/emmetio/brackets-emmet</a></li>
</ul>
</li>
<li>
<p><strong>Brackets Snippets</strong></p>
<ul>
<li>Edward Chu (<a href="https://github.com/chuyik">https://github.com/chuyik</a>) - 1.8.1</li>
<li>Imitate Sublime Text&#x2019;s behavior of snippets: insert snippets of code by typing an abbreviation and a shortcut key.</li>
<li><a href="https://github.com/chuyik/brackets-snippets">https://github.com/chuyik/brackets-snippets</a></li>
</ul>
</li>
<li>
<p><strong>Ternific</strong></p>
<ul>
<li>Miguel Castillo (<a href="https://github.com/MiguelCastillo">https://github.com/MiguelCastillo</a>) - 0.8.0</li>
<li>JavaScript hinting and refactoring powered by Tern.</li>
<li><a href="https://github.com/MiguelCastillo/Brackets-Ternific">https://github.com/MiguelCastillo/Brackets-Ternific</a></li>
</ul>
</li>
<li>
<p><strong>QuickDocsJS</strong></p>
<ul>
<li>Ole Kr&#xF6;ger (<a href="https://github.com/Wikunia">https://github.com/Wikunia</a>) - 1.6.7</li>
<li>Inline short documentation for JavaScript functions, including a summary,syntax and parameters.</li>
<li>Shortcut: Ctrl+K</li>
<li><a href="https://github.com/Wikunia/brackets-QuickDocsJS">https://github.com/Wikunia/brackets-QuickDocsJS</a></li>
</ul>
</li>
<li>
<p><strong>FuncDocr</strong></p>
<ul>
<li>Ole Kr&#xF6;ger (<a href="https://github.com/Wikunia">https://github.com/Wikunia</a>) - 0.8.26</li>
<li>Generates JS/PHPDoc annotations for your functions.</li>
<li>Shortcut: Ctrl+Alt+D</li>
<li><a href="https://github.com/Wikunia/brackets-FuncDocr">https://github.com/Wikunia/brackets-FuncDocr</a></li>
</ul>
</li>
</ul>
<h4 id="removed-because-interactive-linter-supports-them-anyway">Removed because Interactive Linter supports them anyway</h4>
<ul>
<li>
<p><strong>JSHint</strong></p>
<ul>
<li>Enable JSHint support, which can (should) supercedes JSLint. The latter is a bit too strict about &#x201C;rules&#x201D;. The former is very flexible.</li>
<li><a href="https://github.com/cfjedimaster/brackets-jshint">https://github.com/cfjedimaster/brackets-jshint</a></li>
</ul>
</li>
<li>
<p><strong>JSCS</strong></p>
<ul>
<li>JSCS <a href="http://jscs.info/">http://jscs.info/</a> support: JSHint supports some code style rules, but they are deprecated in favor of JSCS.</li>
<li><a href="https://github.com/globexdesigns/brackets-jscs">https://github.com/globexdesigns/brackets-jscs</a></li>
</ul>
</li>
<li>
<p><strong>CSSLint</strong></p>
<ul>
<li><a href="https://github.com/cfjedimaster/brackets-csslint">https://github.com/cfjedimaster/brackets-csslint</a></li>
</ul>
</li>
</ul>
<h3 id="other-tools">Other tools</h3>
<ul>
<li>
<p><strong>Brackets SASS</strong></p>
<ul>
<li>Jason San Jose (<a href="https://github.com/jasonsanjose">https://github.com/jasonsanjose</a>) - 2.0.3-132</li>
<li>Enable Live Preview and compile SASS files.</li>
<li><a href="https://github.com/jasonsanjose/brackets-sass">https://github.com/jasonsanjose/brackets-sass</a></li>
</ul>
</li>
<li>
<p><strong>Markdown Preview</strong></p>
<ul>
<li>Glenn Ruehle (<a href="http://github.com/gruehle">http://github.com/gruehle</a>) - 1.0.10</li>
<li>As the name implies&#x2026;</li>
<li><a href="https://github.com/gruehle/MarkdownPreview">https://github.com/gruehle/MarkdownPreview</a></li>
</ul>
</li>
<li>
<p><strong>Spell-check</strong></p>
<ul>
<li>Jochen Hagentr&#xF6;m (<a href="https://github.com/couzteau">https://github.com/couzteau</a>) - 0.5.8</li>
<li>As the name implies&#x2026; Not real time.</li>
<li><a href="https://github.com/couzteau/SpellCheck">https://github.com/couzteau/SpellCheck</a></li>
</ul>
</li>
<li>
<p><strong>Perforce</strong></p>
<ul>
<li>Joshua Galvin (<a href="https://github.com/JoshGalvin">https://github.com/JoshGalvin</a>) - 1.0.1</li>
<li>Enables Perforce source control integration (no GUI, just check out / add / delete files when dirty).</li>
<li><a href="https://github.com/JoshGalvin/brackets-perforce">https://github.com/JoshGalvin/brackets-perforce</a></li>
</ul>
</li>
<li>
<p><strong>SVG Preview</strong></p>
<ul>
<li>Peter Flynn (<a href="https://github.com/peterflynn">https://github.com/peterflynn</a>) - 1.3.0</li>
<li>Live preview SVG files inline as you edit them</li>
<li><a href="https://github.com/peterflynn/svg-preview">https://github.com/peterflynn/svg-preview</a></li>
</ul>
</li>
</ul>
<h3 id="extensions-that-might-be-installed-someday">Extensions that might be installed someday</h3>
<ul>
<li>
<p><strong>Beautify</strong></p>
<ul>
<li>Format JavaScript, HTML, and CSS files</li>
<li><a href="https://github.com/drewhamlett/brackets-beautify">https://github.com/drewhamlett/brackets-beautify</a></li>
</ul>
</li>
<li>
<p><strong>Git</strong></p>
<ul>
<li><a href="https://github.com/zaggino/brackets-git">https://github.com/zaggino/brackets-git</a></li>
</ul>
</li>
</ul>
<h4 id="removed">Removed</h4>
<ul>
<li><strong>Various Improvements</strong>
<ul>
<li>Add more information in the status bar, lowercase and uppercase converter, super clipboard, button close all folders in file tree, files search.</li>
<li><a href="https://github.com/Dammmien/brackets-various-improvements">https://github.com/Dammmien/brackets-various-improvements</a></li>
</ul>
</li>
</ul>
]]></content>
    <summary type="html">
    <![CDATA[a review of the Brackets IDE for the Web, at version 1.5]]>
    
    </summary>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/tags/ide/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/tags/software/"/>
    
      <category term="Tool" scheme="http://PhiLhoSoft.github.io/tags/tool/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/categories/software/"/>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/categories/software/ide/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Functional Programming: a Brief, Pragmatic Overview]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/Functional-programming-introduction/"/>
    <id>http://PhiLhoSoft.github.io/Programming/Functional-programming-introduction/</id>
    <published>2015-09-19T22:00:00.000Z</published>
    <updated>2016-06-03T12:45:49.792Z</updated>
    <content type="html"><![CDATA[<h1 id="functional-programming-a-brief-pragmatic-overview">Functional Programming: a Brief, Pragmatic Overview</h1>
<p>Functional Programming (FP) is a programming paradigm, like imperative (procedural) programming or object-oriented programming (OOP).<br>
Some people oppose these paradigms, but actually they are not exclusive of each other: we do imperative programming inside OOP&#x2019;s methods, and we can mix OOP and FP: that&#x2019;s even a trend in modern languages (Scala, Ceylon, &#x2026;) and in older ones (JavaScript, Java 8&#x2026;).</p>
<h2 id="why-functional-programming">Why functional programming?</h2>
<p>FP exists for years, but it was rather confined to niche languages. It started to infuse in the mainstream coding practices via the above mentioned languages or libraries like Guava (Java) or Underscore / Lodash (JavaScript).<br>
By promoting stateless functions and immutable data, it proved to be very efficient and easy to control in concurrent programming, leading to efficient processing of big data.<br>
It is also easy to test. Its rather declarative style is also easy to read.<br>
And reactive functional programming (FRP) is a powerful paradigm to process asynchronously big streams of data as well as user input.</p>
<p>Given all these qualities, why isn&#x2019;t more popular?</p>
<p>Very popular languages like C++ or Java are based on OOP, which is easy to grasp: we can relate objects to the real world. So there were a generalization of OOP thinking.<br>
On the other hand, FP comes from lambda calculus, a &#x201C;formal system in mathematical logic&#x201D;. Ie. it has strong mathematical roots, thus some of its concepts can be quite abstract, and it shows when most people explain its concepts. Combined with strong typing, based on type theory, like in Haskell, we quickly end with abstract concepts with specialized jargon. Plus Haskell, one of the most popular FP languages, has a syntax not intuitive for the uninitiated.</p>
<p>Fortunately, as said, some people extracted some core ideas from FP, and exposed them in easier to understand languages and libraries (see above). This helped in spreading these practices in mainstream programming.</p>
<a id="more"></a>
<h2 id="brief-pragmatic">Brief? Pragmatic?</h2>
<p>This article is rather long, but only scratches the surface. One can write a <a href="https://drboolean.gitbooks.io/mostly-adequate-guide/content/">whole book</a> on the topic.<br>
So it is only a <strong>brief overview</strong>. Masters and purists of FP will frown upon many omissions and perhaps inaccuracies. I am not a master and certainly not a purist, and don&#x2019;t plan to be one of the latter. I probably won&#x2019;t complete the article with finer points of FP (monads, etc.) but I will try and fix any inaccuracies that I spot or that are reported.</p>
<p>It is <strong>pragmatic</strong> because I use several FP techniques, as popularized by some libraries or languages, but I don&#x2019;t use the full spectrum of FP possibilities.</p>
<h2 id="core-concepts">Core concepts</h2>
<p>So, what functional programming is about?<br>
As the name implies, like OOP is all about objects, FP is all about functions.<br>
These are first-class citizens: they can be stored in variables and collections, they can be passed as arguments to functions which can return a function. You get the idea&#x2026;<br>
Note: functions manipulating functions are called <em>higher-order functions</em>. I will spray a bit of FP jargon here, for your information; for something more complete, see <a href="https://github.com/hemanth/functional-programming-jargon">Functional programming jargon</a>, an accessible, work-in-progress glossary.</p>
<p>A central idea behind FP is to use <em>pure</em> functions: they must not change the world outside of them. A pure function will always return the same output for a given input. It is called <em>idempotency</em> and <em>referential transparency</em>. The later means that if a pure function is called with a constant, it can be replaced with the value it returns.<br>
Of course, a real program has to alter its environment: to take some data, to output some results, perhaps to react to user input.<br>
Pure FP isolates these <em>side-effects</em> in a special concept: <em>monads</em>. Which I won&#x2019;t attempt to explain here!<br>
Choosing the pragmatic approach, I tolerate functions with side-effects, but avoid them as much as possible, documenting these side-effects and, ideally, isolating them in specific modules. Which is a good practice for unit tests&#x2026;</p>
<p>As a consequence, FP favors <em>immutable</em> data. Functions avoid to mutate the data given as input (that would introduce side-effects), but return new data instead.<br>
It might seem inefficient but there are techniques to optimize this practice. Among them, <em>lazy evaluation</em> defers processing until the result is really needed. This is particularly effective when chaining several operations, which is a very common practice in FP, as we will see.</p>
<p>FP doesn&#x2019;t like loops (those made with <code>for</code>, <code>while</code>, <code>repeat</code>, etc. keywords). These are stateful constructs, with one or more loop variables. FP often uses recursion instead, thus purely relying on functions. But to be effective, the language must support <em>tail-call recursion</em> to avoid bloating the call stack. This means that a function returning the result of calling itself can avoid to push a call reference (to return to the calling point) and can instead jump directly into the new call. Yes, that&#x2019;s a kind of goto&#x2026;<br>
Recursion can be hard to get right, and some languages like Java or JavaScript (up to ES6) don&#x2019;t support tail-call recursion, so it is rarely used outside of specialized usages like iterating on tree or graph nodes.<br>
Fortunately FP offers a wide range of functions to process (or create) collections, which are the most common use case for loops. We will extend on this topic later.</p>
<p>Another important concept in FP is <em>closures</em>. When a function returns another function, the inner one (the closure) can use outer variables in its scope. In general, usage is limited to the immediate scope, ie. variables and parameters of the enclosing function. The closure keeps a reference on the content of the used variables at the time the function is returned. We say the inner function <em>closes</em> over these values, hence the closure name.<br>
It is a double edged sword, as these captured values might be mutated (if possible / allowed for the value), introducing state in the function, something that FP avoids&#x2026;<br>
Let&#x2019;s make an example for this rather abstract concept. I use JavaScript (ES6) here. I make a generic function that can return specialized variants:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> adder = (step) =&gt;</span><br><span class="line">{</span><br><span class="line">  <span class="keyword">return</span> (v) =&gt; v + step;</span><br><span class="line">};</span><br><span class="line"><span class="comment">// The above is verbose for clarity.</span></span><br><span class="line"><span class="comment">// It can be written:</span></span><br><span class="line"><span class="comment">// adder = step =&gt; v =&gt; v + step</span></span><br><span class="line"><span class="keyword">const</span> plusplus = adder(<span class="number">1</span>);</span><br><span class="line">plusplus(<span class="number">5</span>); <span class="comment">// -&gt; 6</span></span><br><span class="line"><span class="keyword">const</span> decr = adder(-<span class="number">1</span>);</span><br><span class="line">decr(<span class="number">43</span>); <span class="comment">// -&gt; 42</span></span><br></pre></td></tr></table></figure>
<p>Note that a function can have state that doesn&#x2019;t affect its idempotency. A common example in FP is <em>memoization</em>. A function with a long computation time (Fibonacci, is prime, etc.) can keep previous results. Thus, if asked again with a previously computed argument, it can just return the previous result. It is particularly effective with functions whose computing of a value is based on results for lower values. The given recursive functions above are good examples.</p>
<h2 id="avoiding-loops">Avoiding loops</h2>
<p>Since I started to use the FP style of coding in a JavaScript project, using the Lodash library, I no longer use the for loop. Or other forms of loops, which are rarely used anyway.<br>
If you look at the loops in your code, you will see some very common patterns of usage.<br>
<code>for</code> loops can be used to iterate an arbitrary number of times to perform an action. Eg. creating objects to put in a collection (or the Dom, etc.).<br>
But most of the time, they are used to iterate on a collection: entries of an array or a list, characters of a string, values of a map or set, etc. &#x201C;Collection&#x201D; is used here in the widest sense, data structure that can hold several items in variable number. Tree or graphs are more often explored with recursive functions, but the language / library can offer iterators flattening them with various strategies.</p>
<p>So why do we iterate on these collections?<br>
Sometime, it is to find an item. It can be also to compute a value (sum, average&#x2026;). Or to process each item, perhaps to transform them into something else. We might want to remove some items, or to process only some items, based on some criteria. Or to process (or extract / remove) only the n first or last items of the list, n being arbitrary on depending on a condition. Other common usage is sorting, removing duplicates, etc.</p>
<p>FP got us covered for all these cases, and more.<br>
The philosophy is similar to the Unix one, which offers lot of small utilities focused on a simple task. They have all a similar interface: accept data on standard input, spit out processed data on standard output, and they are chained via pipes.<br>
FP offers lot of small functions focused on a simple task. They generally take a collection and a function to process each item.<br>
These small functions can be used alone, but they shine when they are chained together. For example, you can take a list, filter out some elements, keep only the unique items and transform the remaining ones, in one operation.<br>
That leads to a rather declarative style of programming (a bit like SQL) which is generally more readable than a bunch of conditions, intermediary variables, sub-loops, etc. that re-implement the same old algorithms&#x2026;</p>
<p>Contrived example: given an array of numbers, eliminate those below 10, keep only the first five, and sum them.<br>
In a C-like language, that would be something like:</p>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">var i, v, r, c; <span class="comment">// assume they start at zero</span></span><br><span class="line">for <span class="comment">(i = 0; i &lt; values.length; i++)</span></span><br><span class="line">{</span><br><span class="line">  v = values[i];</span><br><span class="line">  <span class="keyword">if</span> <span class="comment">(v &gt;= 10)</span></span><br><span class="line">  {</span><br><span class="line">    <span class="keyword">if</span> <span class="comment">(c++ &lt; 5)</span> <span class="comment">// beware of off-by-one errors!</span></span><br><span class="line">    {</span><br><span class="line">      r += v;</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// I forgot else break, a too common error!</span></span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>In functional style:</p>
<figure class="highlight lasso"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">var</span> r = chainOn(values)</span><br><span class="line">  <span class="built_in">.</span>filter(v =&gt; v &gt;= <span class="number">10</span>)</span><br><span class="line">  <span class="built_in">.</span><span class="keyword">take</span>(<span class="number">5</span>)</span><br><span class="line">  <span class="built_in">.</span><span class="keyword">sum</span>();</span><br></pre></td></tr></table></figure>
<p>A nearly literal transcription of the requirement! Much more readable: the intent appears immediately.</p>
<p>As said, each function returns a new collection, but a good library does lazy evaluation, deferring process until the end of the chain, building a complex function out of the bricks, generating only one final collection (or none in this example).</p>
<h2 id="commonly-used-functions">Commonly used functions</h2>
<p>Let&#x2019;s take a look at the most common functions (also called <em>operations</em> or even <em>operators</em>). For clarity, I give a name to each, but these names can vary, depending on language / library. For example, <code>reduce</code> can be named <code>reduceLeft</code>, <code>fold</code>, <code>foldLeft</code>, etc. But their base idea is the same everywhere.<br>
Note that the order of parameters can change, depending on language / library.<br>
Nearly all these operations take a collection as input, and most of them also take a function called on each iteration on the collection, thus named <em>iteratee</em>. Or <em>predicate</em> if it returns a boolean.<br>
The parameters given to iteratees vary, but always include the current item. They can also include the index in the array or the key in the map, sometime a reference to the collection itself, etc.<br>
Note: I will use either the term list or array to talk about ordered collections. In some languages they are the same, in others not, but the differences are not relevant for that article.</p>
<p><code>forEach</code> (or <code>for</code>, <code>forAll</code>, <code>each</code>, etc.) is just a functional version of our old <code>for</code> loop. It has a <code>forEachRight</code> (or <code>eachRight</code>, etc.) variant iterating on reverse order.<br>
The advantage of this function is that it can be used at the end of a filter / transform / etc. chain.<br>
It is (should be) used only to produce side-effects for each item: create elements in the Dom, serialize the item, issue a Rest request, etc.<br>
There is a variant, called <code>tap</code> or <code>do</code>, that can be put in the middle of the chain: it doesn&#x2019;t alter the data but can do side-effects at this point of the processing.</p>
<p><code>reduce</code> (synomyms above) is a fundamental operation: it can be used to do all the other ones. As such, it should be used only in special cases, as more expressive and terser (simpler) operations should be preferred.<br>
It takes three parameters: the collection, the processing function and an initial value.<br>
The iteratee is called with a parameter (named <em>accumulator</em>) holding first the initial value, then the value returned in the previous iteration.<br>
The second parameter is the item itself.<br>
The function processes the item and alters the accumulator, then returns the latter.<br>
The initial value / accumulator can be a number, a collection (often empty), etc.<br>
For a number, the function can sum up the values in the accumulator, or store the min or max, etc. It can push or add values in a collection accumulator. Etc.<br>
The <code>reduce</code> function returns the final value of the accumulator. It is called thusly because it <em>reduces</em> (or <em>folds</em>) the items of a collection to a single value.</p>
<p><code>range</code> allows to create a list of numbers (or characters) between two bounds. This list can be used as an entry point for other functions, thus effectively replacing the numerical <code>for</code> loop.</p>
<p><code>find</code> searches the collection and returns the found item, if any (behavior if not found varies with language). The iteratee is a predicate, inspecting the item and telling if that&#x2019;s the right one. If so, it stops there and returns the found item.<br>
A variant for ordered collections, <code>findIndex</code>, returns the position of the item instead.<br>
On ordered collections, we can use <code>findLast</code> or <code>findRight</code>, iterating on the items in reverse order. These suffixes can be found on other operations for lists or similar.</p>
<p><code>filter</code> returns a reduced version of the collection, keeping the items for which the predicate returns true. It has a variant, <code>reject</code>, dropping items whose predicate is true.<br>
You might wonder why we have two functions when you just have to invert the condition in the predicate. Actually, we have a number of predefined predicates like <code>isNumber</code> or <code>isEmpty</code>. So if you want to remove empty arrays (or strings) out of a collection, you can just use <code>reject(coll, isEmpty)</code>.<br>
You can also do <code>filter(coll, negate(isEmpty))</code>, but the intent is less clear. Still it is a good first example of a function altering the behavior of another function. We will see more later.</p>
<p>Variants on ordered collections allow to keep the first (or last) items, based on a predicate: <code>takeUntil</code> keeps items until the predicate is true, <code>takeWhile</code> keeps them while the predicate is true. <code>take</code> keeps the number of items given as argument.<br>
The <code>Last</code> (or <code>Right</code>) suffix is applicable. And you can replace <code>take</code> with <code>drop</code> to keep the other part of the list.<br>
There are specialized variants for one item, a common operation: <code>first</code>, <code>last</code>, <code>rest</code>, <code>initial</code> keep or drop the first or last item of a list.</p>
<p><code>zip</code> takes a number of arrays / lists, and returns an array of arrays, where the first one groups the first items of the arrays, the second one holds the second items, etc.<br>
For example, you can make an array of <code>[ x, y ]</code> coordinates from an array of <code>x</code>s and one of <code>y</code>s. Or you can associate items with values of a range.<br>
There is an <code>unzip</code> operator doing the reverse operation.</p>
<p><code>map</code> transforms the items of a collection into something else collected in a new collection of same kind. It can be used to transform objects of some type to another type, to extract a value from objects, etc.</p>
<p><code>every</code> or <code>all</code> returns true if the iteratee returns true for all the items of the collection.<br>
<code>some</code> or <code>any</code> returns true if the iteratee returns true for at least one item.</p>
<p>There are lot of other functions, to sort or shuffle an array, to randomly sample some values, to eliminate duplicates, etc.<br>
Explore your library, get familiar with its capacities, to know the palette of tools at your disposal; you can dig more on their usage when you need them.</p>
<h2 id="function-processing">Function processing</h2>
<p>As we saw, there are functions to alter functions, to alter their signature to something expected.<br>
It eases reusability: you have lot of simple functions, from libraries or your own. You can <em>compose</em> (combine) these functions into more powerful functions.<br>
But sometime, the signature of a function of your palette doesn&#x2019;t fit what is expected in the composition.<br>
You can wrap manually the function to adapt it:<br>
<code>filter(numbers, function (n) { return !isPrime(n); }</code><br>
But it is verbose and tiresome.<br>
Or you can use a higher-order function automatically transforming (wrapping) the function:<br>
<code>filter(numbers, negate(isPrime));</code><br>
This <code>negate(isPrime)</code> way of providing a function is called <em>point-free style</em> (or <em>tacit programming</em>). This is because the parameters (<em>points</em>) are not visible, they are tacit, implicit.<br>
More on this later, but let see other examples first.</p>
<p>Let say we have a <code>toNumber</code> function taking a base (2, 10, 16&#x2026;) and a string to convert. If the base is omitted, it default to 10. We need to convert an array of strings.<br>
We can use <code>map</code> for that. If the numbers are hexadecimal, we can write in JS:</p>
<p>numbers = map(hexaStrings, function (s) { return toNumber(16, s); });</p>
<p>A bit verbose (can be better with arrow notation), not very readable.<br>
But we have a JS method named <code>bind</code>, or a (simpler) Lodash method named <code>partial</code>, that can preset the first parameters of a function.</p>
<figure class="highlight lisp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">numbers = map<span class="list">(<span class="keyword">hexaStrings</span>, partial<span class="list">(<span class="keyword">toNumber</span>, <span class="number">16</span>)</span>)</span><span class="comment">;</span></span><br></pre></td></tr></table></figure>
<p>It takes a function with n parameters, and returns a function with less parameters, some of the original parameters being preset.<br>
Such operation is called <em>partial application</em>. Or, if only one parameter remains, <em>currying</em>. The latter has a special name because it is an important process to help in <em>function composition</em>, combining functions to make a complex one.</p>
<p>If the array had decimal numbers in strings, we could use the default value of the base parameter. But the base being the first parameter, we cannot pass it directly to <code>map</code>. No problem, we have a function able to reorder the parameters of a function:</p>
<figure class="highlight lisp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">numbers = map<span class="list">(<span class="keyword">decimalStrings</span>, rearg<span class="list">(<span class="keyword">toNumber</span>, [ <span class="number">1</span>, <span class="number">0</span> ])</span>)</span><span class="comment">;</span></span><br></pre></td></tr></table></figure>
<p>The second parameter (index 1) becomes the first one, while the first one goes to the second place.<br>
<code>partial</code> is better there, but this contrived example aims to show a semi-realistic use case of <code>rearg</code>&#x2026;<br>
But actually, <code>map</code> calls the function with two parameters: the value and its index! So we convert the strings to bases 0, 1, 2, etc. Not what it was intended!<br>
Fortunately, there is a function for that&#x2122;&#x2026; A function that reduces the number of parameters of a function. This number, BTW, is called <em>arity</em>. The function (in Lodash) is called <code>ary</code>:</p>
<figure class="highlight lisp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">numbers = map<span class="list">(<span class="keyword">decimalStrings</span>, ary<span class="list">(<span class="keyword">rearg</span><span class="list">(<span class="keyword">toNumber</span>, [ <span class="number">1</span>, <span class="number">0</span> ])</span>, <span class="number">1</span>)</span><span class="comment">;</span></span></span><br></pre></td></tr></table></figure>
<p>Now, it is really less readable but the point was to show we can manipulate functions like we process collections.</p>
<p>Somehow, we can often describe a process with a list of functions / operations: filter, map, sort, uniqueItems, map, take, for example. We could put these in an array, and apply these functions successively. Some languages make an heavy usage of this scheme and have a syntax for these chains of functions.<br>
For this kind of chaining, it is easier if all these functions take only one parameter: the result of one function is fed as argument to the next function. That&#x2019;s why currying is so important.</p>
<h2 id="conclusion">Conclusion</h2>
<p>As said, I only scratched the surface of the topic, yet I introduced lot of concepts that are useful and practical in daily tasks of your favorite language. Although I admit in some languages like pre-8 Java, the syntax (with anonymous classes) can be a bit heavy.</p>
<p>FP techniques proved to be useful enough that some languages (Java 8 again, JavaScript at ES6 / ES2015) evolved to ease their usage. And lot of new ones integrated them from the start.</p>
<p>I hope this article will give you the will to use (more) these techniques, and perhaps to dig more into it.<br>
If you want to explore more functions via the Lodash library, you can continue the reading with my <a href="/Programming/Using-Lodash-for-fun-and-profit/">article on Lodash</a>.</p>
]]></content>
    <summary type="html">
    <![CDATA[Tutorial about functional programming, short and practical]]>
    
    </summary>
    
      <category term="Functional programming" scheme="http://PhiLhoSoft.github.io/tags/functional-programming/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="Tutorial" scheme="http://PhiLhoSoft.github.io/tags/tutorial/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="General" scheme="http://PhiLhoSoft.github.io/categories/programming/general/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Microsoft Visual Studio Code review]]></title>
    <link href="http://PhiLhoSoft.github.io/Software/Microsoft-Visual-Studio-Code-review/"/>
    <id>http://PhiLhoSoft.github.io/Software/Microsoft-Visual-Studio-Code-review/</id>
    <published>2015-07-12T09:06:00.000Z</published>
    <updated>2016-01-13T23:11:38.716Z</updated>
    <content type="html"><![CDATA[<h1 id="microsoft-visual-studio-code-review">Microsoft Visual Studio Code review</h1>
<p>Integrated Development Environment oriented toward the Web technologies</p>
<p><a href="https://code.visualstudio.com/">https://code.visualstudio.com/</a></p>
<img src="/images/VisualStudioCode_logo.png" title="VisualStudioCode logo" alt="Visual Studio Code">
<h2 id="quick-review">Quick review</h2>
<p>I installed Visual Studio Code (v. 0.10.3 on Windows 7 with 8 GB of memory).<br>
I opened it, it starts reasonably fast.<br>
It has a dark UI, which I don&#x2019;t like, but I quickly found where to change this to the default light theme. Good point than several themes are bundled by default: no need to hunt for them.</p>
<p>Surprisingly, drag&#x2019;n&#x2019;drop of code isn&#x2019;t enabled.<br>
Apparently, it doesn&#x2019;t even exist!<br>
<a href="http://visualstudio.uservoice.com/forums/293070-visual-studio-code/suggestions/7763958-drag-n-drop-selections">http://visualstudio.uservoice.com/forums/293070-visual-studio-code/suggestions/7763958-drag-n-drop-selections</a></p>
<p>Same for column (rectangular) selections!<br>
<a href="https://visualstudio.uservoice.com/forums/293070-visual-studio-code/suggestions/7761618-implement-column-mode-selection-editing">https://visualstudio.uservoice.com/forums/293070-visual-studio-code/suggestions/7761618-implement-column-mode-selection-editing</a></p>
<p>These are features I use extensively in all editors / IDEs I use, I feel cripled if I don&#x2019;t have them&#x2026;</p>
<p>End of test&#x2026; See you later.</p>
]]></content>
    <summary type="html">
    <![CDATA[a review of the Visual Studio Code IDE, at version 0.10]]>
    
    </summary>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/tags/ide/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/tags/software/"/>
    
      <category term="Tool" scheme="http://PhiLhoSoft.github.io/tags/tool/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/categories/software/"/>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/categories/software/ide/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[How to test if a variable or property is defined in JavaScript]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/Test-if-variable-or-property-is-defined-in-JS/"/>
    <id>http://PhiLhoSoft.github.io/Programming/Test-if-variable-or-property-is-defined-in-JS/</id>
    <published>2015-03-20T17:20:00.000Z</published>
    <updated>2015-01-13T11:20:00.000Z</updated>
    <content type="html"><![CDATA[<h1 id="how-to-test-if-a-variable-or-property-is-defined-in-javascript">How to test if a variable or property is defined in JavaScript</h1>
<h2 id="the-problem">The problem</h2>
<p>There are several use cases for testing if a variable or property is defined. We will examine them before examining the ways to check the state.</p>
<ul>
<li>
<p>Check if a global variable exists.<br>
Of course, in our code, we carefully avoid to create global variables&#x2026; We use <code>var</code> each time we declare a variable, and <code>&apos;use strict&apos;;</code> guards against forgetting it. Of course, we have <code>&apos;use strict&apos;;</code> everywhere, and an ESLint, JSHint or similar tool configuration to enforce it.<br>
But still, we can have global variables, at least when we load &#x2018;old-school&#x2019; (not AMD / CommonJS enabled) libraries: jQuery&#x2019;s <code>$</code> and Underscore / Lodash&#x2019;s <code>_</code> are famous examples.<br>
In generic code, we might want to check if these variables are defined, and if not, to provide an alternative implementation.<br>
Reminder: in a browser, these global variables are attached to the <code>window</code> object.<br>
In the general case, we have two scenarii: the variable is not declared at all, or it is declared but no value has been assigned to it yet.<br>
In the first case, if we try to use it, we will have an error (ReferenceError) complaining about a non-existing variable.<br>
In the second case, the variable has the value <code>undefined</code>.</p>
</li>
<li>
<p>Check if a local variable exists.<br>
Actually, I will ignore this one: it is the same case than the first one, and a simple look at the code around is better than coding a check! It is here only for exhausting the cases&#x2026;</p>
</li>
<li>
<p>Check if a property is defined on an object.<br>
That&#x2019;s the most common case. It can be used against global objects (eg. to see if a browser object has one of the latest features), against library objects (to handle old versions or optional features), against function parameters (optional properties on a parameter), etc.</p>
</li>
<li>
<p>Check if a function parameter is defined.<br>
A function expecting a number of parameters can be called with only part of them, or even none.<br>
In this case, the missing parameters (at the end of the list) are declared but have the value <code>undefined</code>.</p>
</li>
</ul>
<a id="more"></a>
<h2 id="the-possible-checks">The possible checks</h2>
<p>JavaScript offers several ways to do this check. What is the &#x201C;best&#x201D; one?<br>
As often, the answer is: &#x201C;It depends&#x201D;&#x2026;</p>
<h3 id="typeof-v">typeof v</h3>
<p>A rather universal / safe way is to use the <code>typeof</code> operator:</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> someIdentifier == <span class="string">&apos;undefined&apos;</span>)</span><br></pre></td></tr></table></figure>
<p>Advantage: it works in all cases, even when the variable is not declared at all (that&#x2019;s the only case where we can use an undeclared variable without throwing an error). But honestly, it is verbose / cumbersome&#x2026; :-) And I dislike using strings in code like that: if you type <code>&apos;undfined&apos;</code> instead, it can go unnoticed for a long time&#x2026;<br>
Note: since <code>typeof</code> is guaranteed to return a string result, we can use the <code>==</code> check. You might prefer to use <code>===</code> comparison if that&#x2019;s the policy of your project (which might be enforced by some tools).</p>
<h3 id="v-undefined">v === undefined</h3>
<p>A simpler way to do the check is to compare against <code>undefined</code>:</p>
<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (someIdentifier === <span class="literal">undefined</span>)</span><br></pre></td></tr></table></figure>
<p>Beware: don&#x2019;t use <code>==</code> as automatic type conversions done by JavaScript will bite you!</p>
<p>Some people object that this method can be flawed because JavaScript doesn&#x2019;t prevent from assigning a value to <code>undefined</code>, which is not a keyword. It is just a variable attached to the global object (<code>window</code> in a browser):<br>
<code>undefined = {};</code> is legal!<br>
Now, it is unlikely to happen, unless somebody made a programming mistake like forgetting an <code>=</code> in an oddly constructed test: <code>if (undefined = foo)</code>.<br>
If you include in your code base some code from an inattentive adept of Yoda conditions, you have a bigger problem than you thought&#x2026; :-)<br>
And EcmaScript 5, implemented in all major modern browsers, now prevent this, making (at least!) <code>undefined</code> immutable.<br>
Although you can still define a local variable shadowing the global <code>undefined</code>. But, again, defining a <code>var undefined</code> in your code is unlikely (or malicious!).<br>
So, unless you target very old browsers or you are very paranoid, it is safe, short and explicit.</p>
<h3 id="if-v">if (v)</h3>
<p><code>if (foo)</code><br>
<em>or</em><br>
<code>if (foo.bar)</code></p>
<p>I mention it because its usage is common. But it is generally a bad way to do the check.<br>
First, the first form fails (with the error &#x201C;ReferenceError: foo is not defined&#x201D;) if the variable is not defined at all. Now, the check is generally done for a property or local variable / parameters, which is safer. Note that so called global variables are, on the browser, properties of the <code>window</code> object, so instead of writing <code>if (foo)</code>, we can always write <code>if (window.foo)</code>, and it won&#x2019;t crash as in the first form.<br>
Second, it is a brittle check: it will fail if <code>foo.bar</code> is undefined, as expected, but also if it is &#x201C;falsey&#x201D;, the JavaScript term for all values evaluated as false because of type coercion. So it also fails if <code>foo.bar</code> is defined but has the value <code>false</code>, or is an empty string, or zero, or <code>null</code>, etc.<br>
Not very trustworthy&#x2026;<br>
To be honest, this form of test is mostly used when <code>foo.bar</code> is expected to be a function, to check if we can call it or not. In this case, it is unlikely to be 0 or &#x2018;&#x2019; or false&#x2026;<br>
It is also OK if the variable / property must be an object. It is often used in the idiom <code>var x = foo &amp;&amp; foo.bar;</code> to avoid getting a property on an undefined object.</p>
<h3 id="yourlibraryisdefined-or-somelibraryisstring">yourLibrary.isDefined() or someLibrary.isString()</h3>
<p>Several libraries offer facilities to properly do this check.</p>
<p>AngularJS offers several functions for that: <code>isDefined()</code>, <code>isUndefined()</code>, but also specialized functions to check if a variable is defined and has the proper type:</p>
<ul>
<li>angular.isArray</li>
<li>angular.isDate</li>
<li>angular.isElement</li>
<li>angular.isFunction</li>
<li>angular.isNumber</li>
<li>angular.isObject</li>
<li>angular.isString</li>
</ul>
<p>Underscore and Lodash have similar functions:</p>
<ul>
<li>_.isElement</li>
<li>_.isArray</li>
<li>_.isObject</li>
<li>_.isArguments</li>
<li>_.isFunction</li>
<li>_.isString</li>
<li>_.isNumber</li>
<li>_.isBoolean</li>
<li>_.isDate</li>
<li>_.isRegExp</li>
<li>_.isError</li>
<li>_.isFinite</li>
<li>_.isNaN</li>
<li>_.isNull</li>
<li>_.isUndefined</li>
</ul>
<p>Lodash has some more functions:</p>
<ul>
<li>_.isNative</li>
<li>_.isPlainObject</li>
<li>_.isTypedArray</li>
</ul>
<p>jQuery also has checks:</p>
<ul>
<li>jquery.isArray</li>
<li>jquery.isFunction</li>
<li>jquery.isNumeric</li>
<li>jquery.isPlainObject</li>
<li>jquery.isWindow</li>
<li>jquery.isXMLDoc</li>
</ul>
<p>And so on.</p>
]]></content>
    <summary type="html">
    <![CDATA[Shows various ways to test if a variable or a property is defined in JavaScript]]>
    
    </summary>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/tags/javascript/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="Tutorial" scheme="http://PhiLhoSoft.github.io/tags/tutorial/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="JavaScript" scheme="http://PhiLhoSoft.github.io/categories/programming/javascript/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[JetBrains WebStorm review]]></title>
    <link href="http://PhiLhoSoft.github.io/Software/JetBrains-WebStorm-review/"/>
    <id>http://PhiLhoSoft.github.io/Software/JetBrains-WebStorm-review/</id>
    <published>2015-03-02T10:42:00.000Z</published>
    <updated>2016-01-13T23:11:38.654Z</updated>
    <content type="html"><![CDATA[<h1 id="jetbrains-webstorm-review">JetBrains WebStorm review</h1>
<p><a href="https://www.jetbrains.com/webstorm/">https://www.jetbrains.com/webstorm/</a></p>
<img src="/images/WebStorm_logo.png" title="WebStorm logo" alt="WebStorm">
<p>For Java coding, I elected Eclipse as my main IDE. I tried NetBeans, and appreciated it, but at the time, it was Java-centric so I went back to Eclipse instead, more polyglot. Now, NetBeans is more versatile, but now I know Eclipse well, with its quirks, warts and all, so I remain there.<br>
When I had to code JavaScript (with AngularJS, how original!) at work, for a new project, I naturally tried to use Eclipse, with an Angular plugin. It wasn&#x2019;t so bad, but still a bit frustrating, with no renaming of local variables, loosing the capability to drag&#x2019;n&#x2019;drop code in CSS or HTML editors (a long-standing bug&#x2026;), and some other frustrations.<br>
A colleague advised to try WebStorm.<br>
At first, I was a bit reluctant. First, it is a payware, something I usually avoid. Of course, there is chance my company finally pays for the software, if it was a real productivity tool. But then, that&#x2019;s something that I would use at work, and couldn&#x2019;t use at home (I have zero software budget&#x2026;).<br>
Secondly, I tried IntelliJ IDEA some years ago, and wasn&#x2019;t convinced. Perhaps it was less mature than now, or perhaps I didn&#x2019;t try hard enough, but I went back to my Eclipse quite quickly.</p>
<a id="more"></a>
<p>Well, I installed it (v. 9.0.3 on Windows 7 with 8 GB of memory) and, as usual in a first contact, I went to the settings, to get a first feel of the capabilities of the application. They are quite complete, yet not overwhelming.<br>
I first chose the Eclipse keyboard configuration, allowing me to find back a familiar interface. And I customized some that I also customize on Eclipse (to find back shortcuts I use in my favorite source code editor, SciTE). It went well and fast.</p>
<p>I also customized the color settings. IIRC, it defaults to a dark theme, which I dislike. I chose a clear theme, and customized the colors to my taste. It is quite flexible, too.<br>
Lastly, I changed the JavaScript formatting to follow the rules we use at work. Also easy and flexible, with still some quirks that have corresponding open issues in their backlog.</p>
<p>One surprise: I imported our project, I selected Perforce (the VCS we use at work) as VCS for it (or it even proposed it, perhaps because it found a .p4ignore file), and it went forward without asking any question (except my password), finding settings in the environment variables. The VCS integration is rather well made.</p>
<p>I have collected a little list of pros and cons:</p>
<p>PROS</p>
<ul>
<li>Good auto-completion. It first propose local occurrences, then some more distant ones. See a cons for this feature, though.</li>
<li>It is aware of file paths in code (in script tags): if I delete a JS file, it can warn it is still used in some source code.</li>
<li>Good renaming facility, powerful, but because of the inherent nature of JavaScript, can be too wide (see the cons).</li>
<li>Smart HTML, CSS (and SCSS) editing, with good auto-completion and formatting.</li>
<li>Good editing capabilities, including column (rectangular) selection mode and drag&#x2019;n&#x2019;drop of text.</li>
<li>Good, fast open resource (Ctrl+Shift+R) facility with real-time list of matching names, and pre-selection of recently / frequently used files. Compensates a bit the issue with tabs (see below).</li>
<li>Good, clear project management: you just import a directory, and mark some folders as excluded (generated files like target), or resource. They are marked with colors in the project tree.<br>
Colors are also used by the VCS to mark new files, changed files, etc.</li>
<li>Natively knows lot of Web languages (JS, Dart, Typescript, Coffeescript), markup (CSS, HTML, XML, Json, Yaml&#x2026;) and tools (Gherkin, HAML, LESS, SASS, SCSS, etc.).</li>
<li>Good analysis of code, with hints, eg. when we forget a semi-colon, or errors (sometime too discrete).</li>
<li>Support of Emmet in HTML and CSS. For example, if we type, in an HTML editor, table&gt;thead&gt;tr&gt;th<em>8^^^tbody&gt;tr</em>5&gt;td*8 then Tab, we get a full HTML table with headers (8 columns) and body (5 rows).</li>
<li>Shortcut to view the current HTML file in any main browser.</li>
</ul>
<p>CONS</p>
<ul>
<li>I am often confused with Tab management. Perhaps I am too used to Eclipse, where I can have lot of open tabs: I have a drop-down list of these tabs, where I can type the first letter to quickly find the editor I want. WS has the same drop-down, but only shows there non-displayed tabs (instead of all of them), and isn&#x2019;t searchable (apparently). The concept of non-displayed is fuzzy too, as some tabs are out of view and I have to scroll them (with the mouse wheel) to see them.<br>
So I don&#x2019;t know if a tab is out of view or non-displayed. I find myself relying on the Project view (hierarchical) to switch between two related files (eg. controller and template), but they are relatively far spaced there, so I scroll a lot, and have to double-click on a file name (even if already opened) to switch to it.<br>
PS.: I just found out I can have tabs on several rows, I will try this disposition.<br>
I find myself loosing lot of time on this. A little pro thought: it is easy to move a tab to put it close to the related one. At least when both are visible!</li>
<li>auto-completion sometime kicks in automatically in the middle of typing an identifier, and sometime it can be annoying as it might freeze completely WebStorm: I get a spinning cursor and I have to wait for several dozens of seconds before being able to resume the typing. I think there is an open bug on this topic.</li>
<li>Lot of operations like auto-completion rely on Node.js for parsing JavaScript and providing a database of identifiers. The Node.js instance can grow enormous (near a gigabyte of memory) and is likely the culprit for the freezing described above.</li>
<li>Renaming a non-local identifier is greedy: it will find all occurrences of this string in the project (can include strings and comments) and will propose all of them. It can be slow (see above) and we have to examine each occurrence. This encourages to use unique names: if we have to data stores, for example, instead of naming the Crud methods with generic names (create, update, delete, etc.), it is better to name them to the specific objects they operate on (createFoo, updateFoo, deleteFoo&#x2026;). This eases auto-completion and renaming by narrowing the possible occurrences.</li>
<li>Bad management of Azerty keyboard: commenting code can be made with Ctrl+/ where / is shifted on my keyboard. I can&#x2019;t get it to work&#x2026; I just mapped the command to one I use in SciTE, anyway.</li>
</ul>
<p>I hadn&#x2019;t time to test how to debug JavaScript within WS, but it also something it can do.</p>
<p>Overall, I am quite impressed by this IDE, which has a deep knowledge of the Web environment, offers good editing facilities and is very pleasant to use.</p>
]]></content>
    <summary type="html">
    <![CDATA[a review of the WebStorm IDE for Web applications, at version 9]]>
    
    </summary>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/tags/ide/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/tags/software/"/>
    
      <category term="Tool" scheme="http://PhiLhoSoft.github.io/tags/tool/"/>
    
      <category term="Software" scheme="http://PhiLhoSoft.github.io/categories/software/"/>
    
      <category term="IDE" scheme="http://PhiLhoSoft.github.io/categories/software/ide/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Ceylon strong selling points]]></title>
    <link href="http://PhiLhoSoft.github.io/Programming/Ceylon-strong-selling-points/"/>
    <id>http://PhiLhoSoft.github.io/Programming/Ceylon-strong-selling-points/</id>
    <published>2014-10-14T16:20:00.000Z</published>
    <updated>2016-04-23T12:40:00.000Z</updated>
    <content type="html"><![CDATA[<h1 id="ceylon-strong-selling-points">Ceylon strong selling points</h1>
<p>Note: this is a draft, based on a Google+ message I made years ago.</p>
<a id="more"></a>
<p>I am only a beginner with this language, so I recommend to take a look at the Quick Introduction [1] and Tour of the language [2] to have a better, less subjective and more accurate overview.</p>
<p>Here is my take:</p>
<ul>
<li>Its syntax is C-like, close of Java, without exotic operators&#x2026; ;-) Likewise, interface / abstract class / classes / inheritance / generics are close of Java, remains familiar.</li>
<li>Visibility rules are simpler than in Java. It allows top-level functions (at module level).</li>
<li>It compiles to the JVM (bytecode) and to JavaScript, with interoperability with both universes.</li>
<li>No primitives, everything is an object, the compiler can optimize integer / float / characters / etc. to their platform equivalent.</li>
<li>Multiline strings with interpolation.</li>
<li>Iterables and Sequences are also first-class entities, with literals.</li>
<li>It has a strong yet flexible typing, with union and intersection of types, and type inference. Full support of variance (co-, contra-, in-).</li>
<li>Mixins: interfaces can have implementations, but no context / state. So they have only pure functions.</li>
<li>An awesome feature is null safety, enforced by the compiler itself: the language doesn&#x2019;t have a concept of NullPointerException, because the compiler forces you to test for nullity (existence of value, more precisely) if you told it your variable can be null. At work, we use FindBugs to check this in Java, but it goes with lot of ceremony and has holes&#x2026;</li>
<li>By default, values are immutable, variable identifiers must be marked as such explicitly.</li>
<li>Functions are first-class entities, can be stored in variables and collections, passed as parameters and returned, etc.</li>
<li>Named parameters, default values, flexible syntax allowing declarative object instantiation.</li>
<li>Simplified accessors: we generally do direct access to (public / shared) members, we can override with getters and setters without breaking the API if we need to change the implementation.</li>
<li>for comprehensions for generating or processing iterables.</li>
<li>Range literal and processing.</li>
<li>Operator overloading, with strict rules.</li>
<li>Capability to rename imported classes; type aliases.</li>
<li>The IDE is quite good (Eclipse plugin), with auto-completion, refactoring, etc.</li>
</ul>
<p>[1] <a href="http://ceylon-lang.org/documentation/1.0/introduction">http://ceylon-lang.org/documentation/1.0/introduction</a><br>
[2] <a href="http://ceylon-lang.org/documentation/1.0/tour">http://ceylon-lang.org/documentation/1.0/tour</a></p>
]]></content>
    <summary type="html">
    <![CDATA[Some strong selling points of Ceylon]]>
    
    </summary>
    
      <category term="Ceylon" scheme="http://PhiLhoSoft.github.io/tags/ceylon/"/>
    
      <category term="Language" scheme="http://PhiLhoSoft.github.io/tags/language/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/tags/programming/"/>
    
      <category term="Programming" scheme="http://PhiLhoSoft.github.io/categories/programming/"/>
    
      <category term="Ceylon" scheme="http://PhiLhoSoft.github.io/categories/programming/ceylon/"/>
    
  </entry>
  
</feed>
