Bunches of new docs.
Type inference! A new treatment of recursion combinator patterns.
This commit is contained in:
parent
049cfd22b7
commit
ca05ea404a
4
Makefile
4
Makefile
|
|
@ -13,6 +13,10 @@ clean:
|
|||
sdist:
|
||||
python ./setup.py sdist
|
||||
|
||||
joy/utils/generated_library.py: joy/utils/types.py
|
||||
python -c 'import joy.utils.types ; joy.utils.types.generate_library_code()' > $@
|
||||
|
||||
|
||||
# In order to support testing the code as installed
|
||||
# create a virtualenv and install the source dist zip there.
|
||||
test: sdist
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ $(docs_rst): %.rst : %.ipynb
|
|||
python -m nbconvert --to rst $<
|
||||
|
||||
|
||||
move_us = Generator_Programs.rst Newton-Raphson.rst Ordered_Binary_Trees.rst Quadratic.rst Replacing.rst Treestep.rst Zipper.rst
|
||||
move_us = Generator_Programs.rst Newton-Raphson.rst Ordered_Binary_Trees.rst Quadratic.rst Recursion_Combinators.rst Replacing.rst Treestep.rst Types.rst Zipper.rst
|
||||
|
||||
mov: $(move_us)
|
||||
cp -v $? ./sphinx_docs/notebooks/
|
||||
|
|
|
|||
|
|
@ -11771,14 +11771,6 @@ div#notebook {
|
|||
<div tabindex="-1" id="notebook" class="border-box-sizing">
|
||||
<div class="container" id="notebook-container">
|
||||
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h1 id="Quadratic-formula"><a href="https://en.wikipedia.org/wiki/Quadratic_formula">Quadratic formula</a><a class="anchor-link" href="#Quadratic-formula">¶</a></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing code_cell rendered">
|
||||
<div class="input">
|
||||
<div class="prompt input_prompt">In [1]:</div>
|
||||
|
|
@ -11791,6 +11783,14 @@ div#notebook {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h1 id="Quadratic-formula"><a href="https://en.wikipedia.org/wiki/Quadratic_formula">Quadratic formula</a><a class="anchor-link" href="#Quadratic-formula">¶</a></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
|
|
@ -11806,9 +11806,9 @@ div#notebook {
|
|||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
|
||||
<pre><code> -b +/- sqrt(b^2 - 4 * a * c)
|
||||
-----------------------------
|
||||
2 * a</code></pre>
|
||||
<pre><code> -b ± sqrt(b^2 - 4 * a * c)
|
||||
--------------------------------
|
||||
2 * a</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -11826,11 +11826,61 @@ div#notebook {
|
|||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h2 id="Write-a-straightforward-program-with-variable-names.">Write a straightforward program with variable names.<a class="anchor-link" href="#Write-a-straightforward-program-with-variable-names.">¶</a></h2>
|
||||
<pre><code>b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
<h2 id="Write-a-straightforward-program-with-variable-names.">Write a straightforward program with variable names.<a class="anchor-link" href="#Write-a-straightforward-program-with-variable-names.">¶</a></h2><p>This math translates to Joy code in a straightforward manner. We are going to use named variables to keep track of the arguments, then write a definition without them.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="-b"><code>-b</code><a class="anchor-link" href="#-b">¶</a></h3>
|
||||
<pre><code>b neg</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="sqrt(b^2---4-*-a-*-c)"><code>sqrt(b^2 - 4 * a * c)</code><a class="anchor-link" href="#sqrt(b^2---4-*-a-*-c)">¶</a></h3>
|
||||
<pre><code>b sqr 4 a c * * - sqrt</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="/2a"><code>/2a</code><a class="anchor-link" href="#/2a">¶</a></h3>
|
||||
<pre><code>a 2 * /</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="±"><code>±</code><a class="anchor-link" href="#±">¶</a></h3><p>There is a function <code>pm</code> that accepts two values on the stack and replaces them with their sum and difference.</p>
|
||||
|
||||
<pre><code>pm == [+] [-] cleave popdd</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="Putting-Them-Together">Putting Them Together<a class="anchor-link" href="#Putting-Them-Together">¶</a></h3>
|
||||
<pre><code>b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
|
||||
</code></pre>
|
||||
<p>We use <code>cleave</code> to compute the sum and difference and then <code>app2</code> to finish computing both roots using a quoted program <code>[2a truediv]</code> built with <code>cons</code>.</p>
|
||||
<p>We use <code>app2</code> to compute both roots by using a quoted program <code>[2a /]</code> built with <code>cons</code>.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -11839,48 +11889,16 @@ div#notebook {
|
|||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="Check-it.">Check it.<a class="anchor-link" href="#Check-it.">¶</a></h3><p>Evaluating by hand:</p>
|
||||
<h2 id="Derive-a-definition.">Derive a definition.<a class="anchor-link" href="#Derive-a-definition.">¶</a></h2><p>Working backwards we use <code>dip</code> and <code>dipd</code> to extract the code from the variables:</p>
|
||||
|
||||
<pre><code> b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4ac - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2-4ac sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b sqrt(b^2-4ac) [+] [-] cleave a 2 * [truediv] cons app2
|
||||
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) a 2 * [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) 2a [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) [2a truediv] app2
|
||||
-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a
|
||||
<pre><code>b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
|
||||
</code></pre>
|
||||
<p>(Eventually we’ll be able to use e.g. Sympy versions of the Joy commands to do this sort of thing symbolically. This is part of what is meant by a “categorical” language.)</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="Cleanup">Cleanup<a class="anchor-link" href="#Cleanup">¶</a></h3>
|
||||
<pre><code>-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a roll< pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a -b pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h2 id="Derive-a-definition.">Derive a definition.<a class="anchor-link" href="#Derive-a-definition.">¶</a></h2>
|
||||
<pre><code>b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop</code></pre>
|
||||
<p>The three arguments are to the left, so we can "chop off" everything to the right and say it's the definition of the <code>quadratic</code> function:</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -11890,13 +11908,22 @@ b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truedi
|
|||
<div class="prompt input_prompt">In [2]:</div>
|
||||
<div class="inner_cell">
|
||||
<div class="input_area">
|
||||
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">'quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop'</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">'quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<p>Let's try it out:</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing code_cell rendered">
|
||||
<div class="input">
|
||||
|
|
@ -11933,26 +11960,7 @@ b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truedi
|
|||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h2 id="Simplify">Simplify<a class="anchor-link" href="#Simplify">¶</a></h2><p>We can define a <code>pm</code> plus-or-minus function:</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
|
||||
<pre><code>pm == [+] [-] cleave popdd</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<p>Then <code>quadratic</code> becomes:</p>
|
||||
<p>If you look at the Joy evaluation trace you can see that the first few lines are the <code>dip</code> and <code>dipd</code> combinators building the main program by incorporating the values on the stack. Then that program runs and you get the results. This is pretty typical of Joy code.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -11962,20 +11970,7 @@ b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truedi
|
|||
<div class="prompt input_prompt">In [4]:</div>
|
||||
<div class="inner_cell">
|
||||
<div class="input_area">
|
||||
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">'quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2'</span><span class="p">)</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 [5]:</div>
|
||||
<div class="inner_cell">
|
||||
<div class="input_area">
|
||||
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">'3 1 1 quadratic'</span><span class="p">)</span>
|
||||
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">'-5 1 4 quadratic'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
|
|
@ -11992,116 +11987,51 @@ b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truedi
|
|||
|
||||
|
||||
<div class="output_subarea output_stream output_stdout output_text">
|
||||
<pre>-0.3819660112501051 -2.618033988749895
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<h3 id="Define-a-"native"-pm-function.">Define a "native" <code>pm</code> function.<a class="anchor-link" href="#Define-a-"native"-pm-function.">¶</a></h3><p>The definition of <code>pm</code> above is pretty elegant, but the implementation takes a lot of steps relative to what it's accomplishing. Since we are likely to use <code>pm</code> more than once in the future, let's write a primitive in Python and add it to the dictionary. (This has been done already.)</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing code_cell rendered">
|
||||
<div class="input">
|
||||
<div class="prompt input_prompt">In [6]:</div>
|
||||
<div class="inner_cell">
|
||||
<div class="input_area">
|
||||
<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">pm</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="n">a</span><span class="p">,</span> <span class="p">(</span><span class="n">b</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">p</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="o">=</span> <span class="n">b</span> <span class="o">+</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">-</span> <span class="n">a</span>
|
||||
<span class="k">return</span> <span class="n">m</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>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||||
</div>
|
||||
<div class="inner_cell">
|
||||
<div class="text_cell_render border-box-sizing rendered_html">
|
||||
<p>The resulting trace is short enough to fit on a page.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell border-box-sizing code_cell rendered">
|
||||
<div class="input">
|
||||
<div class="prompt input_prompt">In [7]:</div>
|
||||
<div class="inner_cell">
|
||||
<div class="input_area">
|
||||
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">'3 1 1 quadratic'</span><span class="p">)</span>
|
||||
</pre></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> . 3 1 1 quadratic
|
||||
3 . 1 1 quadratic
|
||||
3 1 . 1 quadratic
|
||||
3 1 1 . quadratic
|
||||
3 1 1 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [truediv] cons app2
|
||||
3 1 1 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 1 1 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . [neg] dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 [neg] . dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . neg 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 . 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . dup mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 3 . mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 . 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 1 . * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 5 . sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 2.23606797749979 . pm 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 . 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 . 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 2 . * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 . [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 [truediv] . cons app2
|
||||
-0.7639320225002102 -5.23606797749979 [2 truediv] . app2
|
||||
[-0.7639320225002102] [2 truediv] . infra first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 . 2 truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 2 . truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [] . swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
[-0.3819660112501051] . first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] . [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] [2 truediv] . infra first
|
||||
-5.23606797749979 . 2 truediv [-0.3819660112501051] swaack first
|
||||
-5.23606797749979 2 . truediv [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 . [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 [-0.3819660112501051] . swaack first
|
||||
-0.3819660112501051 [-2.618033988749895] . first
|
||||
-0.3819660112501051 -2.618033988749895 .
|
||||
<pre> . -5 1 4 quadratic
|
||||
-5 . 1 4 quadratic
|
||||
-5 1 . 4 quadratic
|
||||
-5 1 4 . quadratic
|
||||
-5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2
|
||||
-5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 16 . - sqrt pm 1 2 * [/] cons app2
|
||||
5 9 . sqrt pm 1 2 * [/] cons app2
|
||||
5 3.0 . pm 1 2 * [/] cons app2
|
||||
8.0 2.0 . 1 2 * [/] cons app2
|
||||
8.0 2.0 1 . 2 * [/] cons app2
|
||||
8.0 2.0 1 2 . * [/] cons app2
|
||||
8.0 2.0 2 . [/] cons app2
|
||||
8.0 2.0 2 [/] . cons app2
|
||||
8.0 2.0 [2 /] . app2
|
||||
[8.0] [2 /] . infra first [2.0] [2 /] infra first
|
||||
8.0 . 2 / [] swaack first [2.0] [2 /] infra first
|
||||
8.0 2 . / [] swaack first [2.0] [2 /] infra first
|
||||
4.0 . [] swaack first [2.0] [2 /] infra first
|
||||
4.0 [] . swaack first [2.0] [2 /] infra first
|
||||
[4.0] . first [2.0] [2 /] infra first
|
||||
4.0 . [2.0] [2 /] infra first
|
||||
4.0 [2.0] . [2 /] infra first
|
||||
4.0 [2.0] [2 /] . infra first
|
||||
2.0 . 2 / [4.0] swaack first
|
||||
2.0 2 . / [4.0] swaack first
|
||||
1.0 . [4.0] swaack first
|
||||
1.0 [4.0] . swaack first
|
||||
4.0 [1.0] . first
|
||||
4.0 1.0 .
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,5 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
|
|
@ -16,6 +9,13 @@
|
|||
"from notebook_preamble import J, V, define"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
|
|
@ -27,9 +27,9 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
" -b +/- sqrt(b^2 - 4 * a * c)\n",
|
||||
" -----------------------------\n",
|
||||
" 2 * a"
|
||||
" -b ± sqrt(b^2 - 4 * a * c)\n",
|
||||
" --------------------------------\n",
|
||||
" 2 * a"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -44,42 +44,52 @@
|
|||
"metadata": {},
|
||||
"source": [
|
||||
"## Write a straightforward program with variable names.\n",
|
||||
"\n",
|
||||
" b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
|
||||
"\n",
|
||||
"We use `cleave` to compute the sum and difference and then `app2` to finish computing both roots using a quoted program `[2a truediv]` built with `cons`."
|
||||
"This math translates to Joy code in a straightforward manner. We are going to use named variables to keep track of the arguments, then write a definition without them."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Check it.\n",
|
||||
"Evaluating by hand:\n",
|
||||
"\n",
|
||||
" b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
|
||||
" -b b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
|
||||
" -b b^2 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
|
||||
" -b b^2 4ac - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
|
||||
" -b b^2-4ac sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
|
||||
" -b sqrt(b^2-4ac) [+] [-] cleave a 2 * [truediv] cons app2\n",
|
||||
"\n",
|
||||
" -b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) a 2 * [truediv] cons app2\n",
|
||||
" -b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) 2a [truediv] cons app2\n",
|
||||
" -b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) [2a truediv] app2\n",
|
||||
" -b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a\n",
|
||||
"\n",
|
||||
"(Eventually we’ll be able to use e.g. Sympy versions of the Joy commands to do this sort of thing symbolically. This is part of what is meant by a “categorical” language.)"
|
||||
"### `-b`\n",
|
||||
" b neg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Cleanup\n",
|
||||
" -b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a roll< pop\n",
|
||||
" -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a -b pop\n",
|
||||
" -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a"
|
||||
"### `sqrt(b^2 - 4 * a * c)`\n",
|
||||
" b sqr 4 a c * * - sqrt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `/2a`\n",
|
||||
" a 2 * /"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `±`\n",
|
||||
"There is a function `pm` that accepts two values on the stack and replaces them with their sum and difference.\n",
|
||||
"\n",
|
||||
" pm == [+] [-] cleave popdd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Putting Them Together\n",
|
||||
"\n",
|
||||
" b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
|
||||
"\n",
|
||||
"We use `app2` to compute both roots by using a quoted program `[2a /]` built with `cons`."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -87,12 +97,15 @@
|
|||
"metadata": {},
|
||||
"source": [
|
||||
"## Derive a definition.\n",
|
||||
"Working backwards we use `dip` and `dipd` to extract the code from the variables:\n",
|
||||
"\n",
|
||||
" b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop\n",
|
||||
" b [neg] dupdip sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop\n",
|
||||
" b a c [[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop\n",
|
||||
" b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop\n",
|
||||
" b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop"
|
||||
" b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
|
||||
" b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
|
||||
" b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2\n",
|
||||
" b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
|
||||
" b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
|
||||
"\n",
|
||||
"The three arguments are to the left, so we can \"chop off\" everything to the right and say it's the definition of the `quadratic` function:"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -101,7 +114,14 @@
|
|||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop')"
|
||||
"define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's try it out:"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -125,137 +145,76 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Simplify\n",
|
||||
"We can define a `pm` plus-or-minus function:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
" pm == [+] [-] cleave popdd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Then `quadratic` becomes:"
|
||||
"If you look at the Joy evaluation trace you can see that the first few lines are the `dip` and `dipd` combinators building the main program by incorporating the values on the stack. Then that program runs and you get the results. This is pretty typical of Joy code."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"-0.3819660112501051 -2.618033988749895\n"
|
||||
" . -5 1 4 quadratic\n",
|
||||
" -5 . 1 4 quadratic\n",
|
||||
" -5 1 . 4 quadratic\n",
|
||||
" -5 1 4 . quadratic\n",
|
||||
" -5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
|
||||
" -5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
|
||||
"-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2\n",
|
||||
" -5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" -5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" -5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" -5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" -5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 25 16 . - sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 9 . sqrt pm 1 2 * [/] cons app2\n",
|
||||
" 5 3.0 . pm 1 2 * [/] cons app2\n",
|
||||
" 8.0 2.0 . 1 2 * [/] cons app2\n",
|
||||
" 8.0 2.0 1 . 2 * [/] cons app2\n",
|
||||
" 8.0 2.0 1 2 . * [/] cons app2\n",
|
||||
" 8.0 2.0 2 . [/] cons app2\n",
|
||||
" 8.0 2.0 2 [/] . cons app2\n",
|
||||
" 8.0 2.0 [2 /] . app2\n",
|
||||
" [8.0] [2 /] . infra first [2.0] [2 /] infra first\n",
|
||||
" 8.0 . 2 / [] swaack first [2.0] [2 /] infra first\n",
|
||||
" 8.0 2 . / [] swaack first [2.0] [2 /] infra first\n",
|
||||
" 4.0 . [] swaack first [2.0] [2 /] infra first\n",
|
||||
" 4.0 [] . swaack first [2.0] [2 /] infra first\n",
|
||||
" [4.0] . first [2.0] [2 /] infra first\n",
|
||||
" 4.0 . [2.0] [2 /] infra first\n",
|
||||
" 4.0 [2.0] . [2 /] infra first\n",
|
||||
" 4.0 [2.0] [2 /] . infra first\n",
|
||||
" 2.0 . 2 / [4.0] swaack first\n",
|
||||
" 2.0 2 . / [4.0] swaack first\n",
|
||||
" 1.0 . [4.0] swaack first\n",
|
||||
" 1.0 [4.0] . swaack first\n",
|
||||
" 4.0 [1.0] . first\n",
|
||||
" 4.0 1.0 . \n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('3 1 1 quadratic')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Define a \"native\" `pm` function.\n",
|
||||
"The definition of `pm` above is pretty elegant, but the implementation takes a lot of steps relative to what it's accomplishing. Since we are likely to use `pm` more than once in the future, let's write a primitive in Python and add it to the dictionary. (This has been done already.)"
|
||||
"V('-5 1 4 quadratic')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def pm(stack):\n",
|
||||
" a, (b, stack) = stack\n",
|
||||
" p, m, = b + a, b - a\n",
|
||||
" return m, (p, stack)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The resulting trace is short enough to fit on a page."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" . 3 1 1 quadratic\n",
|
||||
" 3 . 1 1 quadratic\n",
|
||||
" 3 1 . 1 quadratic\n",
|
||||
" 3 1 1 . quadratic\n",
|
||||
" 3 1 1 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2\n",
|
||||
" 3 1 1 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2\n",
|
||||
" 3 1 1 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [truediv] cons app2\n",
|
||||
" 3 1 1 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" 3 1 1 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" 3 . [neg] dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" 3 [neg] . dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" 3 . neg 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 . 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 3 . sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 3 . dup mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 3 3 . mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 9 . 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 9 4 . 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 9 4 1 . 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 9 4 1 1 . * * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 9 4 1 . * - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 9 4 . - sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 5 . sqrt pm 1 2 * [truediv] cons app2\n",
|
||||
" -3 2.23606797749979 . pm 1 2 * [truediv] cons app2\n",
|
||||
" -0.7639320225002102 -5.23606797749979 . 1 2 * [truediv] cons app2\n",
|
||||
" -0.7639320225002102 -5.23606797749979 1 . 2 * [truediv] cons app2\n",
|
||||
" -0.7639320225002102 -5.23606797749979 1 2 . * [truediv] cons app2\n",
|
||||
" -0.7639320225002102 -5.23606797749979 2 . [truediv] cons app2\n",
|
||||
" -0.7639320225002102 -5.23606797749979 2 [truediv] . cons app2\n",
|
||||
" -0.7639320225002102 -5.23606797749979 [2 truediv] . app2\n",
|
||||
" [-0.7639320225002102] [2 truediv] . infra first [-5.23606797749979] [2 truediv] infra first\n",
|
||||
" -0.7639320225002102 . 2 truediv [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
|
||||
" -0.7639320225002102 2 . truediv [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
|
||||
" -0.3819660112501051 . [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
|
||||
" -0.3819660112501051 [] . swaack first [-5.23606797749979] [2 truediv] infra first\n",
|
||||
" [-0.3819660112501051] . first [-5.23606797749979] [2 truediv] infra first\n",
|
||||
" -0.3819660112501051 . [-5.23606797749979] [2 truediv] infra first\n",
|
||||
" -0.3819660112501051 [-5.23606797749979] . [2 truediv] infra first\n",
|
||||
"-0.3819660112501051 [-5.23606797749979] [2 truediv] . infra first\n",
|
||||
" -5.23606797749979 . 2 truediv [-0.3819660112501051] swaack first\n",
|
||||
" -5.23606797749979 2 . truediv [-0.3819660112501051] swaack first\n",
|
||||
" -2.618033988749895 . [-0.3819660112501051] swaack first\n",
|
||||
" -2.618033988749895 [-0.3819660112501051] . swaack first\n",
|
||||
" -0.3819660112501051 [-2.618033988749895] . first\n",
|
||||
" -0.3819660112501051 -2.618033988749895 . \n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"V('3 1 1 quadratic')"
|
||||
]
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
|
|
|||
|
|
@ -1,80 +1,60 @@
|
|||
|
||||
# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)
|
||||
|
||||
|
||||
```python
|
||||
from notebook_preamble import J, V, define
|
||||
```
|
||||
|
||||
# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)
|
||||
|
||||
Cf. [jp-quadratic.html](http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html)
|
||||
|
||||
-b +/- sqrt(b^2 - 4 * a * c)
|
||||
-----------------------------
|
||||
2 * a
|
||||
-b ± sqrt(b^2 - 4 * a * c)
|
||||
--------------------------------
|
||||
2 * a
|
||||
|
||||
$\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$
|
||||
|
||||
## Write a straightforward program with variable names.
|
||||
This math translates to Joy code in a straightforward manner. We are going to use named variables to keep track of the arguments, then write a definition without them.
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
### `-b`
|
||||
b neg
|
||||
|
||||
We use `cleave` to compute the sum and difference and then `app2` to finish computing both roots using a quoted program `[2a truediv]` built with `cons`.
|
||||
### `sqrt(b^2 - 4 * a * c)`
|
||||
b sqr 4 a c * * - sqrt
|
||||
|
||||
### Check it.
|
||||
Evaluating by hand:
|
||||
### `/2a`
|
||||
a 2 * /
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4ac - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2-4ac sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b sqrt(b^2-4ac) [+] [-] cleave a 2 * [truediv] cons app2
|
||||
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) a 2 * [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) 2a [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) [2a truediv] app2
|
||||
-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a
|
||||
|
||||
(Eventually we’ll be able to use e.g. Sympy versions of the Joy commands to do this sort of thing symbolically. This is part of what is meant by a “categorical” language.)
|
||||
|
||||
### Cleanup
|
||||
-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a roll< pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a -b pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a
|
||||
|
||||
## Derive a definition.
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop
|
||||
|
||||
|
||||
```python
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('3 1 1 quadratic')
|
||||
```
|
||||
|
||||
-0.3819660112501051 -2.618033988749895
|
||||
|
||||
|
||||
## Simplify
|
||||
We can define a `pm` plus-or-minus function:
|
||||
### `±`
|
||||
There is a function `pm` that accepts two values on the stack and replaces them with their sum and difference.
|
||||
|
||||
pm == [+] [-] cleave popdd
|
||||
|
||||
Then `quadratic` becomes:
|
||||
### Putting Them Together
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
|
||||
We use `app2` to compute both roots by using a quoted program `[2a /]` built with `cons`.
|
||||
|
||||
## Derive a definition.
|
||||
Working backwards we use `dip` and `dipd` to extract the code from the variables:
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
|
||||
The three arguments are to the left, so we can "chop off" everything to the right and say it's the definition of the `quadratic` function:
|
||||
|
||||
|
||||
```python
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2')
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
|
||||
```
|
||||
|
||||
Let's try it out:
|
||||
|
||||
|
||||
```python
|
||||
J('3 1 1 quadratic')
|
||||
|
|
@ -83,67 +63,56 @@ J('3 1 1 quadratic')
|
|||
-0.3819660112501051 -2.618033988749895
|
||||
|
||||
|
||||
### Define a "native" `pm` function.
|
||||
The definition of `pm` above is pretty elegant, but the implementation takes a lot of steps relative to what it's accomplishing. Since we are likely to use `pm` more than once in the future, let's write a primitive in Python and add it to the dictionary. (This has been done already.)
|
||||
If you look at the Joy evaluation trace you can see that the first few lines are the `dip` and `dipd` combinators building the main program by incorporating the values on the stack. Then that program runs and you get the results. This is pretty typical of Joy code.
|
||||
|
||||
|
||||
```python
|
||||
def pm(stack):
|
||||
a, (b, stack) = stack
|
||||
p, m, = b + a, b - a
|
||||
return m, (p, stack)
|
||||
V('-5 1 4 quadratic')
|
||||
```
|
||||
|
||||
The resulting trace is short enough to fit on a page.
|
||||
|
||||
|
||||
```python
|
||||
V('3 1 1 quadratic')
|
||||
```
|
||||
|
||||
. 3 1 1 quadratic
|
||||
3 . 1 1 quadratic
|
||||
3 1 . 1 quadratic
|
||||
3 1 1 . quadratic
|
||||
3 1 1 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [truediv] cons app2
|
||||
3 1 1 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 1 1 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . [neg] dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 [neg] . dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . neg 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 . 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . dup mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 3 . mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 . 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 1 . * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 5 . sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 2.23606797749979 . pm 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 . 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 . 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 2 . * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 . [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 [truediv] . cons app2
|
||||
-0.7639320225002102 -5.23606797749979 [2 truediv] . app2
|
||||
[-0.7639320225002102] [2 truediv] . infra first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 . 2 truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 2 . truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [] . swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
[-0.3819660112501051] . first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] . [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] [2 truediv] . infra first
|
||||
-5.23606797749979 . 2 truediv [-0.3819660112501051] swaack first
|
||||
-5.23606797749979 2 . truediv [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 . [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 [-0.3819660112501051] . swaack first
|
||||
-0.3819660112501051 [-2.618033988749895] . first
|
||||
-0.3819660112501051 -2.618033988749895 .
|
||||
. -5 1 4 quadratic
|
||||
-5 . 1 4 quadratic
|
||||
-5 1 . 4 quadratic
|
||||
-5 1 4 . quadratic
|
||||
-5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2
|
||||
-5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 16 . - sqrt pm 1 2 * [/] cons app2
|
||||
5 9 . sqrt pm 1 2 * [/] cons app2
|
||||
5 3.0 . pm 1 2 * [/] cons app2
|
||||
8.0 2.0 . 1 2 * [/] cons app2
|
||||
8.0 2.0 1 . 2 * [/] cons app2
|
||||
8.0 2.0 1 2 . * [/] cons app2
|
||||
8.0 2.0 2 . [/] cons app2
|
||||
8.0 2.0 2 [/] . cons app2
|
||||
8.0 2.0 [2 /] . app2
|
||||
[8.0] [2 /] . infra first [2.0] [2 /] infra first
|
||||
8.0 . 2 / [] swaack first [2.0] [2 /] infra first
|
||||
8.0 2 . / [] swaack first [2.0] [2 /] infra first
|
||||
4.0 . [] swaack first [2.0] [2 /] infra first
|
||||
4.0 [] . swaack first [2.0] [2 /] infra first
|
||||
[4.0] . first [2.0] [2 /] infra first
|
||||
4.0 . [2.0] [2 /] infra first
|
||||
4.0 [2.0] . [2 /] infra first
|
||||
4.0 [2.0] [2 /] . infra first
|
||||
2.0 . 2 / [4.0] swaack first
|
||||
2.0 2 . / [4.0] swaack first
|
||||
1.0 . [4.0] swaack first
|
||||
1.0 [4.0] . swaack first
|
||||
4.0 [1.0] . first
|
||||
4.0 1.0 .
|
||||
|
||||
|
|
|
|||
|
|
@ -1,104 +1,92 @@
|
|||
|
||||
`Quadratic formula <https://en.wikipedia.org/wiki/Quadratic_formula>`__
|
||||
=======================================================================
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
`Quadratic formula <https://en.wikipedia.org/wiki/Quadratic_formula>`__
|
||||
=======================================================================
|
||||
|
||||
Cf.
|
||||
`jp-quadratic.html <http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html>`__
|
||||
|
||||
::
|
||||
|
||||
-b +/- sqrt(b^2 - 4 * a * c)
|
||||
-----------------------------
|
||||
2 * a
|
||||
-b ± sqrt(b^2 - 4 * a * c)
|
||||
--------------------------------
|
||||
2 * a
|
||||
|
||||
:math:`\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}`
|
||||
|
||||
Write a straightforward program with variable names.
|
||||
----------------------------------------------------
|
||||
|
||||
::
|
||||
This math translates to Joy code in a straightforward manner. We are
|
||||
going to use named variables to keep track of the arguments, then write
|
||||
a definition without them.
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
|
||||
We use ``cleave`` to compute the sum and difference and then ``app2`` to
|
||||
finish computing both roots using a quoted program ``[2a truediv]``
|
||||
built with ``cons``.
|
||||
|
||||
Check it.
|
||||
~~~~~~~~~
|
||||
|
||||
Evaluating by hand:
|
||||
``-b``
|
||||
~~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4ac - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2-4ac sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b sqrt(b^2-4ac) [+] [-] cleave a 2 * [truediv] cons app2
|
||||
b neg
|
||||
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) a 2 * [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) 2a [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) [2a truediv] app2
|
||||
-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a
|
||||
``sqrt(b^2 - 4 * a * c)``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
(Eventually we’ll be able to use e.g. Sympy versions of the Joy commands
|
||||
to do this sort of thing symbolically. This is part of what is meant by
|
||||
a “categorical” language.)
|
||||
::
|
||||
|
||||
Cleanup
|
||||
b sqr 4 a c * * - sqrt
|
||||
|
||||
``/2a``
|
||||
~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a roll< pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a -b pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a
|
||||
a 2 * /
|
||||
|
||||
Derive a definition.
|
||||
--------------------
|
||||
``±``
|
||||
~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('3 1 1 quadratic')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-0.3819660112501051 -2.618033988749895
|
||||
|
||||
|
||||
Simplify
|
||||
--------
|
||||
|
||||
We can define a ``pm`` plus-or-minus function:
|
||||
There is a function ``pm`` that accepts two values on the stack and
|
||||
replaces them with their sum and difference.
|
||||
|
||||
::
|
||||
|
||||
pm == [+] [-] cleave popdd
|
||||
|
||||
Then ``quadratic`` becomes:
|
||||
Putting Them Together
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
|
||||
We use ``app2`` to compute both roots by using a quoted program
|
||||
``[2a /]`` built with ``cons``.
|
||||
|
||||
Derive a definition.
|
||||
--------------------
|
||||
|
||||
Working backwards we use ``dip`` and ``dipd`` to extract the code from
|
||||
the variables:
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
|
||||
The three arguments are to the left, so we can "chop off" everything to
|
||||
the right and say it's the definition of the ``quadratic`` function:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2')
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
|
||||
|
||||
Let's try it out:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
|
|
@ -110,74 +98,61 @@ Then ``quadratic`` becomes:
|
|||
-0.3819660112501051 -2.618033988749895
|
||||
|
||||
|
||||
Define a "native" ``pm`` function.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The definition of ``pm`` above is pretty elegant, but the implementation
|
||||
takes a lot of steps relative to what it's accomplishing. Since we are
|
||||
likely to use ``pm`` more than once in the future, let's write a
|
||||
primitive in Python and add it to the dictionary. (This has been done
|
||||
already.)
|
||||
If you look at the Joy evaluation trace you can see that the first few
|
||||
lines are the ``dip`` and ``dipd`` combinators building the main program
|
||||
by incorporating the values on the stack. Then that program runs and you
|
||||
get the results. This is pretty typical of Joy code.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def pm(stack):
|
||||
a, (b, stack) = stack
|
||||
p, m, = b + a, b - a
|
||||
return m, (p, stack)
|
||||
|
||||
The resulting trace is short enough to fit on a page.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('3 1 1 quadratic')
|
||||
V('-5 1 4 quadratic')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 3 1 1 quadratic
|
||||
3 . 1 1 quadratic
|
||||
3 1 . 1 quadratic
|
||||
3 1 1 . quadratic
|
||||
3 1 1 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [truediv] cons app2
|
||||
3 1 1 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 1 1 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . [neg] dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 [neg] . dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . neg 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 . 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . dup mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 3 . mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 . 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 1 . * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 5 . sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 2.23606797749979 . pm 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 . 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 . 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 2 . * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 . [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 [truediv] . cons app2
|
||||
-0.7639320225002102 -5.23606797749979 [2 truediv] . app2
|
||||
[-0.7639320225002102] [2 truediv] . infra first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 . 2 truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 2 . truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [] . swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
[-0.3819660112501051] . first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] . [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] [2 truediv] . infra first
|
||||
-5.23606797749979 . 2 truediv [-0.3819660112501051] swaack first
|
||||
-5.23606797749979 2 . truediv [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 . [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 [-0.3819660112501051] . swaack first
|
||||
-0.3819660112501051 [-2.618033988749895] . first
|
||||
-0.3819660112501051 -2.618033988749895 .
|
||||
. -5 1 4 quadratic
|
||||
-5 . 1 4 quadratic
|
||||
-5 1 . 4 quadratic
|
||||
-5 1 4 . quadratic
|
||||
-5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2
|
||||
-5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 16 . - sqrt pm 1 2 * [/] cons app2
|
||||
5 9 . sqrt pm 1 2 * [/] cons app2
|
||||
5 3.0 . pm 1 2 * [/] cons app2
|
||||
8.0 2.0 . 1 2 * [/] cons app2
|
||||
8.0 2.0 1 . 2 * [/] cons app2
|
||||
8.0 2.0 1 2 . * [/] cons app2
|
||||
8.0 2.0 2 . [/] cons app2
|
||||
8.0 2.0 2 [/] . cons app2
|
||||
8.0 2.0 [2 /] . app2
|
||||
[8.0] [2 /] . infra first [2.0] [2 /] infra first
|
||||
8.0 . 2 / [] swaack first [2.0] [2 /] infra first
|
||||
8.0 2 . / [] swaack first [2.0] [2 /] infra first
|
||||
4.0 . [] swaack first [2.0] [2 /] infra first
|
||||
4.0 [] . swaack first [2.0] [2 /] infra first
|
||||
[4.0] . first [2.0] [2 /] infra first
|
||||
4.0 . [2.0] [2 /] infra first
|
||||
4.0 [2.0] . [2 /] infra first
|
||||
4.0 [2.0] [2 /] . infra first
|
||||
2.0 . 2 / [4.0] swaack first
|
||||
2.0 2 . / [4.0] swaack first
|
||||
1.0 . [4.0] swaack first
|
||||
1.0 [4.0] . swaack first
|
||||
4.0 [1.0] . first
|
||||
4.0 1.0 .
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,859 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from notebook_preamble import D, DefinitionWrapper, J, V, define"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Recursive Combinators\n",
|
||||
"\n",
|
||||
"This article describes the `genrec` combinator, how to use it, and several generic specializations.\n",
|
||||
"\n",
|
||||
" [if] [then] [rec1] [rec2] genrec\n",
|
||||
" ---------------------------------------------------------------------\n",
|
||||
" [if] [then] [rec1 [[if] [then] [rec1] [rec2] genrec] rec2] ifte\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"From \"Recursion Theory and Joy\" (j05cmp.html) by Manfred von Thun:\n",
|
||||
"\n",
|
||||
"> \"The genrec combinator takes four program parameters in addition to\n",
|
||||
"whatever data parameters it needs. Fourth from the top is an if-part,\n",
|
||||
"followed by a then-part. If the if-part yields true, then the then-part\n",
|
||||
"is executed and the combinator terminates. The other two parameters are\n",
|
||||
"the rec1-part and the rec2-part. If the if-part yields false, the\n",
|
||||
"rec1-part is executed. Following that the four program parameters and\n",
|
||||
"the combinator are again pushed onto the stack bundled up in a quoted\n",
|
||||
"form. Then the rec2-part is executed, where it will find the bundled\n",
|
||||
"form. Typically it will then execute the bundled form, either with i or\n",
|
||||
"with app2, or some other combinator.\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Designing Recursive Functions\n",
|
||||
"The way to design one of these is to fix your base case and \n",
|
||||
"test and then treat `R1` and `R2` as an else-part \"sandwiching\"\n",
|
||||
"a quotation of the whole function.\n",
|
||||
"\n",
|
||||
"For example, given a (general recursive) function `F`:\n",
|
||||
"\n",
|
||||
" F == [I] [T] [R1] [R2] genrec\n",
|
||||
" == [I] [T] [R1 [F] R2] ifte\n",
|
||||
"\n",
|
||||
"If the `[I]` predicate is false you must derive `R1` and `R2` from:\n",
|
||||
"\n",
|
||||
" ... R1 [F] R2\n",
|
||||
"\n",
|
||||
"Set the stack arguments in front and figure out what `R1` and `R2`\n",
|
||||
"have to do to apply the quoted `[F]` in the proper way."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Primitive Recursive Functions\n",
|
||||
"Primitive recursive functions are those where `R2 == i`.\n",
|
||||
"\n",
|
||||
" P == [I] [T] [R] primrec\n",
|
||||
" == [I] [T] [R [P] i] ifte\n",
|
||||
" == [I] [T] [R P] ifte"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## [Hylomorphism](https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29)\n",
|
||||
"A [hylomorphism](https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29) is a recursive function `H :: A -> C` that converts a value of type `A` into a value of type `C` by means of:\n",
|
||||
"\n",
|
||||
"- A generator `G :: A -> (B, A)`\n",
|
||||
"- A combiner `F :: (B, C) -> C`\n",
|
||||
"- A predicate `P :: A -> Bool` to detect the base case\n",
|
||||
"- A base case value `c :: C`\n",
|
||||
"- Recursive calls (zero or more); it has a \"call stack in the form of a cons list\".\n",
|
||||
"\n",
|
||||
"It may be helpful to see this function implemented in imperative Python code."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hylomorphism(c, F, P, G):\n",
|
||||
" '''Return a hylomorphism function H.'''\n",
|
||||
"\n",
|
||||
" def H(a):\n",
|
||||
" if P(a):\n",
|
||||
" result = c\n",
|
||||
" else:\n",
|
||||
" b, aa = G(a)\n",
|
||||
" result = F(b, H(aa)) # b is stored in the stack frame during recursive call to H().\n",
|
||||
" return result\n",
|
||||
"\n",
|
||||
" return H"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Cf. [\"Bananas, Lenses, & Barbed Wire\"](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125)\n",
|
||||
"\n",
|
||||
"Note that during evaluation of `H()` the intermediate `b` values are stored in the Python call stack. This is what is meant by \"call stack in the form of a cons list\"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Hylomorphism in Joy\n",
|
||||
"We can define a combinator `hylomorphism` that will make a hylomorphism combinator `H` from constituent parts.\n",
|
||||
"\n",
|
||||
" H == [P] c [G] [F] hylomorphism\n",
|
||||
"\n",
|
||||
"The function `H` is recursive, so we start with `ifte` and set the else-part to\n",
|
||||
"some function `J` that will contain a quoted copy of `H`. (The then-part just\n",
|
||||
"discards the leftover `a` and replaces it with the base case value `c`.)\n",
|
||||
"\n",
|
||||
" H == [P] [pop c] [J] ifte\n",
|
||||
"\n",
|
||||
"The else-part `J` gets just the argument `a` on the stack.\n",
|
||||
"\n",
|
||||
" a J\n",
|
||||
" a G The first thing to do is use the generator G\n",
|
||||
" aa b which produces b and a new aa\n",
|
||||
" aa b [H] dip we recur with H on the new aa\n",
|
||||
" aa H b F and run F on the result.\n",
|
||||
"\n",
|
||||
"This gives us a definition for `J`.\n",
|
||||
"\n",
|
||||
" J == G [H] dip F\n",
|
||||
"\n",
|
||||
"Plug it in and convert to genrec.\n",
|
||||
"\n",
|
||||
" H == [P] [pop c] [G [H] dip F] ifte\n",
|
||||
" H == [P] [pop c] [G] [dip F] genrec\n",
|
||||
"\n",
|
||||
"This is the form of a hylomorphism in Joy, which nicely illustrates that\n",
|
||||
"it is a simple specialization of the general recursion combinator.\n",
|
||||
"\n",
|
||||
" H == [P] c [G] [F] hylomorphism == [P] [pop c] [G] [dip F] genrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Derivation of `hylomorphism` combinator\n",
|
||||
"\n",
|
||||
"Now we just need to derive a definition that builds the `genrec` arguments\n",
|
||||
"out of the pieces given to the `hylomorphism` combinator.\n",
|
||||
"\n",
|
||||
" [P] c [G] [F] hylomorphism\n",
|
||||
" ------------------------------------------\n",
|
||||
" [P] [pop c] [G] [dip F] genrec\n",
|
||||
"\n",
|
||||
"Working in reverse:\n",
|
||||
"\n",
|
||||
"- Use `swoncat` twice to decouple `[c]` and `[F]`.\n",
|
||||
"- Use `unit` to dequote `c`.\n",
|
||||
"- Use `dipd` to untangle `[unit [pop] swoncat]` from the givens.\n",
|
||||
"\n",
|
||||
"So:\n",
|
||||
"\n",
|
||||
" H == [P] [pop c] [G] [dip F] genrec\n",
|
||||
" [P] [c] [pop] swoncat [G] [F] [dip] swoncat genrec\n",
|
||||
" [P] c unit [pop] swoncat [G] [F] [dip] swoncat genrec\n",
|
||||
" [P] c [G] [F] [unit [pop] swoncat] dipd [dip] swoncat genrec\n",
|
||||
"\n",
|
||||
"At this point all of the arguments (givens) to the hylomorphism are to the left so we have\n",
|
||||
"a definition for `hylomorphism`:\n",
|
||||
"\n",
|
||||
" hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Example: Finding [Triangular Numbers](https://en.wikipedia.org/wiki/Triangular_number)\n",
|
||||
"Let's write a function that, given a positive integer, returns the sum of all positive integers less than that one. (In this case the types `A`, `B` and `C` are all `int`.)\n",
|
||||
"\n",
|
||||
"To sum a range of integers from 0 to *n* - 1:\n",
|
||||
"\n",
|
||||
"- `[P]` is `[1 <=]`\n",
|
||||
"- `c` is `0`\n",
|
||||
"- `[G]` is `[-- dup]`\n",
|
||||
"- `[F]` is `[+]`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's try it:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"10\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 triangular_number')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[0 0 1 3 6 10 15]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[0 1 2 3 4 5 6] [triangular_number] map')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Four Specializations\n",
|
||||
"There are at least four kinds of recursive combinator, depending on two choices. The first choice is whether the combiner function `F` should be evaluated during the recursion or pushed into the pending expression to be \"collapsed\" at the end. The second choice is whether the combiner needs to operate on the current value of the datastructure or the generator's output, in other words, whether `F` or `G` should run first in the recursive branch.\n",
|
||||
"\n",
|
||||
" H1 == [P] [pop c] [G ] [dip F] genrec\n",
|
||||
" H2 == c swap [P] [pop] [G [F] dip ] [i] genrec\n",
|
||||
" H3 == [P] [pop c] [ [G] dupdip ] [dip F] genrec\n",
|
||||
" H4 == c swap [P] [pop] [ [F] dupdip G] [i] genrec\n",
|
||||
"\n",
|
||||
"The working of the generator function `G` differs slightly for each. Consider the recursive branches:\n",
|
||||
"\n",
|
||||
" ... a G [H1] dip F w/ a G == a′ b\n",
|
||||
" \n",
|
||||
" ... c a G [F] dip H2 a G == b a′\n",
|
||||
" \n",
|
||||
" ... a [G] dupdip [H3] dip F a G == a′\n",
|
||||
" \n",
|
||||
" ... c a [F] dupdip G H4 a G == a′\n",
|
||||
"\n",
|
||||
"The following four sections illustrate how these work, omitting the predicate evaluation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `H1`\n",
|
||||
"\n",
|
||||
" H1 == [P] [pop c] [G] [dip F] genrec\n",
|
||||
"\n",
|
||||
"Iterate n times.\n",
|
||||
"\n",
|
||||
" ... a G [H1] dip F\n",
|
||||
" ... a′ b [H1] dip F\n",
|
||||
" ... a′ H1 b F\n",
|
||||
" ... a′ G [H1] dip F b F\n",
|
||||
" ... a″ b′ [H1] dip F b F\n",
|
||||
" ... a″ H1 b′ F b F\n",
|
||||
" ... a″ G [H1] dip F b′ F b F\n",
|
||||
" ... a‴ b″ [H1] dip F b′ F b F\n",
|
||||
" ... a‴ H1 b″ F b′ F b F\n",
|
||||
" ... a‴ pop c b″ F b′ F b F\n",
|
||||
" ... c b″ F b′ F b F\n",
|
||||
" ... d b′ F b F\n",
|
||||
" ... d′ b F\n",
|
||||
" ... d″\n",
|
||||
"\n",
|
||||
"This form builds up a pending expression (continuation) that contains the intermediate results along with the pending combiner functions. When the base case is reached the last term is replaced by the identity value `c` and the continuation \"collapses\" into the final result using the combiner `F`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `H2`\n",
|
||||
"When you can start with the identity value `c` on the stack and the combiner `F` can operate as you go using the intermediate results immediately rather than queuing them up, use this form. An important difference is that the generator function must return its results in the reverse order.\n",
|
||||
"\n",
|
||||
" H2 == c swap [P] [pop] [G [F] dip] primrec\n",
|
||||
"\n",
|
||||
" ... c a G [F] dip H2\n",
|
||||
" ... c b a′ [F] dip H2\n",
|
||||
" ... c b F a′ H2\n",
|
||||
" ... d a′ H2\n",
|
||||
" ... d a′ G [F] dip H2\n",
|
||||
" ... d b′ a″ [F] dip H2\n",
|
||||
" ... d b′ F a″ H2\n",
|
||||
" ... d′ a″ H2\n",
|
||||
" ... d′ a″ G [F] dip H2\n",
|
||||
" ... d′ b″ a‴ [F] dip H2\n",
|
||||
" ... d′ b″ F a‴ H2\n",
|
||||
" ... d″ a‴ H2\n",
|
||||
" ... d″ a‴ pop\n",
|
||||
" ... d″\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `H3`\n",
|
||||
"If you examine the traces above you'll see that the combiner `F` only gets to operate on the results of `G`, it never \"sees\" the first value `a`. If the combiner and the generator both need to work on the current value then `dup` must be used, and the generator must produce one item instead of two (the b is instead the duplicate of a.)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" H3 == [P] [pop c] [[G] dupdip] [dip F] genrec\n",
|
||||
"\n",
|
||||
" ... a [G] dupdip [H3] dip F\n",
|
||||
" ... a G a [H3] dip F\n",
|
||||
" ... a′ a [H3] dip F\n",
|
||||
" ... a′ H3 a F\n",
|
||||
" ... a′ [G] dupdip [H3] dip F a F\n",
|
||||
" ... a′ G a′ [H3] dip F a F\n",
|
||||
" ... a″ a′ [H3] dip F a F\n",
|
||||
" ... a″ H3 a′ F a F\n",
|
||||
" ... a″ [G] dupdip [H3] dip F a′ F a F\n",
|
||||
" ... a″ G a″ [H3] dip F a′ F a F\n",
|
||||
" ... a‴ a″ [H3] dip F a′ F a F\n",
|
||||
" ... a‴ H3 a″ F a′ F a F\n",
|
||||
" ... a‴ pop c a″ F a′ F a F\n",
|
||||
" ... c a″ F a′ F a F\n",
|
||||
" ... d a′ F a F\n",
|
||||
" ... d′ a F\n",
|
||||
" ... d″"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `H4`\n",
|
||||
"And, last but not least, if you can combine as you go, starting with `c`, and the combiner `F` needs to work on the current item, this is the form:\n",
|
||||
"\n",
|
||||
" H4 == c swap [P] [pop] [[F] dupdip G] primrec\n",
|
||||
"\n",
|
||||
" ... c a [F] dupdip G H4\n",
|
||||
" ... c a F a G H4\n",
|
||||
" ... d a G H4\n",
|
||||
" ... d a′ H4\n",
|
||||
" ... d a′ [F] dupdip G H4\n",
|
||||
" ... d a′ F a′ G H4\n",
|
||||
" ... d′ a′ G H4\n",
|
||||
" ... d′ a″ H4\n",
|
||||
" ... d′ a″ [F] dupdip G H4\n",
|
||||
" ... d′ a″ F a″ G H4\n",
|
||||
" ... d″ a″ G H4\n",
|
||||
" ... d″ a‴ H4\n",
|
||||
" ... d″ a‴ pop\n",
|
||||
" ... d″"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Anamorphism\n",
|
||||
"An anamorphism can be defined as a hylomorphism that uses `[]` for `c` and\n",
|
||||
"`swons` for `F`. An anamorphic function builds a list of values.\n",
|
||||
"\n",
|
||||
" A == [P] [] [G] [swons] hylomorphism"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `range` et. al.\n",
|
||||
"An example of an anamorphism is the `range` function which generates the list of integers from 0 to *n* - 1 given *n*.\n",
|
||||
"\n",
|
||||
"Each of the above variations can be used to make four slightly different `range` functions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"#### `range` with `H1`\n",
|
||||
" H1 == [P] [pop c] [G] [dip F] genrec\n",
|
||||
" == [0 <=] [pop []] [-- dup] [dip swons] genrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('range == [0 <=] [] [-- dup] [swons] hylomorphism')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[4 3 2 1 0]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 range')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"#### `range` with `H2`\n",
|
||||
" H2 == c swap [P] [pop] [G [F] dip] primrec\n",
|
||||
" == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[0 1 2 3 4]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 range_reverse')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"#### `range` with `H3`\n",
|
||||
" H3 == [P] [pop c] [[G] dupdip] [dip F] genrec\n",
|
||||
" == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[5 4 3 2 1]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 ranger')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"#### `range` with `H4`\n",
|
||||
" H4 == c swap [P] [pop] [[F] dupdip G ] primrec\n",
|
||||
" == [] swap [0 <=] [pop] [[swons] dupdip --] primrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[1 2 3 4 5]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 ranger_reverse')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Hopefully this illustrates the workings of the variations. For more insight you can run the cells using the `V()` function instead of the `J()` function to get a trace of the Joy evaluation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Catamorphism\n",
|
||||
"A catamorphism can be defined as a hylomorphism that uses `[uncons swap]` for `[G]`\n",
|
||||
"and `[[] =]` (or just `[not]`) for the predicate `[P]`. A catamorphic function tears down a list term-by-term and makes some new value.\n",
|
||||
"\n",
|
||||
" C == [not] c [uncons swap] [F] hylomorphism"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('swuncons == uncons swap') # Awkward name."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"An example of a catamorphism is the sum function.\n",
|
||||
"\n",
|
||||
" sum == [not] 0 [swuncons] [+] hylomorphism"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('sum == [not] 0 [swuncons] [+] hylomorphism')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"15\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[5 4 3 2 1] sum')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### The `step` combinator\n",
|
||||
"The `step` combinator will usually be better to use than `catamorphism`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Run a quoted program on each item in a sequence.\n",
|
||||
"::\n",
|
||||
"\n",
|
||||
" ... [] [Q] . step\n",
|
||||
" -----------------------\n",
|
||||
" ... .\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" ... [a] [Q] . step\n",
|
||||
" ------------------------\n",
|
||||
" ... a . Q\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" ... [a b c] [Q] . step\n",
|
||||
" ----------------------------------------\n",
|
||||
" ... a . Q [b c] [Q] step\n",
|
||||
"\n",
|
||||
"The step combinator executes the quotation on each member of the list\n",
|
||||
"on top of the stack.\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[step] help')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('sum == 0 swap [+] step')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"15\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[5 4 3 2 1] sum')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Example: Factorial Function\n",
|
||||
"\n",
|
||||
"For the Factorial function:\n",
|
||||
"\n",
|
||||
" H4 == c swap [P] [pop] [[F] dupdip G] primrec\n",
|
||||
"\n",
|
||||
"With:\n",
|
||||
"\n",
|
||||
" c == 1\n",
|
||||
" F == *\n",
|
||||
" G == --\n",
|
||||
" P == 1 <="
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"120\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 factorial')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Example: `tails`\n",
|
||||
"An example of a paramorphism for lists given in the [\"Bananas...\" paper](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125) is `tails` which returns the list of \"tails\" of a list.\n",
|
||||
"\n",
|
||||
" [1 2 3] tails\n",
|
||||
" --------------------\n",
|
||||
" [[] [3] [2 3]]\n",
|
||||
" "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We can build as we go, and we want `F` to run after `G`, so we use pattern `H2`:\n",
|
||||
"\n",
|
||||
" H2 == c swap [P] [pop] [G [F] dip] primrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We would use:\n",
|
||||
"\n",
|
||||
" c == []\n",
|
||||
" F == swons\n",
|
||||
" G == rest dup\n",
|
||||
" P == not"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[] [3] [2 3]]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[1 2 3] tails')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Conclusion: Patterns of Recursion\n",
|
||||
"Our story so far...\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"### Hylo-, Ana-, Cata-\n",
|
||||
"\n",
|
||||
" H == [P ] [pop c ] [G ] [dip F ] genrec\n",
|
||||
" A == [P ] [pop []] [G ] [dip swap cons] genrec\n",
|
||||
" C == [not] [pop c ] [uncons swap] [dip F ] genrec\n",
|
||||
"\n",
|
||||
"### Para-, ?-, ?-\n",
|
||||
"\n",
|
||||
" P == c swap [P ] [pop] [[F ] dupdip G ] primrec\n",
|
||||
" ? == [] swap [P ] [pop] [[swap cons] dupdip G ] primrec\n",
|
||||
" ? == c swap [not] [pop] [[F ] dupdip uncons swap] primrec\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Appendix: Fun with Symbols\n",
|
||||
"\n",
|
||||
" |[ (c, F), (G, P) ]| == (|c, F|) • [(G, P)]\n",
|
||||
"\n",
|
||||
"[\"Bananas, Lenses, & Barbed Wire\"](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125)\n",
|
||||
"\n",
|
||||
" (|...|) [(...)] [<...>]\n",
|
||||
"\n",
|
||||
"I think they are having slightly too much fun with the symbols. However, \"Too much is always better than not enough.\""
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,525 @@
|
|||
|
||||
|
||||
```python
|
||||
from notebook_preamble import D, DefinitionWrapper, J, V, define
|
||||
```
|
||||
|
||||
# Recursive Combinators
|
||||
|
||||
This article describes the `genrec` combinator, how to use it, and several generic specializations.
|
||||
|
||||
[if] [then] [rec1] [rec2] genrec
|
||||
---------------------------------------------------------------------
|
||||
[if] [then] [rec1 [[if] [then] [rec1] [rec2] genrec] rec2] ifte
|
||||
|
||||
|
||||
From "Recursion Theory and Joy" (j05cmp.html) by Manfred von Thun:
|
||||
|
||||
> "The genrec combinator takes four program parameters in addition to
|
||||
whatever data parameters it needs. Fourth from the top is an if-part,
|
||||
followed by a then-part. If the if-part yields true, then the then-part
|
||||
is executed and the combinator terminates. The other two parameters are
|
||||
the rec1-part and the rec2-part. If the if-part yields false, the
|
||||
rec1-part is executed. Following that the four program parameters and
|
||||
the combinator are again pushed onto the stack bundled up in a quoted
|
||||
form. Then the rec2-part is executed, where it will find the bundled
|
||||
form. Typically it will then execute the bundled form, either with i or
|
||||
with app2, or some other combinator."
|
||||
|
||||
## Designing Recursive Functions
|
||||
The way to design one of these is to fix your base case and
|
||||
test and then treat `R1` and `R2` as an else-part "sandwiching"
|
||||
a quotation of the whole function.
|
||||
|
||||
For example, given a (general recursive) function `F`:
|
||||
|
||||
F == [I] [T] [R1] [R2] genrec
|
||||
== [I] [T] [R1 [F] R2] ifte
|
||||
|
||||
If the `[I]` predicate is false you must derive `R1` and `R2` from:
|
||||
|
||||
... R1 [F] R2
|
||||
|
||||
Set the stack arguments in front and figure out what `R1` and `R2`
|
||||
have to do to apply the quoted `[F]` in the proper way.
|
||||
|
||||
## Primitive Recursive Functions
|
||||
Primitive recursive functions are those where `R2 == i`.
|
||||
|
||||
P == [I] [T] [R] primrec
|
||||
== [I] [T] [R [P] i] ifte
|
||||
== [I] [T] [R P] ifte
|
||||
|
||||
## [Hylomorphism](https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29)
|
||||
A [hylomorphism](https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29) is a recursive function `H :: A -> C` that converts a value of type `A` into a value of type `C` by means of:
|
||||
|
||||
- A generator `G :: A -> (B, A)`
|
||||
- A combiner `F :: (B, C) -> C`
|
||||
- A predicate `P :: A -> Bool` to detect the base case
|
||||
- A base case value `c :: C`
|
||||
- Recursive calls (zero or more); it has a "call stack in the form of a cons list".
|
||||
|
||||
It may be helpful to see this function implemented in imperative Python code.
|
||||
|
||||
|
||||
```python
|
||||
def hylomorphism(c, F, P, G):
|
||||
'''Return a hylomorphism function H.'''
|
||||
|
||||
def H(a):
|
||||
if P(a):
|
||||
result = c
|
||||
else:
|
||||
b, aa = G(a)
|
||||
result = F(b, H(aa)) # b is stored in the stack frame during recursive call to H().
|
||||
return result
|
||||
|
||||
return H
|
||||
```
|
||||
|
||||
Cf. ["Bananas, Lenses, & Barbed Wire"](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125)
|
||||
|
||||
Note that during evaluation of `H()` the intermediate `b` values are stored in the Python call stack. This is what is meant by "call stack in the form of a cons list".
|
||||
|
||||
## Hylomorphism in Joy
|
||||
We can define a combinator `hylomorphism` that will make a hylomorphism combinator `H` from constituent parts.
|
||||
|
||||
H == [P] c [G] [F] hylomorphism
|
||||
|
||||
The function `H` is recursive, so we start with `ifte` and set the else-part to
|
||||
some function `J` that will contain a quoted copy of `H`. (The then-part just
|
||||
discards the leftover `a` and replaces it with the base case value `c`.)
|
||||
|
||||
H == [P] [pop c] [J] ifte
|
||||
|
||||
The else-part `J` gets just the argument `a` on the stack.
|
||||
|
||||
a J
|
||||
a G The first thing to do is use the generator G
|
||||
aa b which produces b and a new aa
|
||||
aa b [H] dip we recur with H on the new aa
|
||||
aa H b F and run F on the result.
|
||||
|
||||
This gives us a definition for `J`.
|
||||
|
||||
J == G [H] dip F
|
||||
|
||||
Plug it in and convert to genrec.
|
||||
|
||||
H == [P] [pop c] [G [H] dip F] ifte
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
This is the form of a hylomorphism in Joy, which nicely illustrates that
|
||||
it is a simple specialization of the general recursion combinator.
|
||||
|
||||
H == [P] c [G] [F] hylomorphism == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
## Derivation of `hylomorphism` combinator
|
||||
|
||||
Now we just need to derive a definition that builds the `genrec` arguments
|
||||
out of the pieces given to the `hylomorphism` combinator.
|
||||
|
||||
[P] c [G] [F] hylomorphism
|
||||
------------------------------------------
|
||||
[P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Working in reverse:
|
||||
|
||||
- Use `swoncat` twice to decouple `[c]` and `[F]`.
|
||||
- Use `unit` to dequote `c`.
|
||||
- Use `dipd` to untangle `[unit [pop] swoncat]` from the givens.
|
||||
|
||||
So:
|
||||
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
[P] [c] [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c unit [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c [G] [F] [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
At this point all of the arguments (givens) to the hylomorphism are to the left so we have
|
||||
a definition for `hylomorphism`:
|
||||
|
||||
hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
|
||||
```python
|
||||
define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
|
||||
```
|
||||
|
||||
### Example: Finding [Triangular Numbers](https://en.wikipedia.org/wiki/Triangular_number)
|
||||
Let's write a function that, given a positive integer, returns the sum of all positive integers less than that one. (In this case the types `A`, `B` and `C` are all `int`.)
|
||||
|
||||
To sum a range of integers from 0 to *n* - 1:
|
||||
|
||||
- `[P]` is `[1 <=]`
|
||||
- `c` is `0`
|
||||
- `[G]` is `[-- dup]`
|
||||
- `[F]` is `[+]`
|
||||
|
||||
|
||||
```python
|
||||
define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
|
||||
```
|
||||
|
||||
Let's try it:
|
||||
|
||||
|
||||
```python
|
||||
J('5 triangular_number')
|
||||
```
|
||||
|
||||
10
|
||||
|
||||
|
||||
|
||||
```python
|
||||
J('[0 1 2 3 4 5 6] [triangular_number] map')
|
||||
```
|
||||
|
||||
[0 0 1 3 6 10 15]
|
||||
|
||||
|
||||
## Four Specializations
|
||||
There are at least four kinds of recursive combinator, depending on two choices. The first choice is whether the combiner function `F` should be evaluated during the recursion or pushed into the pending expression to be "collapsed" at the end. The second choice is whether the combiner needs to operate on the current value of the datastructure or the generator's output, in other words, whether `F` or `G` should run first in the recursive branch.
|
||||
|
||||
H1 == [P] [pop c] [G ] [dip F] genrec
|
||||
H2 == c swap [P] [pop] [G [F] dip ] [i] genrec
|
||||
H3 == [P] [pop c] [ [G] dupdip ] [dip F] genrec
|
||||
H4 == c swap [P] [pop] [ [F] dupdip G] [i] genrec
|
||||
|
||||
The working of the generator function `G` differs slightly for each. Consider the recursive branches:
|
||||
|
||||
... a G [H1] dip F w/ a G == a′ b
|
||||
|
||||
... c a G [F] dip H2 a G == b a′
|
||||
|
||||
... a [G] dupdip [H3] dip F a G == a′
|
||||
|
||||
... c a [F] dupdip G H4 a G == a′
|
||||
|
||||
The following four sections illustrate how these work, omitting the predicate evaluation.
|
||||
|
||||
### `H1`
|
||||
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Iterate n times.
|
||||
|
||||
... a G [H1] dip F
|
||||
... a′ b [H1] dip F
|
||||
... a′ H1 b F
|
||||
... a′ G [H1] dip F b F
|
||||
... a″ b′ [H1] dip F b F
|
||||
... a″ H1 b′ F b F
|
||||
... a″ G [H1] dip F b′ F b F
|
||||
... a‴ b″ [H1] dip F b′ F b F
|
||||
... a‴ H1 b″ F b′ F b F
|
||||
... a‴ pop c b″ F b′ F b F
|
||||
... c b″ F b′ F b F
|
||||
... d b′ F b F
|
||||
... d′ b F
|
||||
... d″
|
||||
|
||||
This form builds up a pending expression (continuation) that contains the intermediate results along with the pending combiner functions. When the base case is reached the last term is replaced by the identity value `c` and the continuation "collapses" into the final result using the combiner `F`.
|
||||
|
||||
### `H2`
|
||||
When you can start with the identity value `c` on the stack and the combiner `F` can operate as you go using the intermediate results immediately rather than queuing them up, use this form. An important difference is that the generator function must return its results in the reverse order.
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
... c a G [F] dip H2
|
||||
... c b a′ [F] dip H2
|
||||
... c b F a′ H2
|
||||
... d a′ H2
|
||||
... d a′ G [F] dip H2
|
||||
... d b′ a″ [F] dip H2
|
||||
... d b′ F a″ H2
|
||||
... d′ a″ H2
|
||||
... d′ a″ G [F] dip H2
|
||||
... d′ b″ a‴ [F] dip H2
|
||||
... d′ b″ F a‴ H2
|
||||
... d″ a‴ H2
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
|
||||
### `H3`
|
||||
If you examine the traces above you'll see that the combiner `F` only gets to operate on the results of `G`, it never "sees" the first value `a`. If the combiner and the generator both need to work on the current value then `dup` must be used, and the generator must produce one item instead of two (the b is instead the duplicate of a.)
|
||||
|
||||
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
|
||||
... a [G] dupdip [H3] dip F
|
||||
... a G a [H3] dip F
|
||||
... a′ a [H3] dip F
|
||||
... a′ H3 a F
|
||||
... a′ [G] dupdip [H3] dip F a F
|
||||
... a′ G a′ [H3] dip F a F
|
||||
... a″ a′ [H3] dip F a F
|
||||
... a″ H3 a′ F a F
|
||||
... a″ [G] dupdip [H3] dip F a′ F a F
|
||||
... a″ G a″ [H3] dip F a′ F a F
|
||||
... a‴ a″ [H3] dip F a′ F a F
|
||||
... a‴ H3 a″ F a′ F a F
|
||||
... a‴ pop c a″ F a′ F a F
|
||||
... c a″ F a′ F a F
|
||||
... d a′ F a F
|
||||
... d′ a F
|
||||
... d″
|
||||
|
||||
### `H4`
|
||||
And, last but not least, if you can combine as you go, starting with `c`, and the combiner `F` needs to work on the current item, this is the form:
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
... c a [F] dupdip G H4
|
||||
... c a F a G H4
|
||||
... d a G H4
|
||||
... d a′ H4
|
||||
... d a′ [F] dupdip G H4
|
||||
... d a′ F a′ G H4
|
||||
... d′ a′ G H4
|
||||
... d′ a″ H4
|
||||
... d′ a″ [F] dupdip G H4
|
||||
... d′ a″ F a″ G H4
|
||||
... d″ a″ G H4
|
||||
... d″ a‴ H4
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
## Anamorphism
|
||||
An anamorphism can be defined as a hylomorphism that uses `[]` for `c` and
|
||||
`swons` for `F`. An anamorphic function builds a list of values.
|
||||
|
||||
A == [P] [] [G] [swons] hylomorphism
|
||||
|
||||
### `range` et. al.
|
||||
An example of an anamorphism is the `range` function which generates the list of integers from 0 to *n* - 1 given *n*.
|
||||
|
||||
Each of the above variations can be used to make four slightly different `range` functions.
|
||||
|
||||
#### `range` with `H1`
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
== [0 <=] [pop []] [-- dup] [dip swons] genrec
|
||||
|
||||
|
||||
```python
|
||||
define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('5 range')
|
||||
```
|
||||
|
||||
[4 3 2 1 0]
|
||||
|
||||
|
||||
#### `range` with `H2`
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
== [] swap [0 <=] [pop] [-- dup [swons] dip] primrec
|
||||
|
||||
|
||||
```python
|
||||
define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('5 range_reverse')
|
||||
```
|
||||
|
||||
[0 1 2 3 4]
|
||||
|
||||
|
||||
#### `range` with `H3`
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
== [0 <=] [pop []] [[--] dupdip] [dip swons] genrec
|
||||
|
||||
|
||||
```python
|
||||
define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('5 ranger')
|
||||
```
|
||||
|
||||
[5 4 3 2 1]
|
||||
|
||||
|
||||
#### `range` with `H4`
|
||||
H4 == c swap [P] [pop] [[F] dupdip G ] primrec
|
||||
== [] swap [0 <=] [pop] [[swons] dupdip --] primrec
|
||||
|
||||
|
||||
```python
|
||||
define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('5 ranger_reverse')
|
||||
```
|
||||
|
||||
[1 2 3 4 5]
|
||||
|
||||
|
||||
Hopefully this illustrates the workings of the variations. For more insight you can run the cells using the `V()` function instead of the `J()` function to get a trace of the Joy evaluation.
|
||||
|
||||
## Catamorphism
|
||||
A catamorphism can be defined as a hylomorphism that uses `[uncons swap]` for `[G]`
|
||||
and `[[] =]` (or just `[not]`) for the predicate `[P]`. A catamorphic function tears down a list term-by-term and makes some new value.
|
||||
|
||||
C == [not] c [uncons swap] [F] hylomorphism
|
||||
|
||||
|
||||
```python
|
||||
define('swuncons == uncons swap') # Awkward name.
|
||||
```
|
||||
|
||||
An example of a catamorphism is the sum function.
|
||||
|
||||
sum == [not] 0 [swuncons] [+] hylomorphism
|
||||
|
||||
|
||||
```python
|
||||
define('sum == [not] 0 [swuncons] [+] hylomorphism')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('[5 4 3 2 1] sum')
|
||||
```
|
||||
|
||||
15
|
||||
|
||||
|
||||
### The `step` combinator
|
||||
The `step` combinator will usually be better to use than `catamorphism`.
|
||||
|
||||
|
||||
```python
|
||||
J('[step] help')
|
||||
```
|
||||
|
||||
Run a quoted program on each item in a sequence.
|
||||
::
|
||||
|
||||
... [] [Q] . step
|
||||
-----------------------
|
||||
... .
|
||||
|
||||
|
||||
... [a] [Q] . step
|
||||
------------------------
|
||||
... a . Q
|
||||
|
||||
|
||||
... [a b c] [Q] . step
|
||||
----------------------------------------
|
||||
... a . Q [b c] [Q] step
|
||||
|
||||
The step combinator executes the quotation on each member of the list
|
||||
on top of the stack.
|
||||
|
||||
|
||||
|
||||
|
||||
```python
|
||||
define('sum == 0 swap [+] step')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('[5 4 3 2 1] sum')
|
||||
```
|
||||
|
||||
15
|
||||
|
||||
|
||||
## Example: Factorial Function
|
||||
|
||||
For the Factorial function:
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
With:
|
||||
|
||||
c == 1
|
||||
F == *
|
||||
G == --
|
||||
P == 1 <=
|
||||
|
||||
|
||||
```python
|
||||
define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('5 factorial')
|
||||
```
|
||||
|
||||
120
|
||||
|
||||
|
||||
## Example: `tails`
|
||||
An example of a paramorphism for lists given in the ["Bananas..." paper](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125) is `tails` which returns the list of "tails" of a list.
|
||||
|
||||
[1 2 3] tails
|
||||
--------------------
|
||||
[[] [3] [2 3]]
|
||||
|
||||
|
||||
We can build as we go, and we want `F` to run after `G`, so we use pattern `H2`:
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
We would use:
|
||||
|
||||
c == []
|
||||
F == swons
|
||||
G == rest dup
|
||||
P == not
|
||||
|
||||
|
||||
```python
|
||||
define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
J('[1 2 3] tails')
|
||||
```
|
||||
|
||||
[[] [3] [2 3]]
|
||||
|
||||
|
||||
## Conclusion: Patterns of Recursion
|
||||
Our story so far...
|
||||
|
||||
|
||||
### Hylo-, Ana-, Cata-
|
||||
|
||||
H == [P ] [pop c ] [G ] [dip F ] genrec
|
||||
A == [P ] [pop []] [G ] [dip swap cons] genrec
|
||||
C == [not] [pop c ] [uncons swap] [dip F ] genrec
|
||||
|
||||
### Para-, ?-, ?-
|
||||
|
||||
P == c swap [P ] [pop] [[F ] dupdip G ] primrec
|
||||
? == [] swap [P ] [pop] [[swap cons] dupdip G ] primrec
|
||||
? == c swap [not] [pop] [[F ] dupdip uncons swap] primrec
|
||||
|
||||
|
||||
## Appendix: Fun with Symbols
|
||||
|
||||
|[ (c, F), (G, P) ]| == (|c, F|) • [(G, P)]
|
||||
|
||||
["Bananas, Lenses, & Barbed Wire"](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125)
|
||||
|
||||
(|...|) [(...)] [<...>]
|
||||
|
||||
I think they are having slightly too much fun with the symbols. However, "Too much is always better than not enough."
|
||||
|
|
@ -0,0 +1,695 @@
|
|||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import D, DefinitionWrapper, J, V, define
|
||||
|
||||
Recursive Combinators
|
||||
=====================
|
||||
|
||||
This article describes the ``genrec`` combinator, how to use it, and
|
||||
several generic specializations.
|
||||
|
||||
::
|
||||
|
||||
[if] [then] [rec1] [rec2] genrec
|
||||
---------------------------------------------------------------------
|
||||
[if] [then] [rec1 [[if] [then] [rec1] [rec2] genrec] rec2] ifte
|
||||
|
||||
From "Recursion Theory and Joy" (j05cmp.html) by Manfred von Thun:
|
||||
|
||||
"The genrec combinator takes four program parameters in addition to
|
||||
whatever data parameters it needs. Fourth from the top is an
|
||||
if-part, followed by a then-part. If the if-part yields true, then
|
||||
the then-part is executed and the combinator terminates. The other
|
||||
two parameters are the rec1-part and the rec2-part. If the if-part
|
||||
yields false, the rec1-part is executed. Following that the four
|
||||
program parameters and the combinator are again pushed onto the
|
||||
stack bundled up in a quoted form. Then the rec2-part is executed,
|
||||
where it will find the bundled form. Typically it will then execute
|
||||
the bundled form, either with i or with app2, or some other
|
||||
combinator."
|
||||
|
||||
Designing Recursive Functions
|
||||
-----------------------------
|
||||
|
||||
The way to design one of these is to fix your base case and test and
|
||||
then treat ``R1`` and ``R2`` as an else-part "sandwiching" a quotation
|
||||
of the whole function.
|
||||
|
||||
For example, given a (general recursive) function ``F``:
|
||||
|
||||
::
|
||||
|
||||
F == [I] [T] [R1] [R2] genrec
|
||||
== [I] [T] [R1 [F] R2] ifte
|
||||
|
||||
If the ``[I]`` predicate is false you must derive ``R1`` and ``R2``
|
||||
from:
|
||||
|
||||
::
|
||||
|
||||
... R1 [F] R2
|
||||
|
||||
Set the stack arguments in front and figure out what ``R1`` and ``R2``
|
||||
have to do to apply the quoted ``[F]`` in the proper way.
|
||||
|
||||
Primitive Recursive Functions
|
||||
-----------------------------
|
||||
|
||||
Primitive recursive functions are those where ``R2 == i``.
|
||||
|
||||
::
|
||||
|
||||
P == [I] [T] [R] primrec
|
||||
== [I] [T] [R [P] i] ifte
|
||||
== [I] [T] [R P] ifte
|
||||
|
||||
`Hylomorphism <https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>`__
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
A
|
||||
`hylomorphism <https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>`__
|
||||
is a recursive function ``H :: A -> C`` that converts a value of type
|
||||
``A`` into a value of type ``C`` by means of:
|
||||
|
||||
- A generator ``G :: A -> (B, A)``
|
||||
- A combiner ``F :: (B, C) -> C``
|
||||
- A predicate ``P :: A -> Bool`` to detect the base case
|
||||
- A base case value ``c :: C``
|
||||
- Recursive calls (zero or more); it has a "call stack in the form of a
|
||||
cons list".
|
||||
|
||||
It may be helpful to see this function implemented in imperative Python
|
||||
code.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def hylomorphism(c, F, P, G):
|
||||
'''Return a hylomorphism function H.'''
|
||||
|
||||
def H(a):
|
||||
if P(a):
|
||||
result = c
|
||||
else:
|
||||
b, aa = G(a)
|
||||
result = F(b, H(aa)) # b is stored in the stack frame during recursive call to H().
|
||||
return result
|
||||
|
||||
return H
|
||||
|
||||
Cf. `"Bananas, Lenses, & Barbed
|
||||
Wire" <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
|
||||
Note that during evaluation of ``H()`` the intermediate ``b`` values are
|
||||
stored in the Python call stack. This is what is meant by "call stack in
|
||||
the form of a cons list".
|
||||
|
||||
Hylomorphism in Joy
|
||||
-------------------
|
||||
|
||||
We can define a combinator ``hylomorphism`` that will make a
|
||||
hylomorphism combinator ``H`` from constituent parts.
|
||||
|
||||
::
|
||||
|
||||
H == [P] c [G] [F] hylomorphism
|
||||
|
||||
The function ``H`` is recursive, so we start with ``ifte`` and set the
|
||||
else-part to some function ``J`` that will contain a quoted copy of
|
||||
``H``. (The then-part just discards the leftover ``a`` and replaces it
|
||||
with the base case value ``c``.)
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [J] ifte
|
||||
|
||||
The else-part ``J`` gets just the argument ``a`` on the stack.
|
||||
|
||||
::
|
||||
|
||||
a J
|
||||
a G The first thing to do is use the generator G
|
||||
aa b which produces b and a new aa
|
||||
aa b [H] dip we recur with H on the new aa
|
||||
aa H b F and run F on the result.
|
||||
|
||||
This gives us a definition for ``J``.
|
||||
|
||||
::
|
||||
|
||||
J == G [H] dip F
|
||||
|
||||
Plug it in and convert to genrec.
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [G [H] dip F] ifte
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
This is the form of a hylomorphism in Joy, which nicely illustrates that
|
||||
it is a simple specialization of the general recursion combinator.
|
||||
|
||||
::
|
||||
|
||||
H == [P] c [G] [F] hylomorphism == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Derivation of ``hylomorphism`` combinator
|
||||
-----------------------------------------
|
||||
|
||||
Now we just need to derive a definition that builds the ``genrec``
|
||||
arguments out of the pieces given to the ``hylomorphism`` combinator.
|
||||
|
||||
::
|
||||
|
||||
[P] c [G] [F] hylomorphism
|
||||
------------------------------------------
|
||||
[P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Working in reverse:
|
||||
|
||||
- Use ``swoncat`` twice to decouple ``[c]`` and ``[F]``.
|
||||
- Use ``unit`` to dequote ``c``.
|
||||
- Use ``dipd`` to untangle ``[unit [pop] swoncat]`` from the givens.
|
||||
|
||||
So:
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
[P] [c] [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c unit [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c [G] [F] [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
At this point all of the arguments (givens) to the hylomorphism are to
|
||||
the left so we have a definition for ``hylomorphism``:
|
||||
|
||||
::
|
||||
|
||||
hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
|
||||
|
||||
Example: Finding `Triangular Numbers <https://en.wikipedia.org/wiki/Triangular_number>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Let's write a function that, given a positive integer, returns the sum
|
||||
of all positive integers less than that one. (In this case the types
|
||||
``A``, ``B`` and ``C`` are all ``int``.)
|
||||
|
||||
To sum a range of integers from 0 to *n* - 1:
|
||||
|
||||
- ``[P]`` is ``[1 <=]``
|
||||
- ``c`` is ``0``
|
||||
- ``[G]`` is ``[-- dup]``
|
||||
- ``[F]`` is ``[+]``
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
|
||||
|
||||
Let's try it:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 triangular_number')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
10
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[0 1 2 3 4 5 6] [triangular_number] map')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 0 1 3 6 10 15]
|
||||
|
||||
|
||||
Four Specializations
|
||||
--------------------
|
||||
|
||||
There are at least four kinds of recursive combinator, depending on two
|
||||
choices. The first choice is whether the combiner function ``F`` should
|
||||
be evaluated during the recursion or pushed into the pending expression
|
||||
to be "collapsed" at the end. The second choice is whether the combiner
|
||||
needs to operate on the current value of the datastructure or the
|
||||
generator's output, in other words, whether ``F`` or ``G`` should run
|
||||
first in the recursive branch.
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G ] [dip F] genrec
|
||||
H2 == c swap [P] [pop] [G [F] dip ] [i] genrec
|
||||
H3 == [P] [pop c] [ [G] dupdip ] [dip F] genrec
|
||||
H4 == c swap [P] [pop] [ [F] dupdip G] [i] genrec
|
||||
|
||||
The working of the generator function ``G`` differs slightly for each.
|
||||
Consider the recursive branches:
|
||||
|
||||
::
|
||||
|
||||
... a G [H1] dip F w/ a G == a′ b
|
||||
|
||||
... c a G [F] dip H2 a G == b a′
|
||||
|
||||
... a [G] dupdip [H3] dip F a G == a′
|
||||
|
||||
... c a [F] dupdip G H4 a G == a′
|
||||
|
||||
The following four sections illustrate how these work, omitting the
|
||||
predicate evaluation.
|
||||
|
||||
``H1``
|
||||
~~~~~~
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Iterate n times.
|
||||
|
||||
::
|
||||
|
||||
... a G [H1] dip F
|
||||
... a′ b [H1] dip F
|
||||
... a′ H1 b F
|
||||
... a′ G [H1] dip F b F
|
||||
... a″ b′ [H1] dip F b F
|
||||
... a″ H1 b′ F b F
|
||||
... a″ G [H1] dip F b′ F b F
|
||||
... a‴ b″ [H1] dip F b′ F b F
|
||||
... a‴ H1 b″ F b′ F b F
|
||||
... a‴ pop c b″ F b′ F b F
|
||||
... c b″ F b′ F b F
|
||||
... d b′ F b F
|
||||
... d′ b F
|
||||
... d″
|
||||
|
||||
This form builds up a pending expression (continuation) that contains
|
||||
the intermediate results along with the pending combiner functions. When
|
||||
the base case is reached the last term is replaced by the identity value
|
||||
``c`` and the continuation "collapses" into the final result using the
|
||||
combiner ``F``.
|
||||
|
||||
``H2``
|
||||
~~~~~~
|
||||
|
||||
When you can start with the identity value ``c`` on the stack and the
|
||||
combiner ``F`` can operate as you go using the intermediate results
|
||||
immediately rather than queuing them up, use this form. An important
|
||||
difference is that the generator function must return its results in the
|
||||
reverse order.
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
... c a G [F] dip H2
|
||||
... c b a′ [F] dip H2
|
||||
... c b F a′ H2
|
||||
... d a′ H2
|
||||
... d a′ G [F] dip H2
|
||||
... d b′ a″ [F] dip H2
|
||||
... d b′ F a″ H2
|
||||
... d′ a″ H2
|
||||
... d′ a″ G [F] dip H2
|
||||
... d′ b″ a‴ [F] dip H2
|
||||
... d′ b″ F a‴ H2
|
||||
... d″ a‴ H2
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
``H3``
|
||||
~~~~~~
|
||||
|
||||
If you examine the traces above you'll see that the combiner ``F`` only
|
||||
gets to operate on the results of ``G``, it never "sees" the first value
|
||||
``a``. If the combiner and the generator both need to work on the
|
||||
current value then ``dup`` must be used, and the generator must produce
|
||||
one item instead of two (the b is instead the duplicate of a.)
|
||||
|
||||
::
|
||||
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
|
||||
... a [G] dupdip [H3] dip F
|
||||
... a G a [H3] dip F
|
||||
... a′ a [H3] dip F
|
||||
... a′ H3 a F
|
||||
... a′ [G] dupdip [H3] dip F a F
|
||||
... a′ G a′ [H3] dip F a F
|
||||
... a″ a′ [H3] dip F a F
|
||||
... a″ H3 a′ F a F
|
||||
... a″ [G] dupdip [H3] dip F a′ F a F
|
||||
... a″ G a″ [H3] dip F a′ F a F
|
||||
... a‴ a″ [H3] dip F a′ F a F
|
||||
... a‴ H3 a″ F a′ F a F
|
||||
... a‴ pop c a″ F a′ F a F
|
||||
... c a″ F a′ F a F
|
||||
... d a′ F a F
|
||||
... d′ a F
|
||||
... d″
|
||||
|
||||
``H4``
|
||||
~~~~~~
|
||||
|
||||
And, last but not least, if you can combine as you go, starting with
|
||||
``c``, and the combiner ``F`` needs to work on the current item, this is
|
||||
the form:
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
... c a [F] dupdip G H4
|
||||
... c a F a G H4
|
||||
... d a G H4
|
||||
... d a′ H4
|
||||
... d a′ [F] dupdip G H4
|
||||
... d a′ F a′ G H4
|
||||
... d′ a′ G H4
|
||||
... d′ a″ H4
|
||||
... d′ a″ [F] dupdip G H4
|
||||
... d′ a″ F a″ G H4
|
||||
... d″ a″ G H4
|
||||
... d″ a‴ H4
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
Anamorphism
|
||||
-----------
|
||||
|
||||
An anamorphism can be defined as a hylomorphism that uses ``[]`` for
|
||||
``c`` and ``swons`` for ``F``. An anamorphic function builds a list of
|
||||
values.
|
||||
|
||||
::
|
||||
|
||||
A == [P] [] [G] [swons] hylomorphism
|
||||
|
||||
``range`` et. al.
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
An example of an anamorphism is the ``range`` function which generates
|
||||
the list of integers from 0 to *n* - 1 given *n*.
|
||||
|
||||
Each of the above variations can be used to make four slightly different
|
||||
``range`` functions.
|
||||
|
||||
``range`` with ``H1``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
== [0 <=] [pop []] [-- dup] [dip swons] genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 range')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[4 3 2 1 0]
|
||||
|
||||
|
||||
``range`` with ``H2``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
== [] swap [0 <=] [pop] [-- dup [swons] dip] primrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 range_reverse')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 1 2 3 4]
|
||||
|
||||
|
||||
``range`` with ``H3``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
== [0 <=] [pop []] [[--] dupdip] [dip swons] genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 ranger')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[5 4 3 2 1]
|
||||
|
||||
|
||||
``range`` with ``H4``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G ] primrec
|
||||
== [] swap [0 <=] [pop] [[swons] dupdip --] primrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 ranger_reverse')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 2 3 4 5]
|
||||
|
||||
|
||||
Hopefully this illustrates the workings of the variations. For more
|
||||
insight you can run the cells using the ``V()`` function instead of the
|
||||
``J()`` function to get a trace of the Joy evaluation.
|
||||
|
||||
Catamorphism
|
||||
------------
|
||||
|
||||
A catamorphism can be defined as a hylomorphism that uses
|
||||
``[uncons swap]`` for ``[G]`` and ``[[] =]`` (or just ``[not]``) for the
|
||||
predicate ``[P]``. A catamorphic function tears down a list term-by-term
|
||||
and makes some new value.
|
||||
|
||||
::
|
||||
|
||||
C == [not] c [uncons swap] [F] hylomorphism
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('swuncons == uncons swap') # Awkward name.
|
||||
|
||||
An example of a catamorphism is the sum function.
|
||||
|
||||
::
|
||||
|
||||
sum == [not] 0 [swuncons] [+] hylomorphism
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('sum == [not] 0 [swuncons] [+] hylomorphism')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[5 4 3 2 1] sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
15
|
||||
|
||||
|
||||
The ``step`` combinator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``step`` combinator will usually be better to use than
|
||||
``catamorphism``.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[step] help')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
Run a quoted program on each item in a sequence.
|
||||
::
|
||||
|
||||
... [] [Q] . step
|
||||
-----------------------
|
||||
... .
|
||||
|
||||
|
||||
... [a] [Q] . step
|
||||
------------------------
|
||||
... a . Q
|
||||
|
||||
|
||||
... [a b c] [Q] . step
|
||||
----------------------------------------
|
||||
... a . Q [b c] [Q] step
|
||||
|
||||
The step combinator executes the quotation on each member of the list
|
||||
on top of the stack.
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('sum == 0 swap [+] step')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[5 4 3 2 1] sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
15
|
||||
|
||||
|
||||
Example: Factorial Function
|
||||
---------------------------
|
||||
|
||||
For the Factorial function:
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
With:
|
||||
|
||||
::
|
||||
|
||||
c == 1
|
||||
F == *
|
||||
G == --
|
||||
P == 1 <=
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 factorial')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
120
|
||||
|
||||
|
||||
Example: ``tails``
|
||||
------------------
|
||||
|
||||
An example of a paramorphism for lists given in the `"Bananas..."
|
||||
paper <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
is ``tails`` which returns the list of "tails" of a list.
|
||||
|
||||
::
|
||||
|
||||
[1 2 3] tails
|
||||
--------------------
|
||||
[[] [3] [2 3]]
|
||||
|
||||
We can build as we go, and we want ``F`` to run after ``G``, so we use
|
||||
pattern ``H2``:
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
We would use:
|
||||
|
||||
::
|
||||
|
||||
c == []
|
||||
F == swons
|
||||
G == rest dup
|
||||
P == not
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 2 3] tails')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[[] [3] [2 3]]
|
||||
|
||||
|
||||
Conclusion: Patterns of Recursion
|
||||
---------------------------------
|
||||
|
||||
Our story so far...
|
||||
|
||||
Hylo-, Ana-, Cata-
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
H == [P ] [pop c ] [G ] [dip F ] genrec
|
||||
A == [P ] [pop []] [G ] [dip swap cons] genrec
|
||||
C == [not] [pop c ] [uncons swap] [dip F ] genrec
|
||||
|
||||
Para-, ?-, ?-
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
P == c swap [P ] [pop] [[F ] dupdip G ] primrec
|
||||
? == [] swap [P ] [pop] [[swap cons] dupdip G ] primrec
|
||||
? == c swap [not] [pop] [[F ] dupdip uncons swap] primrec
|
||||
|
||||
Appendix: Fun with Symbols
|
||||
--------------------------
|
||||
|
||||
::
|
||||
|
||||
|[ (c, F), (G, P) ]| == (|c, F|) • [(G, P)]
|
||||
|
||||
`"Bananas, Lenses, & Barbed
|
||||
Wire" <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
|
||||
::
|
||||
|
||||
(|...|) [(...)] [<...>]
|
||||
|
||||
I think they are having slightly too much fun with the symbols. However,
|
||||
"Too much is always better than not enough."
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
|
@ -61,7 +61,7 @@
|
|||
<span class="kn">import</span> <span class="nn">operator</span><span class="o">,</span> <span class="nn">math</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">.parser</span> <span class="k">import</span> <span class="n">text_to_expression</span><span class="p">,</span> <span class="n">Symbol</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils.stack</span> <span class="k">import</span> <span class="n">list_to_stack</span><span class="p">,</span> <span class="n">iter_stack</span><span class="p">,</span> <span class="n">pick</span><span class="p">,</span> <span class="n">pushback</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils.stack</span> <span class="k">import</span> <span class="n">list_to_stack</span><span class="p">,</span> <span class="n">iter_stack</span><span class="p">,</span> <span class="n">pick</span><span class="p">,</span> <span class="n">concat</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils.brutal_hackery</span> <span class="k">import</span> <span class="n">rename_code_object</span>
|
||||
|
||||
|
||||
|
|
@ -136,9 +136,9 @@
|
|||
<span class="s1">? == dup truthy</span>
|
||||
<span class="s1">dinfrirst == dip infra first</span>
|
||||
<span class="s1">nullary == [stack] dinfrirst</span>
|
||||
<span class="s1">unary == [stack [pop] dip] dinfrirst</span>
|
||||
<span class="s1">binary == [stack [popop] dip] dinfrirst</span>
|
||||
<span class="s1">ternary == [stack [popop pop] dip] dinfrirst</span>
|
||||
<span class="s1">unary == nullary popd</span>
|
||||
<span class="s1">binary == nullary [popop] dip</span>
|
||||
<span class="s1">ternary == unary [popop] dip</span>
|
||||
<span class="s1">pam == [i] map</span>
|
||||
<span class="s1">run == [] swap infra</span>
|
||||
<span class="s1">sqr == dup mul</span>
|
||||
|
|
@ -678,9 +678,9 @@
|
|||
<span class="k">return</span> <span class="n">res</span><span class="p">,</span> <span class="n">stack</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="concat"><a class="viewcode-back" href="../../library.html#joy.library.concat">[docs]</a><span class="nd">@inscribe</span>
|
||||
<div class="viewcode-block" id="concat_"><a class="viewcode-back" href="../../library.html#joy.library.concat_">[docs]</a><span class="nd">@inscribe</span>
|
||||
<span class="nd">@SimpleFunctionWrapper</span>
|
||||
<span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">S</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">concat_</span><span class="p">(</span><span class="n">S</span><span class="p">):</span>
|
||||
<span class="sd">'''Concatinate the two lists on the top of the stack.</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
|
|
@ -690,9 +690,7 @@
|
|||
|
||||
<span class="sd">'''</span>
|
||||
<span class="p">(</span><span class="n">tos</span><span class="p">,</span> <span class="p">(</span><span class="n">second</span><span class="p">,</span> <span class="n">stack</span><span class="p">))</span> <span class="o">=</span> <span class="n">S</span>
|
||||
<span class="k">for</span> <span class="n">term</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">iter_stack</span><span class="p">(</span><span class="n">second</span><span class="p">))):</span>
|
||||
<span class="n">tos</span> <span class="o">=</span> <span class="n">term</span><span class="p">,</span> <span class="n">tos</span>
|
||||
<span class="k">return</span> <span class="n">tos</span><span class="p">,</span> <span class="n">stack</span></div>
|
||||
<span class="k">return</span> <span class="n">concat</span><span class="p">(</span><span class="n">second</span><span class="p">,</span> <span class="n">tos</span><span class="p">),</span> <span class="n">stack</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="shunt"><a class="viewcode-back" href="../../library.html#joy.library.shunt">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -963,7 +961,7 @@
|
|||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">quote</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="x"><a class="viewcode-back" href="../../library.html#joy.library.x">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -980,7 +978,7 @@
|
|||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">quote</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="b"><a class="viewcode-back" href="../../library.html#joy.library.b">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -996,7 +994,7 @@
|
|||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">q</span><span class="p">,</span> <span class="p">(</span><span class="n">p</span><span class="p">,</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="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">pushback</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">pushback</span><span class="p">(</span><span class="n">q</span><span class="p">,</span> <span class="n">expression</span><span class="p">)),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">q</span><span class="p">,</span> <span class="n">expression</span><span class="p">)),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="dupdip"><a class="viewcode-back" href="../../library.html#joy.library.dupdip">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -1015,7 +1013,7 @@
|
|||
<span class="sd"> '''</span>
|
||||
<span class="n">F</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">pushback</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">expression</span><span class="p">)),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">expression</span><span class="p">)),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="infra"><a class="viewcode-back" href="../../library.html#joy.library.infra">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -1032,7 +1030,7 @@
|
|||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">aggregate</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="k">return</span> <span class="n">aggregate</span><span class="p">,</span> <span class="n">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="p">(</span><span class="n">S_swaack</span><span class="p">,</span> <span class="n">expression</span><span class="p">))),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">aggregate</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="p">(</span><span class="n">S_swaack</span><span class="p">,</span> <span class="n">expression</span><span class="p">))),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="genrec"><a class="viewcode-back" href="../../library.html#joy.library.genrec">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -1092,7 +1090,7 @@
|
|||
<span class="p">(</span><span class="n">rec2</span><span class="p">,</span> <span class="p">(</span><span class="n">rec1</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="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">if_</span><span class="p">,</span> <span class="n">_</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="n">F</span> <span class="o">=</span> <span class="p">(</span><span class="n">if_</span><span class="p">,</span> <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">rec1</span><span class="p">,</span> <span class="p">(</span><span class="n">rec2</span><span class="p">,</span> <span class="p">(</span><span class="n">S_genrec</span><span class="p">,</span> <span class="p">())))))</span>
|
||||
<span class="n">else_</span> <span class="o">=</span> <span class="n">pushback</span><span class="p">(</span><span class="n">rec1</span><span class="p">,</span> <span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="n">rec2</span><span class="p">))</span>
|
||||
<span class="n">else_</span> <span class="o">=</span> <span class="n">concat</span><span class="p">(</span><span class="n">rec1</span><span class="p">,</span> <span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="n">rec2</span><span class="p">))</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="n">stack</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">dictionary</span></div>
|
||||
|
||||
|
||||
|
|
@ -1156,7 +1154,7 @@
|
|||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</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="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">pushback</span><span class="p">(</span><span class="n">then</span> <span class="k">if</span> <span class="n">flag</span> <span class="k">else</span> <span class="n">else_</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">then</span> <span class="k">if</span> <span class="n">flag</span> <span class="k">else</span> <span class="n">else_</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="ifte"><a class="viewcode-back" href="../../library.html#joy.library.ifte">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -1243,7 +1241,7 @@
|
|||
<span class="sd"> '''</span>
|
||||
<span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">x</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="p">(</span><span class="n">x</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">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="dipd"><a class="viewcode-back" href="../../library.html#joy.library.dipd">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -1260,7 +1258,7 @@
|
|||
<span class="sd"> '''</span>
|
||||
<span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">S</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="n">x</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">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="dipdd"><a class="viewcode-back" href="../../library.html#joy.library.dipdd">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -1277,7 +1275,7 @@
|
|||
<span class="sd"> '''</span>
|
||||
<span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="n">stack</span><span class="p">))))</span> <span class="o">=</span> <span class="n">S</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="n">x</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">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="app1"><a class="viewcode-back" href="../../library.html#joy.library.app1">[docs]</a><span class="nd">@inscribe</span>
|
||||
|
|
@ -1405,7 +1403,7 @@
|
|||
<span class="n">n</span> <span class="o">-=</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="n">n</span><span class="p">:</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">n</span><span class="p">,</span> <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">S_times</span><span class="p">,</span> <span class="n">expression</span><span class="p">))</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</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></div>
|
||||
|
||||
|
||||
|
|
@ -1443,7 +1441,7 @@
|
|||
<span class="sd"> '''</span>
|
||||
<span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</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="k">if</span> <span class="n">flag</span><span class="p">:</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">S_loop</span><span class="p">,</span> <span class="n">expression</span><span class="p">)))</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">S_loop</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></div>
|
||||
|
||||
|
||||
|
|
@ -1468,7 +1466,7 @@
|
|||
<span class="sd"> L</span>
|
||||
<span class="sd"> '''</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">></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"><</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="n">expression</span> <span class="o">=</span> <span class="n">concat</span><span class="p">(</span><span class="n">G</span> <span class="k">if</span> <span class="n">a</span> <span class="o">></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"><</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></div>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@
|
|||
<span class="p">)</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="pushback"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.pushback">[docs]</a><span class="k">def</span> <span class="nf">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
|
||||
<div class="viewcode-block" id="concat"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.concat">[docs]</a><span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
|
||||
<span class="sd">'''Concatinate quote onto expression.</span>
|
||||
|
||||
<span class="sd"> In joy [1 2] [3 4] would become [1 2 3 4].</span>
|
||||
|
|
@ -188,7 +188,8 @@
|
|||
<span class="c1"># This is the fastest implementation, but will trigger</span>
|
||||
<span class="c1"># RuntimeError: maximum recursion depth exceeded</span>
|
||||
<span class="c1"># on quotes longer than sys.getrecursionlimit().</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">quote</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">pushback</span><span class="p">(</span><span class="n">quote</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">expression</span><span class="p">))</span> <span class="k">if</span> <span class="n">quote</span> <span class="k">else</span> <span class="n">expression</span></div>
|
||||
|
||||
<span class="c1">## return (quote[0], concat(quote[1], expression)) if quote else expression</span>
|
||||
|
||||
<span class="c1"># Original implementation.</span>
|
||||
|
||||
|
|
@ -197,13 +198,13 @@
|
|||
<span class="c1"># In-lining is slightly faster (and won't break the</span>
|
||||
<span class="c1"># recursion limit on long quotes.)</span>
|
||||
|
||||
<span class="c1">## temp = []</span>
|
||||
<span class="c1">## while quote:</span>
|
||||
<span class="c1">## item, quote = quote</span>
|
||||
<span class="c1">## temp.append(item)</span>
|
||||
<span class="c1">## for item in reversed(temp):</span>
|
||||
<span class="c1">## expression = item, expression</span>
|
||||
<span class="c1">## return expression</span>
|
||||
<span class="n">temp</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">while</span> <span class="n">quote</span><span class="p">:</span>
|
||||
<span class="n">item</span><span class="p">,</span> <span class="n">quote</span> <span class="o">=</span> <span class="n">quote</span>
|
||||
<span class="n">temp</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">temp</span><span class="p">):</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">item</span><span class="p">,</span> <span class="n">expression</span>
|
||||
<span class="k">return</span> <span class="n">expression</span></div>
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,9 @@
|
|||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.concat">concat() (in module joy.library)</a>
|
||||
<li><a href="stack.html#joy.utils.stack.concat">concat() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.concat_">concat_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.cond">cond() (in module joy.library)</a>
|
||||
</li>
|
||||
|
|
@ -283,8 +285,6 @@
|
|||
<li><a href="library.html#joy.library.popop">popop() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.pred">pred() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="stack.html#joy.utils.stack.pushback">pushback() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
|
|
|||
|
|
@ -132,13 +132,15 @@ interesting aspects. It’s quite a treasure trove.</p>
|
|||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/index.html">Essays about Programming in Joy</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Recursion_Combinators.html">Recursive Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Types.html">Type Inference</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Categorical.html">Categorical Programming</a></li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -214,8 +214,8 @@ one of the three depending on the results of comparing the two values:</p>
|
|||
</dd></dl>
|
||||
|
||||
<dl class="function">
|
||||
<dt id="joy.library.concat">
|
||||
<code class="descclassname">joy.library.</code><code class="descname">concat</code><span class="sig-paren">(</span><em>stack</em>, <em>expression</em>, <em>dictionary</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/library.html#concat"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.library.concat" title="Permalink to this definition">¶</a></dt>
|
||||
<dt id="joy.library.concat_">
|
||||
<code class="descclassname">joy.library.</code><code class="descname">concat_</code><span class="sig-paren">(</span><em>stack</em>, <em>expression</em>, <em>dictionary</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/library.html#concat_"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.library.concat_" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Concatinate the two lists on the top of the stack.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="n">a</span> <span class="n">b</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">d</span> <span class="n">e</span> <span class="n">f</span><span class="p">]</span> <span class="n">concat</span>
|
||||
<span class="o">----------------------------</span>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Quadratic formula" href="Quadratic.html" />
|
||||
<link rel="next" title="Traversing Datastructures with Zippers" href="Zipper.html" />
|
||||
<link rel="prev" title="Using x to Generate Values" href="Generator_Programs.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
|
@ -257,7 +257,7 @@ generated already and epsilon ε is handy on the stack…</p>
|
|||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Generator_Programs.html" title="previous chapter">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li>Next: <a href="Quadratic.html" title="next chapter">Quadratic formula</a></li>
|
||||
<li>Next: <a href="Zipper.html" title="next chapter">Traversing Datastructures with Zippers</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Traversing Datastructures with Zippers" href="Zipper.html" />
|
||||
<link rel="prev" title="Newton’s method" href="Newton-Raphson.html" />
|
||||
<link rel="next" title="Replacing Functions in the Dictionary" href="Replacing.html" />
|
||||
<link rel="prev" title="Developing a Program in Joy" href="Developing.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
|
@ -32,156 +32,136 @@
|
|||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="quadratic-formula">
|
||||
<h1><a class="reference external" href="https://en.wikipedia.org/wiki/Quadratic_formula">Quadratic formula</a><a class="headerlink" href="#quadratic-formula" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">notebook_preamble</span> <span class="k">import</span> <span class="n">J</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">define</span>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">notebook_preamble</span> <span class="k">import</span> <span class="n">J</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">define</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="section" id="quadratic-formula">
|
||||
<h1><a class="reference external" href="https://en.wikipedia.org/wiki/Quadratic_formula">Quadratic formula</a><a class="headerlink" href="#quadratic-formula" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Cf.
|
||||
<a class="reference external" href="http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html">jp-quadratic.html</a></p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">-</span><span class="n">b</span> <span class="o">+/-</span> <span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">a</span> <span class="o">*</span> <span class="n">c</span><span class="p">)</span>
|
||||
<span class="o">-----------------------------</span>
|
||||
<span class="mi">2</span> <span class="o">*</span> <span class="n">a</span>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> -b ± sqrt(b^2 - 4 * a * c)
|
||||
--------------------------------
|
||||
2 * a
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><span class="math notranslate nohighlight">\(\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\)</span></p>
|
||||
<div class="section" id="write-a-straightforward-program-with-variable-names">
|
||||
<h2>Write a straightforward program with variable names.<a class="headerlink" href="#write-a-straightforward-program-with-variable-names" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<p>This math translates to Joy code in a straightforward manner. We are
|
||||
going to use named variables to keep track of the arguments, then write
|
||||
a definition without them.</p>
|
||||
<div class="section" id="b">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">-b</span></code><a class="headerlink" href="#b" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We use <code class="docutils literal notranslate"><span class="pre">cleave</span></code> to compute the sum and difference and then <code class="docutils literal notranslate"><span class="pre">app2</span></code> to
|
||||
finish computing both roots using a quoted program <code class="docutils literal notranslate"><span class="pre">[2a</span> <span class="pre">truediv]</span></code>
|
||||
built with <code class="docutils literal notranslate"><span class="pre">cons</span></code>.</p>
|
||||
<div class="section" id="check-it">
|
||||
<h3>Check it.<a class="headerlink" href="#check-it" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evaluating by hand:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">b</span> <span class="n">neg</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="n">b</span><span class="o">^</span><span class="mi">2</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="n">b</span><span class="o">^</span><span class="mi">2</span> <span class="mi">4</span><span class="n">ac</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
|
||||
<span class="o">-</span><span class="n">b</span> <span class="o">-</span><span class="n">b</span><span class="o">+</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span> <span class="o">-</span><span class="n">b</span><span class="o">-</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="o">-</span><span class="n">b</span><span class="o">+</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span> <span class="o">-</span><span class="n">b</span><span class="o">-</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span> <span class="mi">2</span><span class="n">a</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="o">-</span><span class="n">b</span><span class="o">+</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span> <span class="o">-</span><span class="n">b</span><span class="o">-</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span> <span class="p">[</span><span class="mi">2</span><span class="n">a</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="n">b</span> <span class="o">-</span><span class="n">b</span><span class="o">+</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span> <span class="o">-</span><span class="n">b</span><span class="o">-</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span>
|
||||
</div>
|
||||
<div class="section" id="sqrt-b-2-4-a-c">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">sqrt(b^2</span> <span class="pre">-</span> <span class="pre">4</span> <span class="pre">*</span> <span class="pre">a</span> <span class="pre">*</span> <span class="pre">c)</span></code><a class="headerlink" href="#sqrt-b-2-4-a-c" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>(Eventually we’ll be able to use e.g. Sympy versions of the Joy commands
|
||||
to do this sort of thing symbolically. This is part of what is meant by
|
||||
a “categorical” language.)</p>
|
||||
</div>
|
||||
<div class="section" id="cleanup">
|
||||
<h3>Cleanup<a class="headerlink" href="#cleanup" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">-</span><span class="n">b</span> <span class="o">-</span><span class="n">b</span><span class="o">+</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span> <span class="o">-</span><span class="n">b</span><span class="o">-</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span> <span class="n">roll</span><span class="o"><</span> <span class="n">pop</span>
|
||||
<span class="o">-</span><span class="n">b</span><span class="o">+</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span> <span class="o">-</span><span class="n">b</span><span class="o">-</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span> <span class="o">-</span><span class="n">b</span> <span class="n">pop</span>
|
||||
<span class="o">-</span><span class="n">b</span><span class="o">+</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span> <span class="o">-</span><span class="n">b</span><span class="o">-</span><span class="n">sqrt</span><span class="p">(</span><span class="n">b</span><span class="o">^</span><span class="mi">2</span><span class="o">-</span><span class="mi">4</span><span class="n">ac</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="n">a</span>
|
||||
<div class="section" id="a">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">/2a</span></code><a class="headerlink" href="#a" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="o">/</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="id1">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">±</span></code><a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h3>
|
||||
<p>There is a function <code class="docutils literal notranslate"><span class="pre">pm</span></code> that accepts two values on the stack and
|
||||
replaces them with their sum and difference.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pm</span> <span class="o">==</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">popdd</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="putting-them-together">
|
||||
<h3>Putting Them Together<a class="headerlink" href="#putting-them-together" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We use <code class="docutils literal notranslate"><span class="pre">app2</span></code> to compute both roots by using a quoted program
|
||||
<code class="docutils literal notranslate"><span class="pre">[2a</span> <span class="pre">/]</span></code> built with <code class="docutils literal notranslate"><span class="pre">cons</span></code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="derive-a-definition">
|
||||
<h2>Derive a definition.<a class="headerlink" href="#derive-a-definition" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span> <span class="n">roll</span><span class="o"><</span> <span class="n">pop</span>
|
||||
<span class="n">b</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span> <span class="n">roll</span><span class="o"><</span> <span class="n">pop</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span> <span class="n">roll</span><span class="o"><</span> <span class="n">pop</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="n">a</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span> <span class="n">roll</span><span class="o"><</span> <span class="n">pop</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="n">over</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span> <span class="n">roll</span><span class="o"><</span> <span class="n">pop</span>
|
||||
<p>Working backwards we use <code class="docutils literal notranslate"><span class="pre">dip</span></code> and <code class="docutils literal notranslate"><span class="pre">dipd</span></code> to extract the code from
|
||||
the variables:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="n">a</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="n">over</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">'quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop'</span><span class="p">)</span>
|
||||
<p>The three arguments are to the left, so we can “chop off” everything to
|
||||
the right and say it’s the definition of the <code class="docutils literal notranslate"><span class="pre">quadratic</span></code> function:</p>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">'quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s try it out:</p>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">'3 1 1 quadratic'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="o">-</span><span class="mf">2.618033988749895</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="simplify">
|
||||
<h2>Simplify<a class="headerlink" href="#simplify" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We can define a <code class="docutils literal notranslate"><span class="pre">pm</span></code> plus-or-minus function:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pm</span> <span class="o">==</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">popdd</span>
|
||||
<p>If you look at the Joy evaluation trace you can see that the first few
|
||||
lines are the <code class="docutils literal notranslate"><span class="pre">dip</span></code> and <code class="docutils literal notranslate"><span class="pre">dipd</span></code> combinators building the main program
|
||||
by incorporating the values on the stack. Then that program runs and you
|
||||
get the results. This is pretty typical of Joy code.</p>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">'-5 1 4 quadratic'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Then <code class="docutils literal notranslate"><span class="pre">quadratic</span></code> becomes:</p>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">'quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2'</span><span class="p">)</span>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">.</span> <span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">4</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">4</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="n">over</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="mi">1</span> <span class="o">.</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="mi">1</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="o">.</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="o">.</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="o">.</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">neg</span> <span class="o">-</span><span class="mi">5</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">.</span> <span class="o">-</span><span class="mi">5</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">dup</span> <span class="n">mul</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">mul</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="o">.</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="mi">4</span> <span class="o">.</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">16</span> <span class="o">.</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">9</span> <span class="o">.</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mf">3.0</span> <span class="o">.</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">app2</span>
|
||||
<span class="p">[</span><span class="mf">8.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">8.0</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">/</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">8.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">/</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="o">.</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="o">.</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">2.0</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">/</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">2.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">/</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">1.0</span> <span class="o">.</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">1.0</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[</span><span class="mf">1.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="mf">1.0</span> <span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">'3 1 1 quadratic'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="o">-</span><span class="mf">2.618033988749895</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="section" id="define-a-native-pm-function">
|
||||
<h3>Define a “native” <code class="docutils literal notranslate"><span class="pre">pm</span></code> function.<a class="headerlink" href="#define-a-native-pm-function" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The definition of <code class="docutils literal notranslate"><span class="pre">pm</span></code> above is pretty elegant, but the implementation
|
||||
takes a lot of steps relative to what it’s accomplishing. Since we are
|
||||
likely to use <code class="docutils literal notranslate"><span class="pre">pm</span></code> more than once in the future, let’s write a
|
||||
primitive in Python and add it to the dictionary. (This has been done
|
||||
already.)</p>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">pm</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="n">a</span><span class="p">,</span> <span class="p">(</span><span class="n">b</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">p</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="o">=</span> <span class="n">b</span> <span class="o">+</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">-</span> <span class="n">a</span>
|
||||
<span class="k">return</span> <span class="n">m</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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The resulting trace is short enough to fit on a page.</p>
|
||||
<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">'3 1 1 quadratic'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">.</span> <span class="mi">3</span> <span class="mi">1</span> <span class="mi">1</span> <span class="n">quadratic</span>
|
||||
<span class="mi">3</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">1</span> <span class="n">quadratic</span>
|
||||
<span class="mi">3</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">1</span> <span class="n">quadratic</span>
|
||||
<span class="mi">3</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">.</span> <span class="n">quadratic</span>
|
||||
<span class="mi">3</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">.</span> <span class="n">over</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">3</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">.</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">3</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="o">.</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">3</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">.</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">3</span> <span class="mi">1</span> <span class="mi">1</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="o">.</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">3</span> <span class="o">.</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">3</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="o">.</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">3</span> <span class="o">.</span> <span class="n">neg</span> <span class="mi">3</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="o">.</span> <span class="mi">3</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">3</span> <span class="o">.</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">3</span> <span class="o">.</span> <span class="n">dup</span> <span class="n">mul</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">3</span> <span class="mi">3</span> <span class="o">.</span> <span class="n">mul</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">9</span> <span class="o">.</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">9</span> <span class="mi">4</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">9</span> <span class="mi">4</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">1</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">9</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">1</span> <span class="o">.</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">9</span> <span class="mi">4</span> <span class="mi">1</span> <span class="o">.</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">9</span> <span class="mi">4</span> <span class="o">.</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mi">5</span> <span class="o">.</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">3</span> <span class="mf">2.23606797749979</span> <span class="o">.</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="o">-</span><span class="mf">5.23606797749979</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="o">-</span><span class="mf">5.23606797749979</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="o">-</span><span class="mf">5.23606797749979</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">*</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="o">-</span><span class="mf">5.23606797749979</span> <span class="mi">2</span> <span class="o">.</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="o">-</span><span class="mf">5.23606797749979</span> <span class="mi">2</span> <span class="p">[</span><span class="n">truediv</span><span class="p">]</span> <span class="o">.</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="o">-</span><span class="mf">5.23606797749979</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="o">.</span> <span class="n">app2</span>
|
||||
<span class="p">[</span><span class="o">-</span><span class="mf">0.7639320225002102</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="o">.</span> <span class="mi">2</span> <span class="n">truediv</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.7639320225002102</span> <span class="mi">2</span> <span class="o">.</span> <span class="n">truediv</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="o">.</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="p">[]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="p">[</span><span class="o">-</span><span class="mf">0.3819660112501051</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="o">.</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="p">[</span><span class="o">-</span><span class="mf">5.23606797749979</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="n">truediv</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">5.23606797749979</span> <span class="o">.</span> <span class="mi">2</span> <span class="n">truediv</span> <span class="p">[</span><span class="o">-</span><span class="mf">0.3819660112501051</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">5.23606797749979</span> <span class="mi">2</span> <span class="o">.</span> <span class="n">truediv</span> <span class="p">[</span><span class="o">-</span><span class="mf">0.3819660112501051</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">2.618033988749895</span> <span class="o">.</span> <span class="p">[</span><span class="o">-</span><span class="mf">0.3819660112501051</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">2.618033988749895</span> <span class="p">[</span><span class="o">-</span><span class="mf">0.3819660112501051</span><span class="p">]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="p">[</span><span class="o">-</span><span class="mf">2.618033988749895</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span>
|
||||
<span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="o">-</span><span class="mf">2.618033988749895</span> <span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -195,15 +175,14 @@ already.)</p>
|
|||
<ul>
|
||||
<li><a class="reference internal" href="#">Quadratic formula</a><ul>
|
||||
<li><a class="reference internal" href="#write-a-straightforward-program-with-variable-names">Write a straightforward program with variable names.</a><ul>
|
||||
<li><a class="reference internal" href="#check-it">Check it.</a></li>
|
||||
<li><a class="reference internal" href="#cleanup">Cleanup</a></li>
|
||||
<li><a class="reference internal" href="#b"><code class="docutils literal notranslate"><span class="pre">-b</span></code></a></li>
|
||||
<li><a class="reference internal" href="#sqrt-b-2-4-a-c"><code class="docutils literal notranslate"><span class="pre">sqrt(b^2</span> <span class="pre">-</span> <span class="pre">4</span> <span class="pre">*</span> <span class="pre">a</span> <span class="pre">*</span> <span class="pre">c)</span></code></a></li>
|
||||
<li><a class="reference internal" href="#a"><code class="docutils literal notranslate"><span class="pre">/2a</span></code></a></li>
|
||||
<li><a class="reference internal" href="#id1"><code class="docutils literal notranslate"><span class="pre">±</span></code></a></li>
|
||||
<li><a class="reference internal" href="#putting-them-together">Putting Them Together</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#derive-a-definition">Derive a definition.</a></li>
|
||||
<li><a class="reference internal" href="#simplify">Simplify</a><ul>
|
||||
<li><a class="reference internal" href="#define-a-native-pm-function">Define a “native” <code class="docutils literal notranslate"><span class="pre">pm</span></code> function.</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -212,8 +191,8 @@ already.)</p>
|
|||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Newton-Raphson.html" title="previous chapter">Newton’s method</a></li>
|
||||
<li>Next: <a href="Zipper.html" title="next chapter">Traversing Datastructures with Zippers</a></li>
|
||||
<li>Previous: <a href="Developing.html" title="previous chapter">Developing a Program in Joy</a></li>
|
||||
<li>Next: <a href="Replacing.html" title="next chapter">Replacing Functions in the Dictionary</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="No Updates" href="NoUpdates.html" />
|
||||
<link rel="prev" title="Quadratic formula" href="Quadratic.html" />
|
||||
<link rel="next" title="Type Inference" href="Types.html" />
|
||||
<link rel="prev" title="Newton’s method" href="Newton-Raphson.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
|
@ -326,8 +326,8 @@ i d i d i d d Bingo!
|
|||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Quadratic.html" title="previous chapter">Quadratic formula</a></li>
|
||||
<li>Next: <a href="NoUpdates.html" title="next chapter">No Updates</a></li>
|
||||
<li>Previous: <a href="Newton-Raphson.html" title="previous chapter">Newton’s method</a></li>
|
||||
<li>Next: <a href="Types.html" title="next chapter">Type Inference</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -44,12 +44,32 @@
|
|||
<li class="toctree-l2"><a class="reference internal" href="Developing.html#the-simplest-program">The Simplest Program</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Quadratic.html">Quadratic formula</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html#write-a-straightforward-program-with-variable-names">Write a straightforward program with variable names.</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html#derive-a-definition">Derive a definition.</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html#a-long-trace">A long trace</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html#replacing-size-with-a-python-version">Replacing <code class="docutils literal notranslate"><span class="pre">size</span></code> with a Python version</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html#a-shorter-trace">A shorter trace</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Recursion_Combinators.html">Recursive Combinators</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#designing-recursive-functions">Designing Recursive Functions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#primitive-recursive-functions">Primitive Recursive Functions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#hylomorphism">Hylomorphism</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#hylomorphism-in-joy">Hylomorphism in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#derivation-of-hylomorphism-combinator">Derivation of <code class="docutils literal notranslate"><span class="pre">hylomorphism</span></code> combinator</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#four-specializations">Four Specializations</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#anamorphism">Anamorphism</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#catamorphism">Catamorphism</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#example-factorial-function">Example: Factorial Function</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#example-tails">Example: <code class="docutils literal notranslate"><span class="pre">tails</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#conclusion-patterns-of-recursion">Conclusion: Patterns of Recursion</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html#appendix-fun-with-symbols">Appendix: Fun with Symbols</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html#adding-nodes-to-the-tree">Adding Nodes to the Tree</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html#interlude-cmp-combinator">Interlude: <code class="docutils literal notranslate"><span class="pre">cmp</span></code> combinator</a></li>
|
||||
|
|
@ -89,12 +109,6 @@
|
|||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html#finding-consecutive-approximations-within-a-tolerance">Finding Consecutive Approximations within a Tolerance</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Quadratic.html">Quadratic formula</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html#write-a-straightforward-program-with-variable-names">Write a straightforward program with variable names.</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html#derive-a-definition">Derive a definition.</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html#simplify">Simplify</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html#trees">Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html#zipper-in-joy">Zipper in Joy</a></li>
|
||||
|
|
@ -104,6 +118,20 @@
|
|||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html#determining-the-right-path-for-an-item-in-a-tree">Determining the right “path” for an item in a tree.</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Types.html">Type Inference</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#poial-s-rules">Pöial’s Rules</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#examples">Examples</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#implementation">Implementation</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#compiling">Compiling</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#types-and-subtypes-of-arguments">Types and Subtypes of Arguments</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#functions-that-use-the-stack">Functions that use the Stack</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#sets-of-stack-effects">Sets of Stack Effects</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#concat"><code class="docutils literal notranslate"><span class="pre">concat</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#typing-combinators">Typing Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#abstract-interpretation">Abstract Interpretation</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html#something-else">Something else…</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
</ul>
|
||||
|
|
|
|||
Binary file not shown.
File diff suppressed because one or more lines are too long
|
|
@ -80,6 +80,31 @@ iterable and another to iterate through a stack and yield its items
|
|||
one-by-one in order. There are also two functions to generate string representations
|
||||
of stacks. They only differ in that one prints the terms in stack from left-to-right while the other prints from right-to-left. In both functions <em>internal stacks</em> are
|
||||
printed left-to-right. These functions are written to support <a class="reference internal" href="pretty.html"><span class="doc">Tracing Joy Execution</span></a>.</p>
|
||||
<dl class="function">
|
||||
<dt id="joy.utils.stack.concat">
|
||||
<code class="descclassname">joy.utils.stack.</code><code class="descname">concat</code><span class="sig-paren">(</span><em>quote</em>, <em>expression</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/stack.html#concat"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.stack.concat" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Concatinate quote onto expression.</p>
|
||||
<p>In joy [1 2] [3 4] would become [1 2 3 4].</p>
|
||||
<table class="docutils field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||
<li><strong>quote</strong> (<em>stack</em>) – A stack.</li>
|
||||
<li><strong>expression</strong> (<em>stack</em>) – A stack.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field-even field"><th class="field-name">Raises:</th><td class="field-body"><p class="first"><strong>RuntimeError</strong> – if quote is larger than sys.getrecursionlimit().</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field-odd field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">stack</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="function">
|
||||
<dt id="joy.utils.stack.expression_to_string">
|
||||
<code class="descclassname">joy.utils.stack.</code><code class="descname">expression_to_string</code><span class="sig-paren">(</span><em>expression</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/stack.html#expression_to_string"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.stack.expression_to_string" title="Permalink to this definition">¶</a></dt>
|
||||
|
|
@ -168,31 +193,6 @@ won’t work because <code class="docutils literal notranslate"><span class="pre
|
|||
</table>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="function">
|
||||
<dt id="joy.utils.stack.pushback">
|
||||
<code class="descclassname">joy.utils.stack.</code><code class="descname">pushback</code><span class="sig-paren">(</span><em>quote</em>, <em>expression</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/stack.html#pushback"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.stack.pushback" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Concatinate quote onto expression.</p>
|
||||
<p>In joy [1 2] [3 4] would become [1 2 3 4].</p>
|
||||
<table class="docutils field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||
<li><strong>quote</strong> (<em>stack</em>) – A stack.</li>
|
||||
<li><strong>expression</strong> (<em>stack</em>) – A stack.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field-even field"><th class="field-name">Raises:</th><td class="field-body"><p class="first"><strong>RuntimeError</strong> – if quote is larger than sys.getrecursionlimit().</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field-odd field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">stack</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="function">
|
||||
<dt id="joy.utils.stack.stack_to_string">
|
||||
<code class="descclassname">joy.utils.stack.</code><code class="descname">stack_to_string</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/stack.html#stack_to_string"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.stack.stack_to_string" title="Permalink to this definition">¶</a></dt>
|
||||
|
|
|
|||
|
|
@ -1,104 +1,92 @@
|
|||
|
||||
`Quadratic formula <https://en.wikipedia.org/wiki/Quadratic_formula>`__
|
||||
=======================================================================
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
`Quadratic formula <https://en.wikipedia.org/wiki/Quadratic_formula>`__
|
||||
=======================================================================
|
||||
|
||||
Cf.
|
||||
`jp-quadratic.html <http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html>`__
|
||||
|
||||
::
|
||||
|
||||
-b +/- sqrt(b^2 - 4 * a * c)
|
||||
-----------------------------
|
||||
2 * a
|
||||
-b ± sqrt(b^2 - 4 * a * c)
|
||||
--------------------------------
|
||||
2 * a
|
||||
|
||||
:math:`\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}`
|
||||
|
||||
Write a straightforward program with variable names.
|
||||
----------------------------------------------------
|
||||
|
||||
::
|
||||
This math translates to Joy code in a straightforward manner. We are
|
||||
going to use named variables to keep track of the arguments, then write
|
||||
a definition without them.
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
|
||||
We use ``cleave`` to compute the sum and difference and then ``app2`` to
|
||||
finish computing both roots using a quoted program ``[2a truediv]``
|
||||
built with ``cons``.
|
||||
|
||||
Check it.
|
||||
~~~~~~~~~
|
||||
|
||||
Evaluating by hand:
|
||||
``-b``
|
||||
~~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2 4ac - sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b b^2-4ac sqrt [+] [-] cleave a 2 * [truediv] cons app2
|
||||
-b sqrt(b^2-4ac) [+] [-] cleave a 2 * [truediv] cons app2
|
||||
b neg
|
||||
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) a 2 * [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) 2a [truediv] cons app2
|
||||
-b -b+sqrt(b^2-4ac) -b-sqrt(b^2-4ac) [2a truediv] app2
|
||||
-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a
|
||||
``sqrt(b^2 - 4 * a * c)``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
(Eventually we’ll be able to use e.g. Sympy versions of the Joy commands
|
||||
to do this sort of thing symbolically. This is part of what is meant by
|
||||
a “categorical” language.)
|
||||
::
|
||||
|
||||
Cleanup
|
||||
b sqr 4 a c * * - sqrt
|
||||
|
||||
``/2a``
|
||||
~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
-b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a roll< pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a -b pop
|
||||
-b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a
|
||||
a 2 * /
|
||||
|
||||
Derive a definition.
|
||||
--------------------
|
||||
``±``
|
||||
~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2 roll< pop
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('3 1 1 quadratic')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-0.3819660112501051 -2.618033988749895
|
||||
|
||||
|
||||
Simplify
|
||||
--------
|
||||
|
||||
We can define a ``pm`` plus-or-minus function:
|
||||
There is a function ``pm`` that accepts two values on the stack and
|
||||
replaces them with their sum and difference.
|
||||
|
||||
::
|
||||
|
||||
pm == [+] [-] cleave popdd
|
||||
|
||||
Then ``quadratic`` becomes:
|
||||
Putting Them Together
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
|
||||
We use ``app2`` to compute both roots by using a quoted program
|
||||
``[2a /]`` built with ``cons``.
|
||||
|
||||
Derive a definition.
|
||||
--------------------
|
||||
|
||||
Working backwards we use ``dip`` and ``dipd`` to extract the code from
|
||||
the variables:
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
|
||||
The three arguments are to the left, so we can "chop off" everything to
|
||||
the right and say it's the definition of the ``quadratic`` function:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2')
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
|
||||
|
||||
Let's try it out:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
|
|
@ -110,74 +98,61 @@ Then ``quadratic`` becomes:
|
|||
-0.3819660112501051 -2.618033988749895
|
||||
|
||||
|
||||
Define a "native" ``pm`` function.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The definition of ``pm`` above is pretty elegant, but the implementation
|
||||
takes a lot of steps relative to what it's accomplishing. Since we are
|
||||
likely to use ``pm`` more than once in the future, let's write a
|
||||
primitive in Python and add it to the dictionary. (This has been done
|
||||
already.)
|
||||
If you look at the Joy evaluation trace you can see that the first few
|
||||
lines are the ``dip`` and ``dipd`` combinators building the main program
|
||||
by incorporating the values on the stack. Then that program runs and you
|
||||
get the results. This is pretty typical of Joy code.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def pm(stack):
|
||||
a, (b, stack) = stack
|
||||
p, m, = b + a, b - a
|
||||
return m, (p, stack)
|
||||
|
||||
The resulting trace is short enough to fit on a page.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('3 1 1 quadratic')
|
||||
V('-5 1 4 quadratic')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 3 1 1 quadratic
|
||||
3 . 1 1 quadratic
|
||||
3 1 . 1 quadratic
|
||||
3 1 1 . quadratic
|
||||
3 1 1 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2
|
||||
3 1 1 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [truediv] cons app2
|
||||
3 1 1 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 1 1 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . [neg] dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 [neg] . dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
3 . neg 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 . 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 . dup mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 3 3 . mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 . 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . 1 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . 1 * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 1 . * * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 1 . * - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 9 4 . - sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 5 . sqrt pm 1 2 * [truediv] cons app2
|
||||
-3 2.23606797749979 . pm 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 . 1 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 . 2 * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 1 2 . * [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 . [truediv] cons app2
|
||||
-0.7639320225002102 -5.23606797749979 2 [truediv] . cons app2
|
||||
-0.7639320225002102 -5.23606797749979 [2 truediv] . app2
|
||||
[-0.7639320225002102] [2 truediv] . infra first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 . 2 truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.7639320225002102 2 . truediv [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [] swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [] . swaack first [-5.23606797749979] [2 truediv] infra first
|
||||
[-0.3819660112501051] . first [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 . [-5.23606797749979] [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] . [2 truediv] infra first
|
||||
-0.3819660112501051 [-5.23606797749979] [2 truediv] . infra first
|
||||
-5.23606797749979 . 2 truediv [-0.3819660112501051] swaack first
|
||||
-5.23606797749979 2 . truediv [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 . [-0.3819660112501051] swaack first
|
||||
-2.618033988749895 [-0.3819660112501051] . swaack first
|
||||
-0.3819660112501051 [-2.618033988749895] . first
|
||||
-0.3819660112501051 -2.618033988749895 .
|
||||
. -5 1 4 quadratic
|
||||
-5 . 1 4 quadratic
|
||||
-5 1 . 4 quadratic
|
||||
-5 1 4 . quadratic
|
||||
-5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2
|
||||
-5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 16 . - sqrt pm 1 2 * [/] cons app2
|
||||
5 9 . sqrt pm 1 2 * [/] cons app2
|
||||
5 3.0 . pm 1 2 * [/] cons app2
|
||||
8.0 2.0 . 1 2 * [/] cons app2
|
||||
8.0 2.0 1 . 2 * [/] cons app2
|
||||
8.0 2.0 1 2 . * [/] cons app2
|
||||
8.0 2.0 2 . [/] cons app2
|
||||
8.0 2.0 2 [/] . cons app2
|
||||
8.0 2.0 [2 /] . app2
|
||||
[8.0] [2 /] . infra first [2.0] [2 /] infra first
|
||||
8.0 . 2 / [] swaack first [2.0] [2 /] infra first
|
||||
8.0 2 . / [] swaack first [2.0] [2 /] infra first
|
||||
4.0 . [] swaack first [2.0] [2 /] infra first
|
||||
4.0 [] . swaack first [2.0] [2 /] infra first
|
||||
[4.0] . first [2.0] [2 /] infra first
|
||||
4.0 . [2.0] [2 /] infra first
|
||||
4.0 [2.0] . [2 /] infra first
|
||||
4.0 [2.0] [2 /] . infra first
|
||||
2.0 . 2 / [4.0] swaack first
|
||||
2.0 2 . / [4.0] swaack first
|
||||
1.0 . [4.0] swaack first
|
||||
1.0 [4.0] . swaack first
|
||||
4.0 [1.0] . first
|
||||
4.0 1.0 .
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,695 @@
|
|||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import D, DefinitionWrapper, J, V, define
|
||||
|
||||
Recursive Combinators
|
||||
=====================
|
||||
|
||||
This article describes the ``genrec`` combinator, how to use it, and
|
||||
several generic specializations.
|
||||
|
||||
::
|
||||
|
||||
[if] [then] [rec1] [rec2] genrec
|
||||
---------------------------------------------------------------------
|
||||
[if] [then] [rec1 [[if] [then] [rec1] [rec2] genrec] rec2] ifte
|
||||
|
||||
From "Recursion Theory and Joy" (j05cmp.html) by Manfred von Thun:
|
||||
|
||||
"The genrec combinator takes four program parameters in addition to
|
||||
whatever data parameters it needs. Fourth from the top is an
|
||||
if-part, followed by a then-part. If the if-part yields true, then
|
||||
the then-part is executed and the combinator terminates. The other
|
||||
two parameters are the rec1-part and the rec2-part. If the if-part
|
||||
yields false, the rec1-part is executed. Following that the four
|
||||
program parameters and the combinator are again pushed onto the
|
||||
stack bundled up in a quoted form. Then the rec2-part is executed,
|
||||
where it will find the bundled form. Typically it will then execute
|
||||
the bundled form, either with i or with app2, or some other
|
||||
combinator."
|
||||
|
||||
Designing Recursive Functions
|
||||
-----------------------------
|
||||
|
||||
The way to design one of these is to fix your base case and test and
|
||||
then treat ``R1`` and ``R2`` as an else-part "sandwiching" a quotation
|
||||
of the whole function.
|
||||
|
||||
For example, given a (general recursive) function ``F``:
|
||||
|
||||
::
|
||||
|
||||
F == [I] [T] [R1] [R2] genrec
|
||||
== [I] [T] [R1 [F] R2] ifte
|
||||
|
||||
If the ``[I]`` predicate is false you must derive ``R1`` and ``R2``
|
||||
from:
|
||||
|
||||
::
|
||||
|
||||
... R1 [F] R2
|
||||
|
||||
Set the stack arguments in front and figure out what ``R1`` and ``R2``
|
||||
have to do to apply the quoted ``[F]`` in the proper way.
|
||||
|
||||
Primitive Recursive Functions
|
||||
-----------------------------
|
||||
|
||||
Primitive recursive functions are those where ``R2 == i``.
|
||||
|
||||
::
|
||||
|
||||
P == [I] [T] [R] primrec
|
||||
== [I] [T] [R [P] i] ifte
|
||||
== [I] [T] [R P] ifte
|
||||
|
||||
`Hylomorphism <https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>`__
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
A
|
||||
`hylomorphism <https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>`__
|
||||
is a recursive function ``H :: A -> C`` that converts a value of type
|
||||
``A`` into a value of type ``C`` by means of:
|
||||
|
||||
- A generator ``G :: A -> (B, A)``
|
||||
- A combiner ``F :: (B, C) -> C``
|
||||
- A predicate ``P :: A -> Bool`` to detect the base case
|
||||
- A base case value ``c :: C``
|
||||
- Recursive calls (zero or more); it has a "call stack in the form of a
|
||||
cons list".
|
||||
|
||||
It may be helpful to see this function implemented in imperative Python
|
||||
code.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def hylomorphism(c, F, P, G):
|
||||
'''Return a hylomorphism function H.'''
|
||||
|
||||
def H(a):
|
||||
if P(a):
|
||||
result = c
|
||||
else:
|
||||
b, aa = G(a)
|
||||
result = F(b, H(aa)) # b is stored in the stack frame during recursive call to H().
|
||||
return result
|
||||
|
||||
return H
|
||||
|
||||
Cf. `"Bananas, Lenses, & Barbed
|
||||
Wire" <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
|
||||
Note that during evaluation of ``H()`` the intermediate ``b`` values are
|
||||
stored in the Python call stack. This is what is meant by "call stack in
|
||||
the form of a cons list".
|
||||
|
||||
Hylomorphism in Joy
|
||||
-------------------
|
||||
|
||||
We can define a combinator ``hylomorphism`` that will make a
|
||||
hylomorphism combinator ``H`` from constituent parts.
|
||||
|
||||
::
|
||||
|
||||
H == [P] c [G] [F] hylomorphism
|
||||
|
||||
The function ``H`` is recursive, so we start with ``ifte`` and set the
|
||||
else-part to some function ``J`` that will contain a quoted copy of
|
||||
``H``. (The then-part just discards the leftover ``a`` and replaces it
|
||||
with the base case value ``c``.)
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [J] ifte
|
||||
|
||||
The else-part ``J`` gets just the argument ``a`` on the stack.
|
||||
|
||||
::
|
||||
|
||||
a J
|
||||
a G The first thing to do is use the generator G
|
||||
aa b which produces b and a new aa
|
||||
aa b [H] dip we recur with H on the new aa
|
||||
aa H b F and run F on the result.
|
||||
|
||||
This gives us a definition for ``J``.
|
||||
|
||||
::
|
||||
|
||||
J == G [H] dip F
|
||||
|
||||
Plug it in and convert to genrec.
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [G [H] dip F] ifte
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
This is the form of a hylomorphism in Joy, which nicely illustrates that
|
||||
it is a simple specialization of the general recursion combinator.
|
||||
|
||||
::
|
||||
|
||||
H == [P] c [G] [F] hylomorphism == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Derivation of ``hylomorphism`` combinator
|
||||
-----------------------------------------
|
||||
|
||||
Now we just need to derive a definition that builds the ``genrec``
|
||||
arguments out of the pieces given to the ``hylomorphism`` combinator.
|
||||
|
||||
::
|
||||
|
||||
[P] c [G] [F] hylomorphism
|
||||
------------------------------------------
|
||||
[P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Working in reverse:
|
||||
|
||||
- Use ``swoncat`` twice to decouple ``[c]`` and ``[F]``.
|
||||
- Use ``unit`` to dequote ``c``.
|
||||
- Use ``dipd`` to untangle ``[unit [pop] swoncat]`` from the givens.
|
||||
|
||||
So:
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
[P] [c] [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c unit [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c [G] [F] [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
At this point all of the arguments (givens) to the hylomorphism are to
|
||||
the left so we have a definition for ``hylomorphism``:
|
||||
|
||||
::
|
||||
|
||||
hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
|
||||
|
||||
Example: Finding `Triangular Numbers <https://en.wikipedia.org/wiki/Triangular_number>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Let's write a function that, given a positive integer, returns the sum
|
||||
of all positive integers less than that one. (In this case the types
|
||||
``A``, ``B`` and ``C`` are all ``int``.)
|
||||
|
||||
To sum a range of integers from 0 to *n* - 1:
|
||||
|
||||
- ``[P]`` is ``[1 <=]``
|
||||
- ``c`` is ``0``
|
||||
- ``[G]`` is ``[-- dup]``
|
||||
- ``[F]`` is ``[+]``
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
|
||||
|
||||
Let's try it:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 triangular_number')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
10
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[0 1 2 3 4 5 6] [triangular_number] map')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 0 1 3 6 10 15]
|
||||
|
||||
|
||||
Four Specializations
|
||||
--------------------
|
||||
|
||||
There are at least four kinds of recursive combinator, depending on two
|
||||
choices. The first choice is whether the combiner function ``F`` should
|
||||
be evaluated during the recursion or pushed into the pending expression
|
||||
to be "collapsed" at the end. The second choice is whether the combiner
|
||||
needs to operate on the current value of the datastructure or the
|
||||
generator's output, in other words, whether ``F`` or ``G`` should run
|
||||
first in the recursive branch.
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G ] [dip F] genrec
|
||||
H2 == c swap [P] [pop] [G [F] dip ] [i] genrec
|
||||
H3 == [P] [pop c] [ [G] dupdip ] [dip F] genrec
|
||||
H4 == c swap [P] [pop] [ [F] dupdip G] [i] genrec
|
||||
|
||||
The working of the generator function ``G`` differs slightly for each.
|
||||
Consider the recursive branches:
|
||||
|
||||
::
|
||||
|
||||
... a G [H1] dip F w/ a G == a′ b
|
||||
|
||||
... c a G [F] dip H2 a G == b a′
|
||||
|
||||
... a [G] dupdip [H3] dip F a G == a′
|
||||
|
||||
... c a [F] dupdip G H4 a G == a′
|
||||
|
||||
The following four sections illustrate how these work, omitting the
|
||||
predicate evaluation.
|
||||
|
||||
``H1``
|
||||
~~~~~~
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Iterate n times.
|
||||
|
||||
::
|
||||
|
||||
... a G [H1] dip F
|
||||
... a′ b [H1] dip F
|
||||
... a′ H1 b F
|
||||
... a′ G [H1] dip F b F
|
||||
... a″ b′ [H1] dip F b F
|
||||
... a″ H1 b′ F b F
|
||||
... a″ G [H1] dip F b′ F b F
|
||||
... a‴ b″ [H1] dip F b′ F b F
|
||||
... a‴ H1 b″ F b′ F b F
|
||||
... a‴ pop c b″ F b′ F b F
|
||||
... c b″ F b′ F b F
|
||||
... d b′ F b F
|
||||
... d′ b F
|
||||
... d″
|
||||
|
||||
This form builds up a pending expression (continuation) that contains
|
||||
the intermediate results along with the pending combiner functions. When
|
||||
the base case is reached the last term is replaced by the identity value
|
||||
``c`` and the continuation "collapses" into the final result using the
|
||||
combiner ``F``.
|
||||
|
||||
``H2``
|
||||
~~~~~~
|
||||
|
||||
When you can start with the identity value ``c`` on the stack and the
|
||||
combiner ``F`` can operate as you go using the intermediate results
|
||||
immediately rather than queuing them up, use this form. An important
|
||||
difference is that the generator function must return its results in the
|
||||
reverse order.
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
... c a G [F] dip H2
|
||||
... c b a′ [F] dip H2
|
||||
... c b F a′ H2
|
||||
... d a′ H2
|
||||
... d a′ G [F] dip H2
|
||||
... d b′ a″ [F] dip H2
|
||||
... d b′ F a″ H2
|
||||
... d′ a″ H2
|
||||
... d′ a″ G [F] dip H2
|
||||
... d′ b″ a‴ [F] dip H2
|
||||
... d′ b″ F a‴ H2
|
||||
... d″ a‴ H2
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
``H3``
|
||||
~~~~~~
|
||||
|
||||
If you examine the traces above you'll see that the combiner ``F`` only
|
||||
gets to operate on the results of ``G``, it never "sees" the first value
|
||||
``a``. If the combiner and the generator both need to work on the
|
||||
current value then ``dup`` must be used, and the generator must produce
|
||||
one item instead of two (the b is instead the duplicate of a.)
|
||||
|
||||
::
|
||||
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
|
||||
... a [G] dupdip [H3] dip F
|
||||
... a G a [H3] dip F
|
||||
... a′ a [H3] dip F
|
||||
... a′ H3 a F
|
||||
... a′ [G] dupdip [H3] dip F a F
|
||||
... a′ G a′ [H3] dip F a F
|
||||
... a″ a′ [H3] dip F a F
|
||||
... a″ H3 a′ F a F
|
||||
... a″ [G] dupdip [H3] dip F a′ F a F
|
||||
... a″ G a″ [H3] dip F a′ F a F
|
||||
... a‴ a″ [H3] dip F a′ F a F
|
||||
... a‴ H3 a″ F a′ F a F
|
||||
... a‴ pop c a″ F a′ F a F
|
||||
... c a″ F a′ F a F
|
||||
... d a′ F a F
|
||||
... d′ a F
|
||||
... d″
|
||||
|
||||
``H4``
|
||||
~~~~~~
|
||||
|
||||
And, last but not least, if you can combine as you go, starting with
|
||||
``c``, and the combiner ``F`` needs to work on the current item, this is
|
||||
the form:
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
... c a [F] dupdip G H4
|
||||
... c a F a G H4
|
||||
... d a G H4
|
||||
... d a′ H4
|
||||
... d a′ [F] dupdip G H4
|
||||
... d a′ F a′ G H4
|
||||
... d′ a′ G H4
|
||||
... d′ a″ H4
|
||||
... d′ a″ [F] dupdip G H4
|
||||
... d′ a″ F a″ G H4
|
||||
... d″ a″ G H4
|
||||
... d″ a‴ H4
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
Anamorphism
|
||||
-----------
|
||||
|
||||
An anamorphism can be defined as a hylomorphism that uses ``[]`` for
|
||||
``c`` and ``swons`` for ``F``. An anamorphic function builds a list of
|
||||
values.
|
||||
|
||||
::
|
||||
|
||||
A == [P] [] [G] [swons] hylomorphism
|
||||
|
||||
``range`` et. al.
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
An example of an anamorphism is the ``range`` function which generates
|
||||
the list of integers from 0 to *n* - 1 given *n*.
|
||||
|
||||
Each of the above variations can be used to make four slightly different
|
||||
``range`` functions.
|
||||
|
||||
``range`` with ``H1``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
== [0 <=] [pop []] [-- dup] [dip swons] genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 range')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[4 3 2 1 0]
|
||||
|
||||
|
||||
``range`` with ``H2``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
== [] swap [0 <=] [pop] [-- dup [swons] dip] primrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 range_reverse')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 1 2 3 4]
|
||||
|
||||
|
||||
``range`` with ``H3``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
== [0 <=] [pop []] [[--] dupdip] [dip swons] genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 ranger')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[5 4 3 2 1]
|
||||
|
||||
|
||||
``range`` with ``H4``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G ] primrec
|
||||
== [] swap [0 <=] [pop] [[swons] dupdip --] primrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 ranger_reverse')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 2 3 4 5]
|
||||
|
||||
|
||||
Hopefully this illustrates the workings of the variations. For more
|
||||
insight you can run the cells using the ``V()`` function instead of the
|
||||
``J()`` function to get a trace of the Joy evaluation.
|
||||
|
||||
Catamorphism
|
||||
------------
|
||||
|
||||
A catamorphism can be defined as a hylomorphism that uses
|
||||
``[uncons swap]`` for ``[G]`` and ``[[] =]`` (or just ``[not]``) for the
|
||||
predicate ``[P]``. A catamorphic function tears down a list term-by-term
|
||||
and makes some new value.
|
||||
|
||||
::
|
||||
|
||||
C == [not] c [uncons swap] [F] hylomorphism
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('swuncons == uncons swap') # Awkward name.
|
||||
|
||||
An example of a catamorphism is the sum function.
|
||||
|
||||
::
|
||||
|
||||
sum == [not] 0 [swuncons] [+] hylomorphism
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('sum == [not] 0 [swuncons] [+] hylomorphism')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[5 4 3 2 1] sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
15
|
||||
|
||||
|
||||
The ``step`` combinator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``step`` combinator will usually be better to use than
|
||||
``catamorphism``.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[step] help')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
Run a quoted program on each item in a sequence.
|
||||
::
|
||||
|
||||
... [] [Q] . step
|
||||
-----------------------
|
||||
... .
|
||||
|
||||
|
||||
... [a] [Q] . step
|
||||
------------------------
|
||||
... a . Q
|
||||
|
||||
|
||||
... [a b c] [Q] . step
|
||||
----------------------------------------
|
||||
... a . Q [b c] [Q] step
|
||||
|
||||
The step combinator executes the quotation on each member of the list
|
||||
on top of the stack.
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('sum == 0 swap [+] step')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[5 4 3 2 1] sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
15
|
||||
|
||||
|
||||
Example: Factorial Function
|
||||
---------------------------
|
||||
|
||||
For the Factorial function:
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
With:
|
||||
|
||||
::
|
||||
|
||||
c == 1
|
||||
F == *
|
||||
G == --
|
||||
P == 1 <=
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 factorial')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
120
|
||||
|
||||
|
||||
Example: ``tails``
|
||||
------------------
|
||||
|
||||
An example of a paramorphism for lists given in the `"Bananas..."
|
||||
paper <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
is ``tails`` which returns the list of "tails" of a list.
|
||||
|
||||
::
|
||||
|
||||
[1 2 3] tails
|
||||
--------------------
|
||||
[[] [3] [2 3]]
|
||||
|
||||
We can build as we go, and we want ``F`` to run after ``G``, so we use
|
||||
pattern ``H2``:
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
We would use:
|
||||
|
||||
::
|
||||
|
||||
c == []
|
||||
F == swons
|
||||
G == rest dup
|
||||
P == not
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 2 3] tails')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[[] [3] [2 3]]
|
||||
|
||||
|
||||
Conclusion: Patterns of Recursion
|
||||
---------------------------------
|
||||
|
||||
Our story so far...
|
||||
|
||||
Hylo-, Ana-, Cata-
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
H == [P ] [pop c ] [G ] [dip F ] genrec
|
||||
A == [P ] [pop []] [G ] [dip swap cons] genrec
|
||||
C == [not] [pop c ] [uncons swap] [dip F ] genrec
|
||||
|
||||
Para-, ?-, ?-
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
P == c swap [P ] [pop] [[F ] dupdip G ] primrec
|
||||
? == [] swap [P ] [pop] [[swap cons] dupdip G ] primrec
|
||||
? == c swap [not] [pop] [[F ] dupdip uncons swap] primrec
|
||||
|
||||
Appendix: Fun with Symbols
|
||||
--------------------------
|
||||
|
||||
::
|
||||
|
||||
|[ (c, F), (G, P) ]| == (|c, F|) • [(G, P)]
|
||||
|
||||
`"Bananas, Lenses, & Barbed
|
||||
Wire" <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
|
||||
::
|
||||
|
||||
(|...|) [(...)] [<...>]
|
||||
|
||||
I think they are having slightly too much fun with the symbols. However,
|
||||
"Too much is always better than not enough."
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,13 +9,15 @@ These essays are adapted from Jupyter notebooks. I hope to have those hosted so
|
|||
:maxdepth: 2
|
||||
|
||||
Developing
|
||||
Quadratic
|
||||
Replacing
|
||||
Recursion_Combinators
|
||||
Ordered_Binary_Trees
|
||||
Treestep
|
||||
Generator_Programs
|
||||
Newton-Raphson
|
||||
Quadratic
|
||||
Zipper
|
||||
Types
|
||||
NoUpdates
|
||||
Categorical
|
||||
|
||||
|
|
|
|||
304
joy/library.py
304
joy/library.py
|
|
@ -25,12 +25,15 @@ function.
|
|||
'''
|
||||
from inspect import getdoc
|
||||
from functools import wraps
|
||||
from inspect import getmembers, isfunction
|
||||
import operator, math
|
||||
|
||||
from .parser import text_to_expression, Symbol
|
||||
from .utils.stack import list_to_stack, iter_stack, pick, concat
|
||||
from .utils.brutal_hackery import rename_code_object
|
||||
|
||||
from .utils import generated_library as genlib
|
||||
|
||||
|
||||
_dictionary = {}
|
||||
|
||||
|
|
@ -88,12 +91,8 @@ def add_aliases(D, A):
|
|||
|
||||
|
||||
definitions = ('''\
|
||||
second == rest first
|
||||
third == rest rest first
|
||||
of == swap at
|
||||
product == 1 swap [*] step
|
||||
swons == swap cons
|
||||
swoncat == swap concat
|
||||
flatten == [] swap [concat] step
|
||||
unit == [] cons
|
||||
quoted == [unit] dip
|
||||
|
|
@ -128,6 +127,10 @@ codireco == cons dip rest cons
|
|||
make_generator == [codireco] ccons
|
||||
ccons == cons cons
|
||||
'''
|
||||
##second == rest first
|
||||
##third == rest rest first
|
||||
##swons == swap cons
|
||||
##swoncat == swap concat
|
||||
|
||||
##Zipper
|
||||
##z-down == [] swap uncons swap
|
||||
|
|
@ -258,6 +261,11 @@ def _text_to_defs(text):
|
|||
#
|
||||
|
||||
|
||||
# Load the auto-generated primitives into the dictionary.
|
||||
for name, primitive in getmembers(genlib, isfunction):
|
||||
inscribe(SimpleFunctionWrapper(primitive))
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def parse(stack):
|
||||
|
|
@ -267,30 +275,30 @@ def parse(stack):
|
|||
return expression, stack
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def first(stack):
|
||||
'''
|
||||
::
|
||||
|
||||
first == uncons pop
|
||||
|
||||
'''
|
||||
((head, tail), stack) = stack
|
||||
return head, stack
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def first(stack):
|
||||
## '''
|
||||
## ::
|
||||
##
|
||||
## first == uncons pop
|
||||
##
|
||||
## '''
|
||||
## ((head, tail), stack) = stack
|
||||
## return head, stack
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def rest(stack):
|
||||
'''
|
||||
::
|
||||
|
||||
rest == uncons popd
|
||||
|
||||
'''
|
||||
((head, tail), stack) = stack
|
||||
return tail, stack
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def rest(stack):
|
||||
## '''
|
||||
## ::
|
||||
##
|
||||
## rest == uncons popd
|
||||
##
|
||||
## '''
|
||||
## ((head, tail), stack) = stack
|
||||
## return tail, stack
|
||||
|
||||
|
||||
@inscribe
|
||||
|
|
@ -479,28 +487,28 @@ def sort_(S):
|
|||
return list_to_stack(sorted(iter_stack(tos))), stack
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def cons(S):
|
||||
'''
|
||||
The cons operator expects a list on top of the stack and the potential
|
||||
member below. The effect is to add the potential member into the
|
||||
aggregate.
|
||||
'''
|
||||
(tos, (second, stack)) = S
|
||||
return (second, tos), stack
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def cons(S):
|
||||
## '''
|
||||
## The cons operator expects a list on top of the stack and the potential
|
||||
## member below. The effect is to add the potential member into the
|
||||
## aggregate.
|
||||
## '''
|
||||
## (tos, (second, stack)) = S
|
||||
## return (second, tos), stack
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def uncons(S):
|
||||
'''
|
||||
Inverse of cons, removes an item from the top of the list on the stack
|
||||
and places it under the remaining list.
|
||||
'''
|
||||
(tos, stack) = S
|
||||
item, tos = tos
|
||||
return tos, (item, stack)
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def uncons(S):
|
||||
## '''
|
||||
## Inverse of cons, removes an item from the top of the list on the stack
|
||||
## and places it under the remaining list.
|
||||
## '''
|
||||
## (tos, stack) = S
|
||||
## item, tos = tos
|
||||
## return tos, (item, stack)
|
||||
|
||||
|
||||
@inscribe
|
||||
|
|
@ -516,52 +524,52 @@ def clear(stack):
|
|||
return ()
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def dup(S):
|
||||
'''Duplicate the top item on the stack.'''
|
||||
(tos, stack) = S
|
||||
return tos, (tos, stack)
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def dup(S):
|
||||
## '''Duplicate the top item on the stack.'''
|
||||
## (tos, stack) = S
|
||||
## return tos, (tos, stack)
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def over(S):
|
||||
'''
|
||||
Copy the second item down on the stack to the top of the stack.
|
||||
::
|
||||
|
||||
a b over
|
||||
--------------
|
||||
a b a
|
||||
|
||||
'''
|
||||
second = S[1][0]
|
||||
return second, S
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def over(S):
|
||||
## '''
|
||||
## Copy the second item down on the stack to the top of the stack.
|
||||
## ::
|
||||
##
|
||||
## a b over
|
||||
## --------------
|
||||
## a b a
|
||||
##
|
||||
## '''
|
||||
## second = S[1][0]
|
||||
## return second, S
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def tuck(S):
|
||||
'''
|
||||
Copy the item at TOS under the second item of the stack.
|
||||
::
|
||||
|
||||
a b tuck
|
||||
--------------
|
||||
b a b
|
||||
|
||||
'''
|
||||
(tos, (second, stack)) = S
|
||||
return tos, (second, (tos, stack))
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def tuck(S):
|
||||
## '''
|
||||
## Copy the item at TOS under the second item of the stack.
|
||||
## ::
|
||||
##
|
||||
## a b tuck
|
||||
## --------------
|
||||
## b a b
|
||||
##
|
||||
## '''
|
||||
## (tos, (second, stack)) = S
|
||||
## return tos, (second, (tos, stack))
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def swap(S):
|
||||
'''Swap the top two items on stack.'''
|
||||
(tos, (second, stack)) = S
|
||||
return second, (tos, stack)
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def swap(S):
|
||||
## '''Swap the top two items on stack.'''
|
||||
## (tos, (second, stack)) = S
|
||||
## return second, (tos, stack)
|
||||
|
||||
|
||||
@inscribe
|
||||
|
|
@ -572,14 +580,14 @@ def swaack(stack):
|
|||
return stack, old_stack
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def stack_(stack):
|
||||
'''
|
||||
The stack operator pushes onto the stack a list containing all the
|
||||
elements of the stack.
|
||||
'''
|
||||
return stack, stack
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def stack_(stack):
|
||||
## '''
|
||||
## The stack operator pushes onto the stack a list containing all the
|
||||
## elements of the stack.
|
||||
## '''
|
||||
## return stack, stack
|
||||
|
||||
|
||||
@inscribe
|
||||
|
|
@ -592,42 +600,42 @@ def unstack(stack):
|
|||
return stack[0]
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def pop(stack):
|
||||
'''Pop and discard the top item from the stack.'''
|
||||
return stack[1]
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def pop(stack):
|
||||
## '''Pop and discard the top item from the stack.'''
|
||||
## return stack[1]
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def popd(stack):
|
||||
'''Pop and discard the second item from the stack.'''
|
||||
(tos, (_, stack)) = stack
|
||||
return tos, stack
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def popd(stack):
|
||||
## '''Pop and discard the second item from the stack.'''
|
||||
## (tos, (_, stack)) = stack
|
||||
## return tos, stack
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def popdd(stack):
|
||||
'''Pop and discard the third item from the stack.'''
|
||||
(tos, (second, (_, stack))) = stack
|
||||
return tos, (second, stack)
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def popdd(stack):
|
||||
## '''Pop and discard the third item from the stack.'''
|
||||
## (tos, (second, (_, stack))) = stack
|
||||
## return tos, (second, stack)
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def popop(stack):
|
||||
'''Pop and discard the first and second items from the stack.'''
|
||||
return stack[1][1]
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def popop(stack):
|
||||
## '''Pop and discard the first and second items from the stack.'''
|
||||
## return stack[1][1]
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def dupd(S):
|
||||
'''Duplicate the second item on the stack.'''
|
||||
(tos, (second, stack)) = S
|
||||
return tos, (second, (second, stack))
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def dupd(S):
|
||||
## '''Duplicate the second item on the stack.'''
|
||||
## (tos, (second, stack)) = S
|
||||
## return tos, (second, (second, stack))
|
||||
|
||||
|
||||
@inscribe
|
||||
|
|
@ -760,34 +768,34 @@ def sqrt(a):
|
|||
return r
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def rollup(S):
|
||||
'''
|
||||
::
|
||||
|
||||
a b c
|
||||
-----------
|
||||
b c a
|
||||
|
||||
'''
|
||||
(a, (b, (c, stack))) = S
|
||||
return b, (c, (a, stack))
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def rollup(S):
|
||||
## '''
|
||||
## ::
|
||||
##
|
||||
## a b c
|
||||
## -----------
|
||||
## b c a
|
||||
##
|
||||
## '''
|
||||
## (a, (b, (c, stack))) = S
|
||||
## return b, (c, (a, stack))
|
||||
|
||||
|
||||
@inscribe
|
||||
@SimpleFunctionWrapper
|
||||
def rolldown(S):
|
||||
'''
|
||||
::
|
||||
|
||||
a b c
|
||||
-----------
|
||||
c a b
|
||||
|
||||
'''
|
||||
(a, (b, (c, stack))) = S
|
||||
return c, (a, (b, stack))
|
||||
##@inscribe
|
||||
##@SimpleFunctionWrapper
|
||||
##def rolldown(S):
|
||||
## '''
|
||||
## ::
|
||||
##
|
||||
## a b c
|
||||
## -----------
|
||||
## c a b
|
||||
##
|
||||
## '''
|
||||
## (a, (b, (c, stack))) = S
|
||||
## return c, (a, (b, stack))
|
||||
|
||||
|
||||
#def execute(S):
|
||||
|
|
|
|||
Loading…
Reference in New Issue