Minor docs edits.

This commit is contained in:
Simon Forman 2018-06-06 07:59:06 -07:00
parent 37c34fc54f
commit 22f7c6da00
4 changed files with 126 additions and 426 deletions

View File

@ -11775,7 +11775,7 @@ div#notebook {
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<h1 id="Treating-Trees-I">Treating Trees I<a class="anchor-link" href="#Treating-Trees-I">&#182;</a></h1><p>Although any expression in Joy can be considered to describe a <a href="https://en.wikipedia.org/wiki/Tree_structure">tree</a> with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about <a href="https://en.wikipedia.org/wiki/Binary_search_tree">ordered binary trees</a> and how to make and use them.</p> <h1 id="Treating-Trees-I:-Ordered-Binary-Trees">Treating Trees I: Ordered Binary Trees<a class="anchor-link" href="#Treating-Trees-I:-Ordered-Binary-Trees">&#182;</a></h1><p>Although any expression in Joy can be considered to describe a <a href="https://en.wikipedia.org/wiki/Tree_structure">tree</a> with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about <a href="https://en.wikipedia.org/wiki/Binary_search_tree">ordered binary trees</a> and how to make and use them.</p>
<p>The basic structure, in a <a href="https://en.wikipedia.org/wiki/Algebraic_data_type">crude type notation</a>, is:</p> <p>The basic structure, in a <a href="https://en.wikipedia.org/wiki/Algebraic_data_type">crude type notation</a>, is:</p>
<pre><code>Tree :: [] | [key value Tree Tree] <pre><code>Tree :: [] | [key value Tree Tree]
@ -11886,6 +11886,24 @@ key [value [] []] cons
</div> </div>
</div> </div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>[&#39;k&#39; &#39;v&#39; [] []]
</pre>
</div>
</div>
</div>
</div>
</div> </div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt"> <div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div> </div>
@ -12498,7 +12516,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec</code></pre>
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Interlude:-cmp-combinator">Interlude: <code>cmp</code> combinator<a class="anchor-link" href="#Interlude:-cmp-combinator">&#182;</a></h2><p>Instead of mucking about with nested <code>ifte</code> combinators let's just go whole hog and define <code>cmp</code> which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:</p> <h2 id="Interlude:-cmp-combinator">Interlude: <code>cmp</code> combinator<a class="anchor-link" href="#Interlude:-cmp-combinator">&#182;</a></h2><p>Instead of mucking about with nested <code>ifte</code> combinators let's use <code>cmp</code> which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:</p>
<pre><code> a b [G] [E] [L] cmp <pre><code> a b [G] [E] [L] cmp
------------------------- a &gt; b ------------------------- a &gt; b
@ -12518,47 +12536,6 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec</code></pre>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[20]:</div> <div class="prompt input_prompt">In&nbsp;[20]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.library</span> <span class="kn">import</span> <span class="n">FunctionWrapper</span>
<span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="kn">import</span> <span class="n">pushback</span>
<span class="kn">from</span> <span class="nn">notebook_preamble</span> <span class="kn">import</span> <span class="n">D</span>
<span class="nd">@FunctionWrapper</span>
<span class="k">def</span> <span class="nf">cmp_</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
<span class="sd">&#39;&#39;&#39;</span>
<span class="sd"> cmp takes two values and three quoted programs on the stack and runs</span>
<span class="sd"> one of the three depending on the results of comparing the two values:</span>
<span class="sd"> a b [G] [E] [L] cmp</span>
<span class="sd"> ------------------------- a &gt; b</span>
<span class="sd"> G</span>
<span class="sd"> a b [G] [E] [L] cmp</span>
<span class="sd"> ------------------------- a = b</span>
<span class="sd"> E</span>
<span class="sd"> a b [G] [E] [L] cmp</span>
<span class="sd"> ------------------------- a &lt; b</span>
<span class="sd"> L</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="n">L</span><span class="p">,</span> <span class="p">(</span><span class="n">E</span><span class="p">,</span> <span class="p">(</span><span class="n">G</span><span class="p">,</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">stack</span><span class="p">))))</span> <span class="o">=</span> <span class="n">stack</span>
<span class="n">expression</span> <span class="o">=</span> <span class="n">pushback</span><span class="p">(</span><span class="n">G</span> <span class="k">if</span> <span class="n">a</span> <span class="o">&gt;</span> <span class="n">b</span> <span class="k">else</span> <span class="n">L</span> <span class="k">if</span> <span class="n">a</span> <span class="o">&lt;</span> <span class="n">b</span> <span class="k">else</span> <span class="n">E</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span>
<span class="n">D</span><span class="p">[</span><span class="s1">&#39;cmp&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">cmp_</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[21]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;1 0 [&#39;G&#39;] [&#39;E&#39;] [&#39;L&#39;] cmp&quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;1 0 [&#39;G&#39;] [&#39;E&#39;] [&#39;L&#39;] cmp&quot;</span><span class="p">)</span>
@ -12589,7 +12566,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[22]:</div> <div class="prompt input_prompt">In&nbsp;[21]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;1 1 [&#39;G&#39;] [&#39;E&#39;] [&#39;L&#39;] cmp&quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;1 1 [&#39;G&#39;] [&#39;E&#39;] [&#39;L&#39;] cmp&quot;</span><span class="p">)</span>
@ -12620,7 +12597,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[23]:</div> <div class="prompt input_prompt">In&nbsp;[22]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;0 1 [&#39;G&#39;] [&#39;E&#39;] [&#39;L&#39;] cmp&quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;0 1 [&#39;G&#39;] [&#39;E&#39;] [&#39;L&#39;] cmp&quot;</span><span class="p">)</span>
@ -12706,7 +12683,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[24]:</div> <div class="prompt input_prompt">In&nbsp;[23]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;P == over [popop popop first] nullary&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;P == over [popop popop first] nullary&#39;</span><span class="p">)</span>
@ -12755,7 +12732,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[25]:</div> <div class="prompt input_prompt">In&nbsp;[24]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec&#39;</span><span class="p">)</span>
@ -12768,7 +12745,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[26]:</div> <div class="prompt input_prompt">In&nbsp;[25]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] 23 &quot;b&quot; Tree-add 88 &quot;a&quot; Tree-add 44 &quot;c&quot; Tree-add&#39;</span><span class="p">)</span> <span class="c1"># Still works.</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] 23 &quot;b&quot; Tree-add 88 &quot;a&quot; Tree-add 44 &quot;c&quot; Tree-add&#39;</span><span class="p">)</span> <span class="c1"># Still works.</span>
@ -12938,7 +12915,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[27]:</div> <div class="prompt input_prompt">In&nbsp;[26]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;Tree-iter == [not] [pop] roll&lt; [dupdip rest rest] cons [step] genrec&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;Tree-iter == [not] [pop] roll&lt; [dupdip rest rest] cons [step] genrec&#39;</span><span class="p">)</span>
@ -12959,7 +12936,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[28]:</div> <div class="prompt input_prompt">In&nbsp;[27]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] [foo] Tree-iter&#39;</span><span class="p">)</span> <span class="c1"># It doesn&#39;t matter what F is as it won&#39;t be used.</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] [foo] Tree-iter&#39;</span><span class="p">)</span> <span class="c1"># It doesn&#39;t matter what F is as it won&#39;t be used.</span>
@ -12990,7 +12967,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[29]:</div> <div class="prompt input_prompt">In&nbsp;[28]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;b&#39; 23 [&#39;a&#39; 88 [] []] [&#39;c&#39; 44 [] []]] [first] Tree-iter&quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;b&#39; 23 [&#39;a&#39; 88 [] []] [&#39;c&#39; 44 [] []]] [first] Tree-iter&quot;</span><span class="p">)</span>
@ -13021,7 +12998,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[30]:</div> <div class="prompt input_prompt">In&nbsp;[29]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;b&#39; 23 [&#39;a&#39; 88 [] []] [&#39;c&#39; 44 [] []]] [second] Tree-iter&quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;b&#39; 23 [&#39;a&#39; 88 [] []] [&#39;c&#39; 44 [] []]] [second] Tree-iter&quot;</span><span class="p">)</span>
@ -13061,7 +13038,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[31]:</div> <div class="prompt input_prompt">In&nbsp;[30]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step&#39;</span><span class="p">)</span>
@ -13092,7 +13069,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[32]:</div> <div class="prompt input_prompt">In&nbsp;[31]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;to_set == [] swap [0 swap Tree-add] step&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;to_set == [] swap [0 swap Tree-add] step&#39;</span><span class="p">)</span>
@ -13105,7 +13082,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[33]:</div> <div class="prompt input_prompt">In&nbsp;[32]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[3 9 5 2 8 6 7 8 4] to_set&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[3 9 5 2 8 6 7 8 4] to_set&#39;</span><span class="p">)</span>
@ -13145,7 +13122,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[34]:</div> <div class="prompt input_prompt">In&nbsp;[33]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;unique == [to_set [first] Tree-iter] cons run&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;unique == [to_set [first] Tree-iter] cons run&#39;</span><span class="p">)</span>
@ -13158,7 +13135,7 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[35]:</div> <div class="prompt input_prompt">In&nbsp;[34]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique&#39;</span><span class="p">)</span> <span class="c1"># Filter duplicate items.</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique&#39;</span><span class="p">)</span> <span class="c1"># Filter duplicate items.</span>
@ -13302,7 +13279,7 @@ Tree-iter-order == [not] [pop] [dup third] [proc_left proc_current proc_right] g
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[36]:</div> <div class="prompt input_prompt">In&nbsp;[35]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="c1">#define(&#39;Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec&#39;)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="c1">#define(&#39;Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec&#39;)</span>
@ -13328,7 +13305,7 @@ Tree-iter-order == [not] [pop] [dup third] [proc_left proc_current proc_right] g
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[37]:</div> <div class="prompt input_prompt">In&nbsp;[36]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order&#39;</span><span class="p">)</span>
@ -13361,7 +13338,7 @@ Tree-iter-order == [not] [pop] [dup third] [proc_left proc_current proc_right] g
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<p>Parameterizing the <code>[F]</code> function is left as an exercise for the reader (for now.)</p> <p>Parameterizing the <code>[F]</code> function is left as an exercise for the reader.</p>
</div> </div>
</div> </div>
@ -13528,7 +13505,7 @@ Tree-get == [pop not] swap [] [P [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[38]:</div> <div class="prompt input_prompt">In&nbsp;[37]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="c1"># I don&#39;t want to deal with name conflicts with the above so I&#39;m inlining everything here.</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="c1"># I don&#39;t want to deal with name conflicts with the above so I&#39;m inlining everything here.</span>
@ -13555,7 +13532,7 @@ Tree-get == [pop not] swap [] [P [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[39]:</div> <div class="prompt input_prompt">In&nbsp;[38]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[&quot;gary&quot; 23 [] []] &quot;mike&quot; [popd &quot; not in tree&quot; +] Tree-get&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[&quot;gary&quot; 23 [] []] &quot;mike&quot; [popd &quot; not in tree&quot; +] Tree-get&#39;</span><span class="p">)</span>
@ -13586,7 +13563,7 @@ Tree-get == [pop not] swap [] [P [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[40]:</div> <div class="prompt input_prompt">In&nbsp;[39]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[&quot;gary&quot; 23 [] []] &quot;gary&quot; [popop &quot;err&quot;] Tree-get&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[&quot;gary&quot; 23 [] []] &quot;gary&quot; [popop &quot;err&quot;] Tree-get&#39;</span><span class="p">)</span>
@ -13617,7 +13594,7 @@ Tree-get == [pop not] swap [] [P [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[41]:</div> <div class="prompt input_prompt">In&nbsp;[40]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;&#39;&#39;</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;&#39;&#39;</span>
@ -13654,7 +13631,7 @@ Tree-get == [pop not] swap [] [P [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[52]:</div> <div class="prompt input_prompt">In&nbsp;[41]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;&#39;&#39;</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;&#39;&#39;</span>
@ -13847,59 +13824,6 @@ T&lt; == [dipdd] cons infra</code></pre>
</div> </div>
</div> </div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[42]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.library</span> <span class="kn">import</span> <span class="n">FunctionWrapper</span><span class="p">,</span> <span class="n">S_ifte</span>
<span class="nd">@FunctionWrapper</span>
<span class="k">def</span> <span class="nf">cond</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
<span class="sd">&#39;&#39;&#39;</span>
<span class="sd"> like a case statement; works by rewriting into a chain of ifte.</span>
<span class="sd"> [..[[Bi] Ti]..[D]] -&gt; ...</span>
<span class="sd"> [[[B0] T0] [[B1] T1] [D]] cond</span>
<span class="sd"> -----------------------------------------</span>
<span class="sd"> [B0] [T0] [[B1] [T1] [D] ifte] ifte</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="n">conditions</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
<span class="k">if</span> <span class="n">conditions</span><span class="p">:</span>
<span class="n">expression</span> <span class="o">=</span> <span class="n">_cond</span><span class="p">(</span><span class="n">conditions</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># Attempt to preload the args to first ifte.</span>
<span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="p">(</span><span class="n">E</span><span class="p">,</span> <span class="n">expression</span><span class="p">)))</span> <span class="o">=</span> <span class="n">expression</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="c1"># If, for any reason, the argument to cond should happen to contain</span>
<span class="c1"># only the default clause then this optimization will fail.</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">stack</span> <span class="o">=</span> <span class="p">(</span><span class="n">E</span><span class="p">,</span> <span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span>
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span>
<span class="k">def</span> <span class="nf">_cond</span><span class="p">(</span><span class="n">conditions</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
<span class="p">(</span><span class="n">clause</span><span class="p">,</span> <span class="n">rest</span><span class="p">)</span> <span class="o">=</span> <span class="n">conditions</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">rest</span><span class="p">:</span> <span class="c1"># clause is [D]</span>
<span class="k">return</span> <span class="n">clause</span>
<span class="n">P</span><span class="p">,</span> <span class="n">T</span> <span class="o">=</span> <span class="n">clause</span>
<span class="k">return</span> <span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="p">(</span><span class="n">_cond</span><span class="p">(</span><span class="n">rest</span><span class="p">,</span> <span class="p">()),</span> <span class="p">(</span><span class="n">S_ifte</span><span class="p">,</span> <span class="n">expression</span><span class="p">))))</span>
<span class="n">D</span><span class="p">[</span><span class="s1">&#39;cond&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">cond</span>
</pre></div>
</div>
</div>
</div>
</div> </div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt"> <div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div> </div>
@ -14198,7 +14122,7 @@ E == [
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<p>Minor rearrangement:</p> <p>Minor rearrangement, move <code>dup</code> into <code>W</code>:</p>
<pre><code>W == dup [fourth] [fourth] while uncons uncons pop over <pre><code>W == dup [fourth] [fourth] while uncons uncons pop over
E == roll&gt; popop rest [W] dip cons dipd swap E == roll&gt; popop rest [W] dip cons dipd swap
@ -14218,9 +14142,9 @@ E == [
<h3 id="Refactoring">Refactoring<a class="anchor-link" href="#Refactoring">&#182;</a></h3> <h3 id="Refactoring">Refactoring<a class="anchor-link" href="#Refactoring">&#182;</a></h3>
<pre><code>W.rightmost == [fourth] [fourth] while <pre><code>W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop W.unpack == uncons uncons pop
W == dup W.rightmost W.unpack over
E.clear_stuff == roll&gt; popop rest E.clear_stuff == roll&gt; popop rest
E.delete == cons dipd E.delete == cons dipd
W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap E.0 == E.clear_stuff [W] dip E.delete swap
E == [ E == [
[[pop third not] pop fourth] [[pop third not] pop fourth]
@ -14241,7 +14165,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[43]:</div> <div class="prompt input_prompt">In&nbsp;[42]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">DefinitionWrapper</span><span class="o">.</span><span class="n">add_definitions</span><span class="p">(</span><span class="s1">&#39;&#39;&#39;</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">DefinitionWrapper</span><span class="o">.</span><span class="n">add_definitions</span><span class="p">(</span><span class="s1">&#39;&#39;&#39;</span>
@ -14258,7 +14182,8 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
<span class="s1">T&lt; == [dipdd] cons infra</span> <span class="s1">T&lt; == [dipdd] cons infra</span>
<span class="s1">R0 == over first swap dup</span> <span class="s1">R0 == over first swap dup</span>
<span class="s1">R1 == cons roll&gt; [T&gt;] [E] [T&lt;] cmp</span> <span class="s1">R1 == cons roll&gt; [T&gt;] [E] [T&lt;] cmp</span>
<span class="s1">Tree-Delete == [pop not] [pop] [R0] [R1] genrec&#39;&#39;&#39;</span><span class="p">,</span> <span class="n">D</span><span class="p">)</span> <span class="s1">Tree-Delete == [pop not] [pop] [R0] [R1] genrec</span>
<span class="s1">&#39;&#39;&#39;</span><span class="p">,</span> <span class="n">D</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -14268,7 +14193,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[44]:</div> <div class="prompt input_prompt">In&nbsp;[43]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;c&#39; Tree-Delete &quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;c&#39; Tree-Delete &quot;</span><span class="p">)</span>
@ -14299,7 +14224,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[45]:</div> <div class="prompt input_prompt">In&nbsp;[44]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;b&#39; Tree-Delete &quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;b&#39; Tree-Delete &quot;</span><span class="p">)</span>
@ -14330,7 +14255,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[46]:</div> <div class="prompt input_prompt">In&nbsp;[45]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;a&#39; Tree-Delete &quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;a&#39; Tree-Delete &quot;</span><span class="p">)</span>
@ -14361,7 +14286,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[47]:</div> <div class="prompt input_prompt">In&nbsp;[46]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;der&#39; Tree-Delete &quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;der&#39; Tree-Delete &quot;</span><span class="p">)</span>
@ -14392,7 +14317,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[48]:</div> <div class="prompt input_prompt">In&nbsp;[47]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step&#39;</span><span class="p">)</span>
@ -14423,7 +14348,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[49]:</div> <div class="prompt input_prompt">In&nbsp;[48]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete &quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete &quot;</span><span class="p">)</span>
@ -14454,7 +14379,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[50]:</div> <div class="prompt input_prompt">In&nbsp;[49]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete &quot;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete &quot;</span><span class="p">)</span>

View File

@ -4,7 +4,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# Treating Trees I\n", "# Treating Trees I: Ordered Binary Trees\n",
"\n", "\n",
"Although any expression in Joy can be considered to describe a [tree](https://en.wikipedia.org/wiki/Tree_structure) with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about [ordered binary trees](https://en.wikipedia.org/wiki/Binary_search_tree) and how to make and use them.\n", "Although any expression in Joy can be considered to describe a [tree](https://en.wikipedia.org/wiki/Tree_structure) with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about [ordered binary trees](https://en.wikipedia.org/wiki/Binary_search_tree) and how to make and use them.\n",
"\n", "\n",
@ -92,7 +92,15 @@
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['k' 'v' [] []]\n"
]
}
],
"source": [ "source": [
"J('\"v\" \"k\" Tree-new')" "J('\"v\" \"k\" Tree-new')"
] ]
@ -521,7 +529,7 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Interlude: `cmp` combinator\n", "## Interlude: `cmp` combinator\n",
"Instead of mucking about with nested `ifte` combinators let's just go whole hog and define `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:\n", "Instead of mucking about with nested `ifte` combinators let's use `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:\n",
"\n", "\n",
" a b [G] [E] [L] cmp\n", " a b [G] [E] [L] cmp\n",
" ------------------------- a > b\n", " ------------------------- a > b\n",
@ -540,43 +548,6 @@
"cell_type": "code", "cell_type": "code",
"execution_count": 20, "execution_count": 20,
"metadata": {}, "metadata": {},
"outputs": [],
"source": [
"from joy.library import FunctionWrapper\n",
"from joy.utils.stack import pushback\n",
"from notebook_preamble import D\n",
"\n",
"\n",
"@FunctionWrapper\n",
"def cmp_(stack, expression, dictionary):\n",
" '''\n",
" cmp takes two values and three quoted programs on the stack and runs\n",
" one of the three depending on the results of comparing the two values:\n",
"\n",
" a b [G] [E] [L] cmp\n",
" ------------------------- a > b\n",
" G\n",
"\n",
" a b [G] [E] [L] cmp\n",
" ------------------------- a = b\n",
" E\n",
"\n",
" a b [G] [E] [L] cmp\n",
" ------------------------- a < b\n",
" L\n",
" '''\n",
" L, (E, (G, (b, (a, stack)))) = stack\n",
" expression = pushback(G if a > b else L if a < b else E, expression)\n",
" return stack, expression, dictionary\n",
"\n",
"\n",
"D['cmp'] = cmp_"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
@ -592,7 +563,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 22, "execution_count": 21,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -609,7 +580,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 22,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -674,7 +645,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 24, "execution_count": 23,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -713,7 +684,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 25, "execution_count": 24,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -722,7 +693,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 26, "execution_count": 25,
"metadata": { "metadata": {
"scrolled": false "scrolled": false
}, },
@ -865,7 +836,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 27, "execution_count": 26,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -881,7 +852,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 28, "execution_count": 27,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -898,7 +869,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 29, "execution_count": 28,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -915,7 +886,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 30, "execution_count": 29,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -940,7 +911,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 31, "execution_count": 30,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -957,7 +928,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 32, "execution_count": 31,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -966,7 +937,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 33, "execution_count": 32,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -990,7 +961,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 34, "execution_count": 33,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -999,7 +970,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 35, "execution_count": 34,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -1117,7 +1088,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 36, "execution_count": 35,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1141,7 +1112,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 37, "execution_count": 36,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1160,7 +1131,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Parameterizing the `[F]` function is left as an exercise for the reader (for now.)" "Parameterizing the `[F]` function is left as an exercise for the reader."
] ]
}, },
{ {
@ -1310,7 +1281,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 38, "execution_count": 37,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1333,7 +1304,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 39, "execution_count": 38,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1350,7 +1321,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 40, "execution_count": 39,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1367,7 +1338,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 41, "execution_count": 40,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1390,7 +1361,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 52, "execution_count": 41,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1552,55 +1523,6 @@
"We have to handle three cases, so let's use `cond`." "We have to handle three cases, so let's use `cond`."
] ]
}, },
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
"from joy.library import FunctionWrapper, S_ifte\n",
"\n",
"\n",
"@FunctionWrapper\n",
"def cond(stack, expression, dictionary):\n",
" '''\n",
" like a case statement; works by rewriting into a chain of ifte.\n",
"\n",
" [..[[Bi] Ti]..[D]] -> ...\n",
"\n",
"\n",
" [[[B0] T0] [[B1] T1] [D]] cond\n",
" -----------------------------------------\n",
" [B0] [T0] [[B1] [T1] [D] ifte] ifte\n",
"\n",
" '''\n",
" conditions, stack = stack\n",
" if conditions:\n",
" expression = _cond(conditions, expression)\n",
" try:\n",
" # Attempt to preload the args to first ifte.\n",
" (P, (T, (E, expression))) = expression\n",
" except ValueError:\n",
" # If, for any reason, the argument to cond should happen to contain\n",
" # only the default clause then this optimization will fail.\n",
" pass\n",
" else:\n",
" stack = (E, (T, (P, stack)))\n",
" return stack, expression, dictionary\n",
"\n",
"\n",
"def _cond(conditions, expression):\n",
" (clause, rest) = conditions\n",
" if not rest: # clause is [D]\n",
" return clause\n",
" P, T = clause\n",
" return (P, (T, (_cond(rest, ()), (S_ifte, expression))))\n",
"\n",
"\n",
"\n",
"D['cond'] = cond"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
@ -1860,7 +1782,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Minor rearrangement:\n", "Minor rearrangement, move `dup` into `W`:\n",
"\n", "\n",
" W == dup [fourth] [fourth] while uncons uncons pop over\n", " W == dup [fourth] [fourth] while uncons uncons pop over\n",
" E == roll> popop rest [W] dip cons dipd swap\n", " E == roll> popop rest [W] dip cons dipd swap\n",
@ -1879,9 +1801,9 @@
"\n", "\n",
" W.rightmost == [fourth] [fourth] while\n", " W.rightmost == [fourth] [fourth] while\n",
" W.unpack == uncons uncons pop\n", " W.unpack == uncons uncons pop\n",
" W == dup W.rightmost W.unpack over\n",
" E.clear_stuff == roll> popop rest\n", " E.clear_stuff == roll> popop rest\n",
" E.delete == cons dipd\n", " E.delete == cons dipd\n",
" W == dup W.rightmost W.unpack over\n",
" E.0 == E.clear_stuff [W] dip E.delete swap\n", " E.0 == E.clear_stuff [W] dip E.delete swap\n",
" E == [\n", " E == [\n",
" [[pop third not] pop fourth]\n", " [[pop third not] pop fourth]\n",
@ -1899,7 +1821,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 43, "execution_count": 42,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1917,12 +1839,13 @@
"T< == [dipdd] cons infra\n", "T< == [dipdd] cons infra\n",
"R0 == over first swap dup\n", "R0 == over first swap dup\n",
"R1 == cons roll> [T>] [E] [T<] cmp\n", "R1 == cons roll> [T>] [E] [T<] cmp\n",
"Tree-Delete == [pop not] [pop] [R0] [R1] genrec''', D)" "Tree-Delete == [pop not] [pop] [R0] [R1] genrec\n",
"''', D)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 44, "execution_count": 43,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1939,7 +1862,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 45, "execution_count": 44,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1956,7 +1879,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 46, "execution_count": 45,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1973,7 +1896,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 47, "execution_count": 46,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -1990,7 +1913,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 48, "execution_count": 47,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -2007,7 +1930,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 49, "execution_count": 48,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -2024,7 +1947,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 50, "execution_count": 49,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -2099,11 +2022,6 @@
" Tree-delete == [pop not] [pop] [_Tree_delete_R0] [_Tree_delete_R1] genrec\n", " Tree-delete == [pop not] [pop] [_Tree_delete_R0] [_Tree_delete_R1] genrec\n",
"\n" "\n"
] ]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
} }
], ],
"metadata": { "metadata": {

View File

@ -1,5 +1,5 @@
# Treating Trees I # Treating Trees I: Ordered Binary Trees
Although any expression in Joy can be considered to describe a [tree](https://en.wikipedia.org/wiki/Tree_structure) with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about [ordered binary trees](https://en.wikipedia.org/wiki/Binary_search_tree) and how to make and use them. Although any expression in Joy can be considered to describe a [tree](https://en.wikipedia.org/wiki/Tree_structure) with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about [ordered binary trees](https://en.wikipedia.org/wiki/Binary_search_tree) and how to make and use them.
@ -64,6 +64,9 @@ define('Tree-new == swap [[] []] cons cons')
J('"v" "k" Tree-new') J('"v" "k" Tree-new')
``` ```
['k' 'v' [] []]
(As an implementation detail, the `[[] []]` literal used in the definition of `Tree-new` will be reused to supply the *constant* tail for *all* new nodes produced by it. This is one of those cases where you get amortized storage "for free" by using [persistent datastructures](https://en.wikipedia.org/wiki/Persistent_data_structure). Because the tail, which is `((), ((), ()))` in Python, is immutable and embedded in the definition body for `Tree-new`, all new nodes can reuse it as their own tail without fear that some other code somewhere will change it.) (As an implementation detail, the `[[] []]` literal used in the definition of `Tree-new` will be reused to supply the *constant* tail for *all* new nodes produced by it. This is one of those cases where you get amortized storage "for free" by using [persistent datastructures](https://en.wikipedia.org/wiki/Persistent_data_structure). Because the tail, which is `((), ((), ()))` in Python, is immutable and embedded in the definition body for `Tree-new`, all new nodes can reuse it as their own tail without fear that some other code somewhere will change it.)
### Adding to a non-empty node. ### Adding to a non-empty node.
@ -302,7 +305,7 @@ J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step')
## Interlude: `cmp` combinator ## Interlude: `cmp` combinator
Instead of mucking about with nested `ifte` combinators let's just go whole hog and define `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values: Instead of mucking about with nested `ifte` combinators let's use `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp a b [G] [E] [L] cmp
------------------------- a > b ------------------------- a > b
@ -317,39 +320,6 @@ Instead of mucking about with nested `ifte` combinators let's just go whole hog
L L
```python
from joy.library import FunctionWrapper
from joy.utils.stack import pushback
from notebook_preamble import D
@FunctionWrapper
def cmp_(stack, expression, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack
expression = pushback(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary
D['cmp'] = cmp_
```
```python ```python
J("1 0 ['G'] ['E'] ['L'] cmp") J("1 0 ['G'] ['E'] ['L'] cmp")
``` ```
@ -681,7 +651,7 @@ J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order')
2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9
Parameterizing the `[F]` function is left as an exercise for the reader (for now.) Parameterizing the `[F]` function is left as an exercise for the reader.
## Getting values by key ## Getting values by key
Let's derive a function that accepts a tree and a key and returns the value associated with that key. Let's derive a function that accepts a tree and a key and returns the value associated with that key.
@ -937,51 +907,6 @@ We have found the node in the tree where `key` equals `node_key`. We need to re
We have to handle three cases, so let's use `cond`. We have to handle three cases, so let's use `cond`.
```python
from joy.library import FunctionWrapper, S_ifte
@FunctionWrapper
def cond(stack, expression, dictionary):
'''
like a case statement; works by rewriting into a chain of ifte.
[..[[Bi] Ti]..[D]] -> ...
[[[B0] T0] [[B1] T1] [D]] cond
-----------------------------------------
[B0] [T0] [[B1] [T1] [D] ifte] ifte
'''
conditions, stack = stack
if conditions:
expression = _cond(conditions, expression)
try:
# Attempt to preload the args to first ifte.
(P, (T, (E, expression))) = expression
except ValueError:
# If, for any reason, the argument to cond should happen to contain
# only the default clause then this optimization will fail.
pass
else:
stack = (E, (T, (P, stack)))
return stack, expression, dictionary
def _cond(conditions, expression):
(clause, rest) = conditions
if not rest: # clause is [D]
return clause
P, T = clause
return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
D['cond'] = cond
```
#### One or more child nodes are `[]` #### One or more child nodes are `[]`
The first two cases are symmetrical: if we only have one non-empty child node return it. If both child nodes are empty return an empty node. The first two cases are symmetrical: if we only have one non-empty child node return it. If both child nodes are empty return an empty node.
@ -1127,7 +1052,7 @@ Substituting:
[[E] cons infra] [[E] cons infra]
] cond ] cond
Minor rearrangement: Minor rearrangement, move `dup` into `W`:
W == dup [fourth] [fourth] while uncons uncons pop over W == dup [fourth] [fourth] while uncons uncons pop over
E == roll> popop rest [W] dip cons dipd swap E == roll> popop rest [W] dip cons dipd swap
@ -1141,9 +1066,9 @@ Minor rearrangement:
W.rightmost == [fourth] [fourth] while W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop W.unpack == uncons uncons pop
W == dup W.rightmost W.unpack over
E.clear_stuff == roll> popop rest E.clear_stuff == roll> popop rest
E.delete == cons dipd E.delete == cons dipd
W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap E.0 == E.clear_stuff [W] dip E.delete swap
E == [ E == [
[[pop third not] pop fourth] [[pop third not] pop fourth]
@ -1174,7 +1099,8 @@ T> == [dipd] cons infra
T< == [dipdd] cons infra T< == [dipdd] cons infra
R0 == over first swap dup R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp R1 == cons roll> [T>] [E] [T<] cmp
Tree-Delete == [pop not] [pop] [R0] [R1] genrec''', D) Tree-Delete == [pop not] [pop] [R0] [R1] genrec
''', D)
``` ```

View File

@ -1,6 +1,6 @@
Treating Trees I Treating Trees I: Ordered Binary Trees
================ ======================================
Although any expression in Joy can be considered to describe a Although any expression in Joy can be considered to describe a
`tree <https://en.wikipedia.org/wiki/Tree_structure>`__ with the quotes `tree <https://en.wikipedia.org/wiki/Tree_structure>`__ with the quotes
@ -96,6 +96,12 @@ Definition:
J('"v" "k" Tree-new') J('"v" "k" Tree-new')
.. parsed-literal::
['k' 'v' [] []]
(As an implementation detail, the ``[[] []]`` literal used in the (As an implementation detail, the ``[[] []]`` literal used in the
definition of ``Tree-new`` will be reused to supply the *constant* tail definition of ``Tree-new`` will be reused to supply the *constant* tail
for *all* new nodes produced by it. This is one of those cases where you for *all* new nodes produced by it. This is one of those cases where you
@ -420,10 +426,10 @@ Examples
Interlude: ``cmp`` combinator Interlude: ``cmp`` combinator
----------------------------- -----------------------------
Instead of mucking about with nested ``ifte`` combinators let's just go Instead of mucking about with nested ``ifte`` combinators let's use
whole hog and define ``cmp`` which takes two values and three quoted ``cmp`` which takes two values and three quoted programs on the stack
programs on the stack and runs one of the three depending on the results and runs one of the three depending on the results of comparing the two
of comparing the two values: values:
:: ::
@ -439,38 +445,6 @@ of comparing the two values:
------------------------- a < b ------------------------- a < b
L L
.. code:: ipython2
from joy.library import FunctionWrapper
from joy.utils.stack import pushback
from notebook_preamble import D
@FunctionWrapper
def cmp_(stack, expression, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack
expression = pushback(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary
D['cmp'] = cmp_
.. code:: ipython2 .. code:: ipython2
J("1 0 ['G'] ['E'] ['L'] cmp") J("1 0 ['G'] ['E'] ['L'] cmp")
@ -930,7 +904,7 @@ Now we can sort sequences.
Parameterizing the ``[F]`` function is left as an exercise for the Parameterizing the ``[F]`` function is left as an exercise for the
reader (for now.) reader.
Getting values by key Getting values by key
--------------------- ---------------------
@ -1291,50 +1265,6 @@ need to replace the current node with something
We have to handle three cases, so let's use ``cond``. We have to handle three cases, so let's use ``cond``.
.. code:: ipython2
from joy.library import FunctionWrapper, S_ifte
@FunctionWrapper
def cond(stack, expression, dictionary):
'''
like a case statement; works by rewriting into a chain of ifte.
[..[[Bi] Ti]..[D]] -> ...
[[[B0] T0] [[B1] T1] [D]] cond
-----------------------------------------
[B0] [T0] [[B1] [T1] [D] ifte] ifte
'''
conditions, stack = stack
if conditions:
expression = _cond(conditions, expression)
try:
# Attempt to preload the args to first ifte.
(P, (T, (E, expression))) = expression
except ValueError:
# If, for any reason, the argument to cond should happen to contain
# only the default clause then this optimization will fail.
pass
else:
stack = (E, (T, (P, stack)))
return stack, expression, dictionary
def _cond(conditions, expression):
(clause, rest) = conditions
if not rest: # clause is [D]
return clause
P, T = clause
return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
D['cond'] = cond
One or more child nodes are ``[]`` One or more child nodes are ``[]``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -1534,7 +1464,7 @@ Substituting:
[[E] cons infra] [[E] cons infra]
] cond ] cond
Minor rearrangement: Minor rearrangement, move ``dup`` into ``W``:
:: ::
@ -1553,9 +1483,9 @@ Refactoring
W.rightmost == [fourth] [fourth] while W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop W.unpack == uncons uncons pop
W == dup W.rightmost W.unpack over
E.clear_stuff == roll> popop rest E.clear_stuff == roll> popop rest
E.delete == cons dipd E.delete == cons dipd
W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap E.0 == E.clear_stuff [W] dip E.delete swap
E == [ E == [
[[pop third not] pop fourth] [[pop third not] pop fourth]
@ -1587,7 +1517,8 @@ program.
T< == [dipdd] cons infra T< == [dipdd] cons infra
R0 == over first swap dup R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp R1 == cons roll> [T>] [E] [T<] cmp
Tree-Delete == [pop not] [pop] [R0] [R1] genrec''', D) Tree-Delete == [pop not] [pop] [R0] [R1] genrec
''', D)
.. code:: ipython2 .. code:: ipython2