From: Simon Forman Date: Sat, 27 Nov 2021 17:04:25 +0000 (-0800) Subject: Recover the square spiral example code. X-Git-Url: http://git.osdn.net/view?p=joypy%2FThun.git;a=commitdiff_plain;h=1b193b19243a3aa23f74b6ecbcfd3f217bf66907 Recover the square spiral example code. I hve no idea how this isn't in VCS. I checked hg and git. Is it in an old branch that I deleted before merging or something? I have backups from which to restore, but it would be nice to know how I effed it up in the first place, eh? --- diff --git a/docs/Square_Spiral.html b/docs/Square_Spiral.html new file mode 100644 index 0000000..7a94974 --- /dev/null +++ b/docs/Square_Spiral.html @@ -0,0 +1,13739 @@ + + + + +Square_Spiral + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
In [1]:
+
+
+
from notebook_preamble import J, V, define
+
+ +
+
+
+ +
+
+
+
+

Square Spiral Example Joy Code

+
+
+
+
+
+
+

Here is the example of Joy code from the README file:

+ +
[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
+
+
+

It might seem unreadable but with a little familiarity it becomes just as +legible as any other notation. Some layout helps:

+ +
[   [[abs] ii <=]
+    [
+        [<>] [pop !-] ||
+    ] &&
+]
+[[    !-] [[++]] [[--]] ifte dip]
+[[pop !-]  [--]   [++]  ifte    ]
+ifte
+
+
+

This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral).

+ +
+
+
+
+
+
+

Original Form

It's adapted from the original code on StackOverflow:

+

If all you're trying to do is generate the first N points in the spiral +(without the original problem's constraint of masking to an N x M +region), the code becomes very simple:

+
+ +
void spiral(const int N)
+{
+    int x = 0;
+    int y = 0;
+    for(int i = 0; i < N; ++i)
+    {
+        cout << x << '\t' << y << '\n';
+        if(abs(x) <= abs(y) && (x != y || x >= 0))
+            x += ((y >= 0) ? 1 : -1);
+        else
+            y += ((x >= 0) ? -1 : 1);
+    }
+}
+ +
+
+
+
+
+
+

Translation to Joy

I'm going to make a function that take two ints (x and y) and +generates the next pair, we'll turn it into a generator later using the +x combinator.

+ +
+
+
+
+
+
+

First Boolean Predicate

We need a function that computes abs(x) <= abs(y), we can use ii to +apply abs to both values and then compare them +with <=:

+ +
[abs] ii <=
+
+
+

I've defined two short-circuiting Boolean combinators && and || that +each accept two quoted predicate programs, run the first, and +conditionally run the second only if required (to compute the final +Boolean value). They run their predicate arguments nullary.

+ +
+
+
+
+
+
In [2]:
+
+
+
define('&& [nullary] cons [nullary [0]] dip branch')
+define('|| [nullary] cons [nullary] dip [1] branch')
+
+ +
+
+
+ +
+
+
+
+

Given those, we can define x != y || x >= 0 as:

+ +
[<>] [pop 0 >=] ||
+
+
+

And (abs(x) <= abs(y) && (x != y || x >= 0)) as:

+ +
[[abs] ii <=] [[<>] [pop 0 >=] ||] &&
+
+
+

It's a little rough, but, as I say, with a little familiarity it becomes +legible.

+ +
+
+
+
+
+
+

The Increment / Decrement Branches

Turning to the branches of the main if statement:

+ +
x += ((y >= 0) ? 1 : -1);
+
+
+

Rewrite as a hybrid (pseudo-code) ifte expression:

+ +
[y >= 0] [x += 1] [X -= 1] ifte
+
+
+

Change each C phrase to Joy code:

+ +
[0 >=] [[++] dip] [[--] dip] ifte
+
+
+

Factor out the dip from each branch:

+ +
[0 >=] [[++]] [[--]] ifte dip
+
+
+

Similar logic applies to the other branch:

+ +
y += ((x >= 0) ? -1 : 1);
+
+[x >= 0] [y -= 1] [y += 1] ifte
+
+[pop 0 >=] [--] [++] ifte
+ +
+
+
+
+
+
+

"Not Negative"

+
+
+
+
+
+
In [3]:
+
+
+
define('!- 0 >=')
+
+ +
+
+
+ +
+
+
+
+

Putting the Pieces Together

We can assemble the three functions we just defined in quotes and give +them them to the ifte combinator. With some arrangement to show off +the symmetry of the two branches, we have:

+ +
[[[abs] ii <=] [[<>] [pop !-] ||] &&]
+[[    !-] [[++]] [[--]] ifte dip]
+[[pop !-]  [--]   [++]  ifte    ]
+ifte
+
+
+

As I was writing this up I realized that, since the && combinator +doesn't consume the stack (below its quoted args), I can unquote the +predicate, swap the branches, and use the branch combinator instead of +ifte:

+ +
[[abs] ii <=] [[<>] [pop !-] ||] &&
+[[pop !-]  [--]   [++]  ifte    ]
+[[    !-] [[++]] [[--]] ifte dip]
+branch
+ +
+
+
+
+
+
In [4]:
+
+
+
define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte')
+
+ +
+
+
+ +
+
+
+
+

Let's try it out:

+ +
+
+
+
+
+
In [5]:
+
+
+
J('0 0 spiral_next')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
1 0
+
+
+
+ +
+
+ +
+
+
+
In [6]:
+
+
+
J('1 0 spiral_next')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
1 -1
+
+
+
+ +
+
+ +
+
+
+
In [7]:
+
+
+
J('1 -1 spiral_next')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
0 -1
+
+
+
+ +
+
+ +
+
+
+
In [8]:
+
+
+
J('0 -1 spiral_next')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
-1 -1
+
+
+
+ +
+
+ +
+
+
+
+

Turning it into a Generator with x

It can be used with the x combinator to make a kind of generator for +spiral square coordinates.

+

We can use codireco to make a generator

+ +
codireco ::= cons dip rest cons
+
+
+

It will look like this:

+ +
[value [F] codireco]
+
+
+

Here's a trace of how it works:

+ +
           [0 [dup ++] codireco] . x
+           [0 [dup ++] codireco] . 0 [dup ++] codireco
+         [0 [dup ++] codireco] 0 . [dup ++] codireco
+[0 [dup ++] codireco] 0 [dup ++] . codireco
+[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
+[0 [dup ++] codireco] [0 dup ++] . dip rest cons
+                                 . 0 dup ++ [0 [dup ++] codireco] rest cons
+                               0 . dup ++ [0 [dup ++] codireco] rest cons
+                             0 0 . ++ [0 [dup ++] codireco] rest cons
+                             0 1 . [0 [dup ++] codireco] rest cons
+       0 1 [0 [dup ++] codireco] . rest cons
+         0 1 [[dup ++] codireco] . cons
+         0 [1 [dup ++] codireco] . 
+ +
+
+
+
+
+
+

But first we have to change the spiral_next function to work on a +quoted pair of integers, and leave a copy of the pair on the stack. +From:

+ +
   y x spiral_next
+---------------------
+        y' x'
+
+
+

to:

+ +
   [x y] [spiral_next] infra
+-------------------------------
+           [x' y']
+ +
+
+
+
+
+
In [9]:
+
+
+
J('[0 0] [spiral_next] infra')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
[0 1]
+
+
+
+ +
+
+ +
+
+
+
+

So our generator is:

+ +
[[x y] [dup [spiral_next] infra] codireco]
+
+
+

Or rather:

+ +
[[0 0] [dup [spiral_next] infra] codireco]
+
+
+

There is a function make_generator that will build the generator for us +out of the value and stepper function:

+ +
   [0 0] [dup [spiral_next] infra] make_generator
+----------------------------------------------------
+     [[0 0] [dup [spiral_next] infra] codireco]
+ +
+
+
+
+
+
+

Here it is in action:

+ +
+
+
+
+
+
In [10]:
+
+
+
J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
[0 0] [0 1] [-1 1] [-1 0]
+
+
+
+ +
+
+ +
+
+
+
+

Four x combinators, four pairs of coordinates.

+ +
+
+
+
+
+
+

Conclusion

So that's an example of Joy code. It's a straightforward translation of +the original. It's a little long for a single definition, you might +break it up like so:

+ +
     _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&
+
+     _spn_T ::= [    !-] [[++]] [[--]] ifte dip
+     _spn_E ::= [pop !-]  [--]   [++]  ifte
+
+spiral_next ::= _spn_P [_spn_E] [_spn_T] branch
+
+
+

This way it's easy to see that the function is a branch with two +quasi-symmetrical paths.

+

We then used this function to make a simple generator of coordinate +pairs, where the next pair in the series can be generated at any time by +using the x combinator on the generator (which is just a quoted +expression containing a copy of the current pair and the "stepper +function" to generate the next pair from that.)

+ +
+
+
+
+
+
In [11]:
+
+
+
define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&')
+define('_spn_T [!-] [[++]] [[--]] ifte dip')
+define('_spn_E [pop !-] [--] [++] ifte')
+define('spiral_next _spn_P [_spn_E] [_spn_T] branch')
+
+ +
+
+
+ +
+
+
+
In [12]:
+
+
+
V('23 18 spiral_next')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
                                                               . 23 18 spiral_next
+                                                            23 . 18 spiral_next
+                                                         23 18 . spiral_next
+                                                         23 18 . _spn_P [_spn_E] [_spn_T] branch
+                                                         23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
+                                           23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
+                        23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch
+                        23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
+              23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
+              23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch
+23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch
+                                           23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                           23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                   23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                   23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                         23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                 23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                   23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                         23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                   23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                   23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                             23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                   23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                            23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                            23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                         23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                   23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                         23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                         23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                         False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                 False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                 23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                                   23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                                               23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
+                  23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch
+                                                         23 18 . 0 [_spn_E] [_spn_T] branch
+                                                       23 18 0 . [_spn_E] [_spn_T] branch
+                                              23 18 0 [_spn_E] . [_spn_T] branch
+                                     23 18 0 [_spn_E] [_spn_T] . branch
+                                                         23 18 . _spn_E
+                                                         23 18 . [pop !-] [--] [++] ifte
+                                                23 18 [pop !-] . [--] [++] ifte
+                                           23 18 [pop !-] [--] . [++] ifte
+                                      23 18 [pop !-] [--] [++] . ifte
+                                      23 18 [pop !-] [--] [++] . [nullary not] dipd branch
+                        23 18 [pop !-] [--] [++] [nullary not] . dipd branch
+                                                23 18 [pop !-] . nullary not [--] [++] branch
+                                                23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch
+                                        23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch
+                                        23 18 [pop !-] [stack] . dip infra first not [--] [++] branch
+                                                         23 18 . stack [pop !-] infra first not [--] [++] branch
+                                                 23 18 [18 23] . [pop !-] infra first not [--] [++] branch
+                                        23 18 [18 23] [pop !-] . infra first not [--] [++] branch
+                                                         23 18 . pop !- [18 23] swaack first not [--] [++] branch
+                                                            23 . !- [18 23] swaack first not [--] [++] branch
+                                                            23 . 0 >= [18 23] swaack first not [--] [++] branch
+                                                          23 0 . >= [18 23] swaack first not [--] [++] branch
+                                                          True . [18 23] swaack first not [--] [++] branch
+                                                  True [18 23] . swaack first not [--] [++] branch
+                                                  23 18 [True] . first not [--] [++] branch
+                                                    23 18 True . not [--] [++] branch
+                                                   23 18 False . [--] [++] branch
+                                              23 18 False [--] . [++] branch
+                                         23 18 False [--] [++] . branch
+                                                         23 18 . --
+                                                         23 17 . 
+
+
+
+ +
+
+ +
+
+
+ + + + + + diff --git a/docs/Square_Spiral.ipynb b/docs/Square_Spiral.ipynb new file mode 100644 index 0000000..8dc4273 --- /dev/null +++ b/docs/Square_Spiral.ipynb @@ -0,0 +1,554 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from notebook_preamble import J, V, define" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Square Spiral Example Joy Code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Here is the example of Joy code from the `README` file:\n", + "\n", + " [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte\n", + "\n", + "It might seem unreadable but with a little familiarity it becomes just as\n", + "legible as any other notation. Some layout helps:\n", + "\n", + " [ [[abs] ii <=]\n", + " [\n", + " [<>] [pop !-] ||\n", + " ] &&\n", + " ]\n", + " [[ !-] [[++]] [[--]] ifte dip]\n", + " [[pop !-] [--] [++] ifte ]\n", + " ifte\n", + "\n", + "This function accepts two integers on the stack and increments or\n", + "decrements one of them such that the new pair of numbers is the next\n", + "coordinate pair in a square spiral (like the kind used to construct an\n", + "Ulam Spiral). \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Original Form\n", + "\n", + "It's adapted from [the original code on StackOverflow](https://stackoverflow.com/questions/398299/looping-in-a-spiral/31864777#31864777):\n", + "\n", + "\n", + "> If all you're trying to do is generate the first N points in the spiral\n", + "> (without the original problem's constraint of masking to an N x M\n", + "> region), the code becomes very simple:\n", + "\n", + " void spiral(const int N)\n", + " {\n", + " int x = 0;\n", + " int y = 0;\n", + " for(int i = 0; i < N; ++i)\n", + " {\n", + " cout << x << '\\t' << y << '\\n';\n", + " if(abs(x) <= abs(y) && (x != y || x >= 0))\n", + " x += ((y >= 0) ? 1 : -1);\n", + " else\n", + " y += ((x >= 0) ? -1 : 1);\n", + " }\n", + " }" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Translation to Joy\n", + "\n", + "I'm going to make a function that take two ints (`x` and `y`) and\n", + "generates the next pair, we'll turn it into a generator later using the\n", + "`x` combinator." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### First Boolean Predicate\n", + "\n", + "We need a function that computes `abs(x) <= abs(y)`, we can use `ii` to\n", + "apply `abs` to both values and then compare them\n", + "with `<=`:\n", + "\n", + " [abs] ii <=\n", + "\n", + "I've defined two short-circuiting Boolean combinators `&&` and `||` that\n", + "each accept two quoted predicate programs, run the first, and\n", + "conditionally run the second only if required (to compute the final\n", + "Boolean value). They run their predicate arguments `nullary`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "define('&& [nullary] cons [nullary [0]] dip branch')\n", + "define('|| [nullary] cons [nullary] dip [1] branch')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Given those, we can define `x != y || x >= 0` as:\n", + "\n", + " [<>] [pop 0 >=] ||\n", + "\n", + "And `(abs(x) <= abs(y) && (x != y || x >= 0))` as:\n", + "\n", + " [[abs] ii <=] [[<>] [pop 0 >=] ||] &&\n", + "\n", + "It's a little rough, but, as I say, with a little familiarity it becomes\n", + "legible." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The Increment / Decrement Branches\n", + "\n", + "Turning to the branches of the main `if` statement:\n", + "\n", + " x += ((y >= 0) ? 1 : -1);\n", + "\n", + "Rewrite as a hybrid (pseudo-code) `ifte` expression:\n", + "\n", + " [y >= 0] [x += 1] [X -= 1] ifte\n", + "\n", + "Change each C phrase to Joy code:\n", + "\n", + " [0 >=] [[++] dip] [[--] dip] ifte\n", + "\n", + "Factor out the dip from each branch:\n", + "\n", + " [0 >=] [[++]] [[--]] ifte dip\n", + "\n", + "Similar logic applies to the other branch:\n", + "\n", + " y += ((x >= 0) ? -1 : 1);\n", + "\n", + " [x >= 0] [y -= 1] [y += 1] ifte\n", + "\n", + " [pop 0 >=] [--] [++] ifte" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### \"Not Negative\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "define('!- 0 >=')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Putting the Pieces Together\n", + "\n", + "We can assemble the three functions we just defined in quotes and give\n", + "them them to the `ifte` combinator. With some arrangement to show off\n", + "the symmetry of the two branches, we have:\n", + "\n", + " [[[abs] ii <=] [[<>] [pop !-] ||] &&]\n", + " [[ !-] [[++]] [[--]] ifte dip]\n", + " [[pop !-] [--] [++] ifte ]\n", + " ifte\n", + "\n", + "As I was writing this up I realized that, since the `&&` combinator\n", + "doesn't consume the stack (below its quoted args), I can unquote the\n", + "predicate, swap the branches, and use the `branch` combinator instead of\n", + "`ifte`:\n", + "\n", + " [[abs] ii <=] [[<>] [pop !-] ||] &&\n", + " [[pop !-] [--] [++] ifte ]\n", + " [[ !-] [[++]] [[--]] ifte dip]\n", + " branch" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's try it out:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 0\n" + ] + } + ], + "source": [ + "J('0 0 spiral_next')" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 -1\n" + ] + } + ], + "source": [ + "J('1 0 spiral_next')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 -1\n" + ] + } + ], + "source": [ + "J('1 -1 spiral_next')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-1 -1\n" + ] + } + ], + "source": [ + "J('0 -1 spiral_next')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Turning it into a Generator with `x`\n", + "\n", + "It can be used with the x combinator to make a kind of generator for\n", + "spiral square coordinates.\n", + "\n", + "\n", + "We can use `codireco` to make a generator\n", + "\n", + " codireco ::= cons dip rest cons\n", + "\n", + "It will look like this:\n", + "\n", + " [value [F] codireco]\n", + "\n", + "Here's a trace of how it works:\n", + "\n", + " [0 [dup ++] codireco] . x\n", + " [0 [dup ++] codireco] . 0 [dup ++] codireco\n", + " [0 [dup ++] codireco] 0 . [dup ++] codireco\n", + " [0 [dup ++] codireco] 0 [dup ++] . codireco\n", + " [0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons\n", + " [0 [dup ++] codireco] [0 dup ++] . dip rest cons\n", + " . 0 dup ++ [0 [dup ++] codireco] rest cons\n", + " 0 . dup ++ [0 [dup ++] codireco] rest cons\n", + " 0 0 . ++ [0 [dup ++] codireco] rest cons\n", + " 0 1 . [0 [dup ++] codireco] rest cons\n", + " 0 1 [0 [dup ++] codireco] . rest cons\n", + " 0 1 [[dup ++] codireco] . cons\n", + " 0 [1 [dup ++] codireco] . " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But first we have to change the `spiral_next` function to work on a\n", + "quoted pair of integers, and leave a copy of the pair on the stack.\n", + "From:\n", + "\n", + " y x spiral_next\n", + " ---------------------\n", + " y' x'\n", + "\n", + "to:\n", + "\n", + " [x y] [spiral_next] infra\n", + " -------------------------------\n", + " [x' y']" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0 1]\n" + ] + } + ], + "source": [ + "J('[0 0] [spiral_next] infra')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So our generator is:\n", + "\n", + " [[x y] [dup [spiral_next] infra] codireco]\n", + "\n", + "Or rather:\n", + "\n", + " [[0 0] [dup [spiral_next] infra] codireco]\n", + "\n", + "There is a function `make_generator` that will build the generator for us\n", + "out of the value and stepper function:\n", + "\n", + " [0 0] [dup [spiral_next] infra] make_generator\n", + " ----------------------------------------------------\n", + " [[0 0] [dup [spiral_next] infra] codireco]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here it is in action:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0 0] [0 1] [-1 1] [-1 0]\n" + ] + } + ], + "source": [ + "J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Four `x` combinators, four pairs of coordinates." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusion\n", + "\n", + "So that's an example of Joy code. It's a straightforward translation of\n", + "the original. It's a little long for a single definition, you might\n", + "break it up like so:\n", + "\n", + " _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&\n", + "\n", + " _spn_T ::= [ !-] [[++]] [[--]] ifte dip\n", + " _spn_E ::= [pop !-] [--] [++] ifte\n", + "\n", + " spiral_next ::= _spn_P [_spn_E] [_spn_T] branch\n", + "\n", + "This way it's easy to see that the function is a branch with two\n", + "quasi-symmetrical paths.\n", + "\n", + "We then used this function to make a simple generator of coordinate\n", + "pairs, where the next pair in the series can be generated at any time by\n", + "using the `x` combinator on the generator (which is just a quoted\n", + "expression containing a copy of the current pair and the \"stepper\n", + "function\" to generate the next pair from that.)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&')\n", + "define('_spn_T [!-] [[++]] [[--]] ifte dip')\n", + "define('_spn_E [pop !-] [--] [++] ifte')\n", + "define('spiral_next _spn_P [_spn_E] [_spn_T] branch')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " . 23 18 spiral_next\n", + " 23 . 18 spiral_next\n", + " 23 18 . spiral_next\n", + " 23 18 . _spn_P [_spn_E] [_spn_T] branch\n", + " 23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch\n", + "23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch\n", + " 23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch\n", + " 23 18 . 0 [_spn_E] [_spn_T] branch\n", + " 23 18 0 . [_spn_E] [_spn_T] branch\n", + " 23 18 0 [_spn_E] . [_spn_T] branch\n", + " 23 18 0 [_spn_E] [_spn_T] . branch\n", + " 23 18 . _spn_E\n", + " 23 18 . [pop !-] [--] [++] ifte\n", + " 23 18 [pop !-] . [--] [++] ifte\n", + " 23 18 [pop !-] [--] . [++] ifte\n", + " 23 18 [pop !-] [--] [++] . ifte\n", + " 23 18 [pop !-] [--] [++] . [nullary not] dipd branch\n", + " 23 18 [pop !-] [--] [++] [nullary not] . dipd branch\n", + " 23 18 [pop !-] . nullary not [--] [++] branch\n", + " 23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch\n", + " 23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch\n", + " 23 18 [pop !-] [stack] . dip infra first not [--] [++] branch\n", + " 23 18 . stack [pop !-] infra first not [--] [++] branch\n", + " 23 18 [18 23] . [pop !-] infra first not [--] [++] branch\n", + " 23 18 [18 23] [pop !-] . infra first not [--] [++] branch\n", + " 23 18 . pop !- [18 23] swaack first not [--] [++] branch\n", + " 23 . !- [18 23] swaack first not [--] [++] branch\n", + " 23 . 0 >= [18 23] swaack first not [--] [++] branch\n", + " 23 0 . >= [18 23] swaack first not [--] [++] branch\n", + " True . [18 23] swaack first not [--] [++] branch\n", + " True [18 23] . swaack first not [--] [++] branch\n", + " 23 18 [True] . first not [--] [++] branch\n", + " 23 18 True . not [--] [++] branch\n", + " 23 18 False . [--] [++] branch\n", + " 23 18 False [--] . [++] branch\n", + " 23 18 False [--] [++] . branch\n", + " 23 18 . --\n", + " 23 17 . \n" + ] + } + ], + "source": [ + "V('23 18 spiral_next')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/Square_Spiral.md b/docs/Square_Spiral.md new file mode 100644 index 0000000..a217605 --- /dev/null +++ b/docs/Square_Spiral.md @@ -0,0 +1,363 @@ +```python +from notebook_preamble import J, V, define +``` + +# Square Spiral Example Joy Code + + +Here is the example of Joy code from the `README` file: + + [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte + +It might seem unreadable but with a little familiarity it becomes just as +legible as any other notation. Some layout helps: + + [ [[abs] ii <=] + [ + [<>] [pop !-] || + ] && + ] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral). + + + +## Original Form + +It's adapted from [the original code on StackOverflow](https://stackoverflow.com/questions/398299/looping-in-a-spiral/31864777#31864777): + + +> If all you're trying to do is generate the first N points in the spiral +> (without the original problem's constraint of masking to an N x M +> region), the code becomes very simple: + + void spiral(const int N) + { + int x = 0; + int y = 0; + for(int i = 0; i < N; ++i) + { + cout << x << '\t' << y << '\n'; + if(abs(x) <= abs(y) && (x != y || x >= 0)) + x += ((y >= 0) ? 1 : -1); + else + y += ((x >= 0) ? -1 : 1); + } + } + +## Translation to Joy + +I'm going to make a function that take two ints (`x` and `y`) and +generates the next pair, we'll turn it into a generator later using the +`x` combinator. + +### First Boolean Predicate + +We need a function that computes `abs(x) <= abs(y)`, we can use `ii` to +apply `abs` to both values and then compare them +with `<=`: + + [abs] ii <= + +I've defined two short-circuiting Boolean combinators `&&` and `||` that +each accept two quoted predicate programs, run the first, and +conditionally run the second only if required (to compute the final +Boolean value). They run their predicate arguments `nullary`. + + +```python +define('&& [nullary] cons [nullary [0]] dip branch') +define('|| [nullary] cons [nullary] dip [1] branch') +``` + +Given those, we can define `x != y || x >= 0` as: + + [<>] [pop 0 >=] || + +And `(abs(x) <= abs(y) && (x != y || x >= 0))` as: + + [[abs] ii <=] [[<>] [pop 0 >=] ||] && + +It's a little rough, but, as I say, with a little familiarity it becomes +legible. + +### The Increment / Decrement Branches + +Turning to the branches of the main `if` statement: + + x += ((y >= 0) ? 1 : -1); + +Rewrite as a hybrid (pseudo-code) `ifte` expression: + + [y >= 0] [x += 1] [X -= 1] ifte + +Change each C phrase to Joy code: + + [0 >=] [[++] dip] [[--] dip] ifte + +Factor out the dip from each branch: + + [0 >=] [[++]] [[--]] ifte dip + +Similar logic applies to the other branch: + + y += ((x >= 0) ? -1 : 1); + + [x >= 0] [y -= 1] [y += 1] ifte + + [pop 0 >=] [--] [++] ifte + +### "Not Negative" + + +```python +define('!- 0 >=') +``` + +## Putting the Pieces Together + +We can assemble the three functions we just defined in quotes and give +them them to the `ifte` combinator. With some arrangement to show off +the symmetry of the two branches, we have: + + [[[abs] ii <=] [[<>] [pop !-] ||] &&] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +As I was writing this up I realized that, since the `&&` combinator +doesn't consume the stack (below its quoted args), I can unquote the +predicate, swap the branches, and use the `branch` combinator instead of +`ifte`: + + [[abs] ii <=] [[<>] [pop !-] ||] && + [[pop !-] [--] [++] ifte ] + [[ !-] [[++]] [[--]] ifte dip] + branch + + +```python +define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte') +``` + +Let's try it out: + + +```python +J('0 0 spiral_next') +``` + + 1 0 + + + +```python +J('1 0 spiral_next') +``` + + 1 -1 + + + +```python +J('1 -1 spiral_next') +``` + + 0 -1 + + + +```python +J('0 -1 spiral_next') +``` + + -1 -1 + + +## Turning it into a Generator with `x` + +It can be used with the x combinator to make a kind of generator for +spiral square coordinates. + + +We can use `codireco` to make a generator + + codireco ::= cons dip rest cons + +It will look like this: + + [value [F] codireco] + +Here's a trace of how it works: + + [0 [dup ++] codireco] . x + [0 [dup ++] codireco] . 0 [dup ++] codireco + [0 [dup ++] codireco] 0 . [dup ++] codireco + [0 [dup ++] codireco] 0 [dup ++] . codireco + [0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons + [0 [dup ++] codireco] [0 dup ++] . dip rest cons + . 0 dup ++ [0 [dup ++] codireco] rest cons + 0 . dup ++ [0 [dup ++] codireco] rest cons + 0 0 . ++ [0 [dup ++] codireco] rest cons + 0 1 . [0 [dup ++] codireco] rest cons + 0 1 [0 [dup ++] codireco] . rest cons + 0 1 [[dup ++] codireco] . cons + 0 [1 [dup ++] codireco] . + +But first we have to change the `spiral_next` function to work on a +quoted pair of integers, and leave a copy of the pair on the stack. +From: + + y x spiral_next + --------------------- + y' x' + +to: + + [x y] [spiral_next] infra + ------------------------------- + [x' y'] + + +```python +J('[0 0] [spiral_next] infra') +``` + + [0 1] + + +So our generator is: + + [[x y] [dup [spiral_next] infra] codireco] + +Or rather: + + [[0 0] [dup [spiral_next] infra] codireco] + +There is a function `make_generator` that will build the generator for us +out of the value and stepper function: + + [0 0] [dup [spiral_next] infra] make_generator + ---------------------------------------------------- + [[0 0] [dup [spiral_next] infra] codireco] + +Here it is in action: + + +```python +J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop') +``` + + [0 0] [0 1] [-1 1] [-1 0] + + +Four `x` combinators, four pairs of coordinates. + +## Conclusion + +So that's an example of Joy code. It's a straightforward translation of +the original. It's a little long for a single definition, you might +break it up like so: + + _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] && + + _spn_T ::= [ !-] [[++]] [[--]] ifte dip + _spn_E ::= [pop !-] [--] [++] ifte + + spiral_next ::= _spn_P [_spn_E] [_spn_T] branch + +This way it's easy to see that the function is a branch with two +quasi-symmetrical paths. + +We then used this function to make a simple generator of coordinate +pairs, where the next pair in the series can be generated at any time by +using the `x` combinator on the generator (which is just a quoted +expression containing a copy of the current pair and the "stepper +function" to generate the next pair from that.) + + +```python +define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&') +define('_spn_T [!-] [[++]] [[--]] ifte dip') +define('_spn_E [pop !-] [--] [++] ifte') +define('spiral_next _spn_P [_spn_E] [_spn_T] branch') +``` + + +```python +V('23 18 spiral_next') +``` + + . 23 18 spiral_next + 23 . 18 spiral_next + 23 18 . spiral_next + 23 18 . _spn_P [_spn_E] [_spn_T] branch + 23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch + 23 18 . 0 [_spn_E] [_spn_T] branch + 23 18 0 . [_spn_E] [_spn_T] branch + 23 18 0 [_spn_E] . [_spn_T] branch + 23 18 0 [_spn_E] [_spn_T] . branch + 23 18 . _spn_E + 23 18 . [pop !-] [--] [++] ifte + 23 18 [pop !-] . [--] [++] ifte + 23 18 [pop !-] [--] . [++] ifte + 23 18 [pop !-] [--] [++] . ifte + 23 18 [pop !-] [--] [++] . [nullary not] dipd branch + 23 18 [pop !-] [--] [++] [nullary not] . dipd branch + 23 18 [pop !-] . nullary not [--] [++] branch + 23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dip infra first not [--] [++] branch + 23 18 . stack [pop !-] infra first not [--] [++] branch + 23 18 [18 23] . [pop !-] infra first not [--] [++] branch + 23 18 [18 23] [pop !-] . infra first not [--] [++] branch + 23 18 . pop !- [18 23] swaack first not [--] [++] branch + 23 . !- [18 23] swaack first not [--] [++] branch + 23 . 0 >= [18 23] swaack first not [--] [++] branch + 23 0 . >= [18 23] swaack first not [--] [++] branch + True . [18 23] swaack first not [--] [++] branch + True [18 23] . swaack first not [--] [++] branch + 23 18 [True] . first not [--] [++] branch + 23 18 True . not [--] [++] branch + 23 18 False . [--] [++] branch + 23 18 False [--] . [++] branch + 23 18 False [--] [++] . branch + 23 18 . -- + 23 17 . + diff --git a/docs/Square_Spiral.rst b/docs/Square_Spiral.rst new file mode 100644 index 0000000..7b5e67a --- /dev/null +++ b/docs/Square_Spiral.rst @@ -0,0 +1,421 @@ +.. code:: ipython3 + + from notebook_preamble import J, V, define + +Square Spiral Example Joy Code +============================== + +Here is the example of Joy code from the ``README`` file: + +:: + + [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte + +It might seem unreadable but with a little familiarity it becomes just +as legible as any other notation. Some layout helps: + +:: + + [ [[abs] ii <=] + [ + [<>] [pop !-] || + ] && + ] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral). + +Original Form +------------- + +It's adapted from `the original code on +StackOverflow `__: + + If all you're trying to do is generate the first N points in the + spiral (without the original problem's constraint of masking to an N + x M region), the code becomes very simple: + +:: + + void spiral(const int N) + { + int x = 0; + int y = 0; + for(int i = 0; i < N; ++i) + { + cout << x << '\t' << y << '\n'; + if(abs(x) <= abs(y) && (x != y || x >= 0)) + x += ((y >= 0) ? 1 : -1); + else + y += ((x >= 0) ? -1 : 1); + } + } + +Translation to Joy +------------------ + +I'm going to make a function that take two ints (``x`` and ``y``) and +generates the next pair, we'll turn it into a generator later using the +``x`` combinator. + +First Boolean Predicate +~~~~~~~~~~~~~~~~~~~~~~~ + +We need a function that computes ``abs(x) <= abs(y)``, we can use ``ii`` +to apply ``abs`` to both values and then compare them with ``<=``: + +:: + + [abs] ii <= + +I've defined two short-circuiting Boolean combinators ``&&`` and ``||`` +that each accept two quoted predicate programs, run the first, and +conditionally run the second only if required (to compute the final +Boolean value). They run their predicate arguments ``nullary``. + +.. code:: ipython3 + + define('&& [nullary] cons [nullary [0]] dip branch') + define('|| [nullary] cons [nullary] dip [1] branch') + +Given those, we can define ``x != y || x >= 0`` as: + +:: + + [<>] [pop 0 >=] || + +And ``(abs(x) <= abs(y) && (x != y || x >= 0))`` as: + +:: + + [[abs] ii <=] [[<>] [pop 0 >=] ||] && + +It's a little rough, but, as I say, with a little familiarity it becomes +legible. + +The Increment / Decrement Branches +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Turning to the branches of the main ``if`` statement: + +:: + + x += ((y >= 0) ? 1 : -1); + +Rewrite as a hybrid (pseudo-code) ``ifte`` expression: + +:: + + [y >= 0] [x += 1] [X -= 1] ifte + +Change each C phrase to Joy code: + +:: + + [0 >=] [[++] dip] [[--] dip] ifte + +Factor out the dip from each branch: + +:: + + [0 >=] [[++]] [[--]] ifte dip + +Similar logic applies to the other branch: + +:: + + y += ((x >= 0) ? -1 : 1); + + [x >= 0] [y -= 1] [y += 1] ifte + + [pop 0 >=] [--] [++] ifte + +"Not Negative" +~~~~~~~~~~~~~~ + +.. code:: ipython3 + + define('!- 0 >=') + +Putting the Pieces Together +--------------------------- + +We can assemble the three functions we just defined in quotes and give +them them to the ``ifte`` combinator. With some arrangement to show off +the symmetry of the two branches, we have: + +:: + + [[[abs] ii <=] [[<>] [pop !-] ||] &&] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +As I was writing this up I realized that, since the ``&&`` combinator +doesn't consume the stack (below its quoted args), I can unquote the +predicate, swap the branches, and use the ``branch`` combinator instead +of ``ifte``: + +:: + + [[abs] ii <=] [[<>] [pop !-] ||] && + [[pop !-] [--] [++] ifte ] + [[ !-] [[++]] [[--]] ifte dip] + branch + +.. code:: ipython3 + + define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte') + +Let's try it out: + +.. code:: ipython3 + + J('0 0 spiral_next') + + +.. parsed-literal:: + + 1 0 + + +.. code:: ipython3 + + J('1 0 spiral_next') + + +.. parsed-literal:: + + 1 -1 + + +.. code:: ipython3 + + J('1 -1 spiral_next') + + +.. parsed-literal:: + + 0 -1 + + +.. code:: ipython3 + + J('0 -1 spiral_next') + + +.. parsed-literal:: + + -1 -1 + + +Turning it into a Generator with ``x`` +-------------------------------------- + +It can be used with the x combinator to make a kind of generator for +spiral square coordinates. + +We can use ``codireco`` to make a generator + +:: + + codireco ::= cons dip rest cons + +It will look like this: + +:: + + [value [F] codireco] + +Here's a trace of how it works: + +:: + + [0 [dup ++] codireco] . x + [0 [dup ++] codireco] . 0 [dup ++] codireco + [0 [dup ++] codireco] 0 . [dup ++] codireco + [0 [dup ++] codireco] 0 [dup ++] . codireco + [0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons + [0 [dup ++] codireco] [0 dup ++] . dip rest cons + . 0 dup ++ [0 [dup ++] codireco] rest cons + 0 . dup ++ [0 [dup ++] codireco] rest cons + 0 0 . ++ [0 [dup ++] codireco] rest cons + 0 1 . [0 [dup ++] codireco] rest cons + 0 1 [0 [dup ++] codireco] . rest cons + 0 1 [[dup ++] codireco] . cons + 0 [1 [dup ++] codireco] . + +But first we have to change the ``spiral_next`` function to work on a +quoted pair of integers, and leave a copy of the pair on the stack. +From: + +:: + + y x spiral_next + --------------------- + y' x' + +to: + +:: + + [x y] [spiral_next] infra + ------------------------------- + [x' y'] + +.. code:: ipython3 + + J('[0 0] [spiral_next] infra') + + +.. parsed-literal:: + + [0 1] + + +So our generator is: + +:: + + [[x y] [dup [spiral_next] infra] codireco] + +Or rather: + +:: + + [[0 0] [dup [spiral_next] infra] codireco] + +There is a function ``make_generator`` that will build the generator for +us out of the value and stepper function: + +:: + + [0 0] [dup [spiral_next] infra] make_generator + ---------------------------------------------------- + [[0 0] [dup [spiral_next] infra] codireco] + +Here it is in action: + +.. code:: ipython3 + + J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop') + + +.. parsed-literal:: + + [0 0] [0 1] [-1 1] [-1 0] + + +Four ``x`` combinators, four pairs of coordinates. + +Conclusion +---------- + +So that's an example of Joy code. It's a straightforward translation of +the original. It's a little long for a single definition, you might +break it up like so: + +:: + + _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] && + + _spn_T ::= [ !-] [[++]] [[--]] ifte dip + _spn_E ::= [pop !-] [--] [++] ifte + + spiral_next ::= _spn_P [_spn_E] [_spn_T] branch + +This way it's easy to see that the function is a branch with two +quasi-symmetrical paths. + +We then used this function to make a simple generator of coordinate +pairs, where the next pair in the series can be generated at any time by +using the ``x`` combinator on the generator (which is just a quoted +expression containing a copy of the current pair and the "stepper +function" to generate the next pair from that.) + +.. code:: ipython3 + + define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&') + define('_spn_T [!-] [[++]] [[--]] ifte dip') + define('_spn_E [pop !-] [--] [++] ifte') + define('spiral_next _spn_P [_spn_E] [_spn_T] branch') + +.. code:: ipython3 + + V('23 18 spiral_next') + + +.. parsed-literal:: + + . 23 18 spiral_next + 23 . 18 spiral_next + 23 18 . spiral_next + 23 18 . _spn_P [_spn_E] [_spn_T] branch + 23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch + 23 18 . 0 [_spn_E] [_spn_T] branch + 23 18 0 . [_spn_E] [_spn_T] branch + 23 18 0 [_spn_E] . [_spn_T] branch + 23 18 0 [_spn_E] [_spn_T] . branch + 23 18 . _spn_E + 23 18 . [pop !-] [--] [++] ifte + 23 18 [pop !-] . [--] [++] ifte + 23 18 [pop !-] [--] . [++] ifte + 23 18 [pop !-] [--] [++] . ifte + 23 18 [pop !-] [--] [++] . [nullary not] dipd branch + 23 18 [pop !-] [--] [++] [nullary not] . dipd branch + 23 18 [pop !-] . nullary not [--] [++] branch + 23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dip infra first not [--] [++] branch + 23 18 . stack [pop !-] infra first not [--] [++] branch + 23 18 [18 23] . [pop !-] infra first not [--] [++] branch + 23 18 [18 23] [pop !-] . infra first not [--] [++] branch + 23 18 . pop !- [18 23] swaack first not [--] [++] branch + 23 . !- [18 23] swaack first not [--] [++] branch + 23 . 0 >= [18 23] swaack first not [--] [++] branch + 23 0 . >= [18 23] swaack first not [--] [++] branch + True . [18 23] swaack first not [--] [++] branch + True [18 23] . swaack first not [--] [++] branch + 23 18 [True] . first not [--] [++] branch + 23 18 True . not [--] [++] branch + 23 18 False . [--] [++] branch + 23 18 False [--] . [++] branch + 23 18 False [--] [++] . branch + 23 18 . -- + 23 17 . + diff --git a/docs/sphinx_docs/_build/doctrees/environment.pickle b/docs/sphinx_docs/_build/doctrees/environment.pickle index c2efa5d..1710eb5 100644 Binary files a/docs/sphinx_docs/_build/doctrees/environment.pickle and b/docs/sphinx_docs/_build/doctrees/environment.pickle differ diff --git a/docs/sphinx_docs/_build/doctrees/index.doctree b/docs/sphinx_docs/_build/doctrees/index.doctree index 35d5feb..2f8a002 100644 Binary files a/docs/sphinx_docs/_build/doctrees/index.doctree and b/docs/sphinx_docs/_build/doctrees/index.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Derivatives_of_Regular_Expressions.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Derivatives_of_Regular_Expressions.doctree index f834481..c5f9725 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Derivatives_of_Regular_Expressions.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Derivatives_of_Regular_Expressions.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Generator_Programs.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Generator_Programs.doctree index eac2cc4..ccb3948 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Generator_Programs.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Generator_Programs.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Newton-Raphson.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Newton-Raphson.doctree index 1367d10..4a86f59 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Newton-Raphson.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Newton-Raphson.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Ordered_Binary_Trees.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Ordered_Binary_Trees.doctree index 38d5c96..67405fe 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Ordered_Binary_Trees.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Ordered_Binary_Trees.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Quadratic.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Quadratic.doctree index 11a77fc..9506af3 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Quadratic.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Quadratic.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Recursion_Combinators.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Recursion_Combinators.doctree index 32d4dc1..fd0934b 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Recursion_Combinators.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Recursion_Combinators.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Replacing.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Replacing.doctree index 3bde7b5..2ad1055 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Replacing.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Replacing.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Square_Spiral.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Square_Spiral.doctree new file mode 100644 index 0000000..e80264a Binary files /dev/null and b/docs/sphinx_docs/_build/doctrees/notebooks/Square_Spiral.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Treestep.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Treestep.doctree index 62d36b7..91f5241 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Treestep.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Treestep.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/TypeChecking.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/TypeChecking.doctree index 646bf47..ad9a5c1 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/TypeChecking.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/TypeChecking.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Types.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Types.doctree index e144f9e..9ba07c8 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Types.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Types.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/Zipper.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/Zipper.doctree index e51d16c..22f043b 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/Zipper.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/Zipper.doctree differ diff --git a/docs/sphinx_docs/_build/doctrees/notebooks/index.doctree b/docs/sphinx_docs/_build/doctrees/notebooks/index.doctree index d8c2f71..4eb8e5f 100644 Binary files a/docs/sphinx_docs/_build/doctrees/notebooks/index.doctree and b/docs/sphinx_docs/_build/doctrees/notebooks/index.doctree differ diff --git a/docs/sphinx_docs/_build/html/_sources/index.rst.txt b/docs/sphinx_docs/_build/html/_sources/index.rst.txt index b29fc83..eddc007 100644 --- a/docs/sphinx_docs/_build/html/_sources/index.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/index.rst.txt @@ -34,6 +34,31 @@ itself. .. _Concatinative: https://en.wikipedia.org/wiki/Concatenative_programming_language +Example Code +-------------------------------------------------- + +Here is an example of Joy code:: + + [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte + +It might seem unreadable but with a little familiarity it becomes just as +legible as any other notation. Some layout helps:: + + [ [[abs] ii <=] + [ + [<>] [pop !-] || + ] && + ] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral). For more information see :doc:`notebooks/Square_Spiral` + + Quick Start -------------------------------------------------- diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Derivatives_of_Regular_Expressions.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Derivatives_of_Regular_Expressions.rst.txt index be09155..29dc9fb 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Derivatives_of_Regular_Expressions.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Derivatives_of_Regular_Expressions.rst.txt @@ -76,7 +76,7 @@ E.g.: Implementation -------------- -.. code:: python +.. code:: ipython2 from functools import partial as curry from itertools import product @@ -86,7 +86,7 @@ Implementation The empty set and the set of just the empty string. -.. code:: python +.. code:: ipython2 phi = frozenset() # ϕ y = frozenset({''}) # λ @@ -101,7 +101,7 @@ alphabet with two symbols (if you had to.) I chose the names ``O`` and ``l`` (uppercase “o” and lowercase “L”) to look like ``0`` and ``1`` (zero and one) respectively. -.. code:: python +.. code:: ipython2 syms = O, l = frozenset({'0'}), frozenset({'1'}) @@ -123,7 +123,7 @@ expression* is one of: Where ``R`` and ``S`` stand for *regular expressions*. -.. code:: python +.. code:: ipython2 AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split() # Tags are just strings. @@ -133,7 +133,7 @@ only, these datastructures are immutable. String Representation of RE Datastructures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def stringy(re): ''' @@ -175,11 +175,11 @@ Match anything. Often spelled “.” I = (0|1)* -.. code:: python +.. code:: ipython2 I = (KSTAR, (OR, O, l)) -.. code:: python +.. code:: ipython2 print stringy(I) @@ -201,14 +201,14 @@ The example expression from Brzozowski: Note that it contains one of everything. -.. code:: python +.. code:: ipython2 a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I)))) b = (CONS, I, (CONS, O, l)) c = (CONS, l, (KSTAR, l)) it = (AND, a, (NOT, (OR, b, c))) -.. code:: python +.. code:: ipython2 print stringy(it) @@ -223,7 +223,7 @@ Note that it contains one of everything. Let’s get that auxiliary predicate function ``δ`` out of the way. -.. code:: python +.. code:: ipython2 def nully(R): ''' @@ -263,7 +263,7 @@ This is the straightforward version with no “compaction”. It works fine, but does waaaay too much work because the expressions grow each derivation. -.. code:: python +.. code:: ipython2 def D(symbol): @@ -308,7 +308,7 @@ derivation. Compaction Rules ~~~~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def _compaction_rule(relation, one, zero, a, b): return ( @@ -320,7 +320,7 @@ Compaction Rules An elegant symmetry. -.. code:: python +.. code:: ipython2 # R ∧ I = I ∧ R = R # R ∧ ϕ = ϕ ∧ R = ϕ @@ -341,7 +341,7 @@ We can save re-processing by remembering results we have already computed. RE datastructures are immutable and the ``derv()`` functions are *pure* so this is fine. -.. code:: python +.. code:: ipython2 class Memo(object): @@ -365,7 +365,7 @@ With “Compaction” This version uses the rules above to perform compaction. It keeps the expressions from growing too large. -.. code:: python +.. code:: ipython2 def D_compaction(symbol): @@ -414,7 +414,7 @@ Let’s try it out… (FIXME: redo.) -.. code:: python +.. code:: ipython2 o, z = D_compaction('0'), D_compaction('1') REs = set() @@ -533,10 +533,10 @@ machine transition table. Says, “Three or more 1’s and not ending in 01 nor composed of all 1’s.” -.. figure:: omg.svg - :alt: State Machine Graph +.. figure:: attachment:omg.svg + :alt: omg.svg - State Machine Graph + omg.svg Start at ``a`` and follow the transition arrows according to their labels. Accepting states have a double outline. (Graphic generated with @@ -605,20 +605,20 @@ You can see the one-way nature of the ``g`` state and the ``hij`` “trap” in the way that the ``.111.`` on the left-hand side of the ``&`` disappears once it has been matched. -.. code:: python +.. code:: ipython2 from collections import defaultdict from pprint import pprint from string import ascii_lowercase -.. code:: python +.. code:: ipython2 d0, d1 = D_compaction('0'), D_compaction('1') ``explore()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def explore(re): @@ -645,7 +645,7 @@ disappears once it has been matched. return table, accepting -.. code:: python +.. code:: ipython2 table, accepting = explore(it) table @@ -678,7 +678,7 @@ disappears once it has been matched. -.. code:: python +.. code:: ipython2 accepting @@ -697,7 +697,7 @@ Generate Diagram Once we have the FSM table and the set of accepting states we can generate the diagram above. -.. code:: python +.. code:: ipython2 _template = '''\ digraph finite_state_machine { @@ -722,7 +722,7 @@ generate the diagram above. ) ) -.. code:: python +.. code:: ipython2 print make_graph(table, accepting) @@ -776,7 +776,7 @@ Trampoline Function Python has no GOTO statement but we can fake it with a “trampoline” function. -.. code:: python +.. code:: ipython2 def trampoline(input_, jump_from, accepting): I = iter(input_) @@ -793,7 +793,7 @@ Stream Functions Little helpers to process the iterator of our data (a “stream” of “1” and “0” characters, not bits.) -.. code:: python +.. code:: ipython2 getch = lambda I: int(next(I)) @@ -816,7 +816,7 @@ code. (You have to imagine that these are GOTO statements in C or branches in assembly and that the state names are branch destination labels.) -.. code:: python +.. code:: ipython2 a = lambda I: c if getch(I) else b b = lambda I: _0(I) or d @@ -833,12 +833,12 @@ Note that the implementations of ``h`` and ``g`` are identical ergo ``h = g`` and we could eliminate one in the code but ``h`` is an accepting state and ``g`` isn’t. -.. code:: python +.. code:: ipython2 def acceptable(input_): return trampoline(input_, a, {h, i}) -.. code:: python +.. code:: ipython2 for n in range(2**5): s = bin(n)[2:] diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Generator_Programs.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Generator_Programs.rst.txt index a59df18..55e1679 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Generator_Programs.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Generator_Programs.rst.txt @@ -3,7 +3,7 @@ Using ``x`` to Generate Values Cf. jp-reprod.html -.. code:: python +.. code:: ipython2 from notebook_preamble import J, V, define @@ -57,7 +57,7 @@ We can make a generator for the Natural numbers (0, 1, 2, …) by using Let’s try it: -.. code:: python +.. code:: ipython2 V('[0 swap [dup ++] dip rest cons] x') @@ -81,7 +81,7 @@ Let’s try it: After one application of ``x`` the quoted program contains ``1`` and ``0`` is below it on the stack. -.. code:: python +.. code:: ipython2 J('[0 swap [dup ++] dip rest cons] x x x x x pop') @@ -94,11 +94,11 @@ After one application of ``x`` the quoted program contains ``1`` and ``direco`` ---------- -.. code:: python +.. code:: ipython2 define('direco == dip rest cons') -.. code:: python +.. code:: ipython2 V('[0 swap [dup ++] direco] x') @@ -149,13 +149,13 @@ Reading from the bottom up: G == [direco] cons [swap] swap concat cons G == [direco] cons [swap] swoncat cons -.. code:: python +.. code:: ipython2 define('G == [direco] cons [swap] swoncat cons') Let’s try it out: -.. code:: python +.. code:: ipython2 J('0 [dup ++] G') @@ -165,7 +165,7 @@ Let’s try it out: [0 swap [dup ++] direco] -.. code:: python +.. code:: ipython2 J('0 [dup ++] G x x x pop') @@ -178,7 +178,7 @@ Let’s try it out: Powers of 2 ~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 J('1 [dup 1 <<] G x x x x x x x x x pop') @@ -194,7 +194,7 @@ Powers of 2 If we have one of these quoted programs we can drive it using ``times`` with the ``x`` combinator. -.. code:: python +.. code:: ipython2 J('23 [dup ++] G 5 [x] times') @@ -226,11 +226,11 @@ int: And pick them off by masking with 3 (binary 11) and then shifting the int right two bits. -.. code:: python +.. code:: ipython2 define('PE1.1 == dup [3 &] dip 2 >>') -.. code:: python +.. code:: ipython2 V('14811 PE1.1') @@ -252,7 +252,7 @@ int right two bits. If we plug ``14811`` and ``[PE1.1]`` into our generator form… -.. code:: python +.. code:: ipython2 J('14811 [PE1.1] G') @@ -264,7 +264,7 @@ If we plug ``14811`` and ``[PE1.1]`` into our generator form… …we get a generator that works for seven cycles before it reaches zero: -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1] direco] 7 [x] times') @@ -280,11 +280,11 @@ Reset at Zero We need a function that checks if the int has reached zero and resets it if so. -.. code:: python +.. code:: ipython2 define('PE1.1.check == dup [pop 14811] [] branch') -.. code:: python +.. code:: ipython2 J('14811 [PE1.1.check PE1.1] G') @@ -294,7 +294,7 @@ if so. [14811 swap [PE1.1.check PE1.1] direco] -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times') @@ -316,7 +316,7 @@ In the PE1 problem we are asked to sum all the multiples of three and five less than 1000. It’s worked out that we need to use all seven numbers sixty-six times and then four more. -.. code:: python +.. code:: ipython2 J('7 66 * 4 +') @@ -328,7 +328,7 @@ numbers sixty-six times and then four more. If we drive our generator 466 times and sum the stack we get 999. -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times') @@ -338,7 +338,7 @@ If we drive our generator 466 times and sum the stack we get 999. 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco] -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum') @@ -351,13 +351,13 @@ If we drive our generator 466 times and sum the stack we get 999. Project Euler Problem One ------------------------- -.. code:: python +.. code:: ipython2 define('PE1.2 == + dup [+] dip') Now we can add ``PE1.2`` to the quoted program given to ``G``. -.. code:: python +.. code:: ipython2 J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop') @@ -445,15 +445,15 @@ Putting it all together: F == + [popdd over] cons infra uncons fib_gen == [1 1 F] -.. code:: python +.. code:: ipython2 define('fib == + [popdd over] cons infra uncons') -.. code:: python +.. code:: ipython2 define('fib_gen == [1 1 fib]') -.. code:: python +.. code:: ipython2 J('fib_gen 10 [x] times') @@ -473,14 +473,14 @@ Now that we have a generator for the Fibonacci sequence, we need a function that adds a term in the sequence to a sum if it is even, and ``pop``\ s it otherwise. -.. code:: python +.. code:: ipython2 define('PE2.1 == dup 2 % [+] [pop] branch') And a predicate function that detects when the terms in the series “exceed four million”. -.. code:: python +.. code:: ipython2 define('>4M == 4000000 >') @@ -488,11 +488,11 @@ Now it’s straightforward to define ``PE2`` as a recursive function that generates terms in the Fibonacci sequence until they exceed four million and sums the even ones. -.. code:: python +.. code:: ipython2 define('PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec') -.. code:: python +.. code:: ipython2 J('PE2') @@ -535,7 +535,7 @@ So the Fibonacci sequence considered in terms of just parity would be: Every third term is even. -.. code:: python +.. code:: ipython2 J('[1 0 fib] x x x') # To start the sequence with 1 1 2 3 instead of 1 2 3. @@ -547,7 +547,7 @@ Every third term is even. Drive the generator three times and ``popop`` the two odd terms. -.. code:: python +.. code:: ipython2 J('[1 0 fib] x x x [popop] dipd') @@ -557,11 +557,11 @@ Drive the generator three times and ``popop`` the two odd terms. 2 [3 2 fib] -.. code:: python +.. code:: ipython2 define('PE2.2 == x x x [popop] dipd') -.. code:: python +.. code:: ipython2 J('[1 0 fib] 10 [PE2.2] times') @@ -574,7 +574,7 @@ Drive the generator three times and ``popop`` the two odd terms. Replace ``x`` with our new driver function ``PE2.2`` and start our ``fib`` generator at ``1 0``. -.. code:: python +.. code:: ipython2 J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec') @@ -593,11 +593,11 @@ modifications to the default ``x``? An Interesting Variation ------------------------ -.. code:: python +.. code:: ipython2 define('codireco == cons dip rest cons') -.. code:: python +.. code:: ipython2 V('[0 [dup ++] codireco] x') @@ -620,11 +620,11 @@ An Interesting Variation 0 [1 [dup ++] codireco] . -.. code:: python +.. code:: ipython2 define('G == [codireco] cons cons') -.. code:: python +.. code:: ipython2 J('230 [dup ++] G 5 [x] times pop') diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Newton-Raphson.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Newton-Raphson.rst.txt index b580502..cb3f759 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Newton-Raphson.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Newton-Raphson.rst.txt @@ -7,7 +7,7 @@ to write a function that can compute the square root of a number. Cf. `"Why Functional Programming Matters" by John Hughes `__ -.. code:: python +.. code:: ipython3 from notebook_preamble import J, V, define @@ -75,11 +75,11 @@ The generator can be written as: 1 [23 over / + 2 /] [dup] swoncat make_generator 1 [dup 23 over / + 2 /] make_generator -.. code:: python +.. code:: ipython3 define('gsra 1 swap [over / + 2 /] cons [dup] swoncat make_generator') -.. code:: python +.. code:: ipython3 J('23 gsra') @@ -92,7 +92,7 @@ The generator can be written as: Let's drive the generator a few time (with the ``x`` combinator) and square the approximation to see how well it works... -.. code:: python +.. code:: ipython3 J('23 gsra 6 [x popd] times first sqr') @@ -142,7 +142,7 @@ Predicate abs(a-b) ε <= (abs(a-b)<=ε) -.. code:: python +.. code:: ipython3 define('_within_P [first - abs] dip <=') @@ -156,7 +156,7 @@ Base-Case [b G] first b -.. code:: python +.. code:: ipython3 define('_within_B roll< popop first') @@ -184,7 +184,7 @@ Pretty straightforward: b [c G] ε within -.. code:: python +.. code:: ipython3 define('_within_R [popd x] dip') @@ -199,14 +199,14 @@ The recursive function we have defined so far needs a slight preamble: [a G] x ε ... a [b G] ε ... -.. code:: python +.. code:: ipython3 define('within x 0.000000001 [_within_P] [_within_B] [_within_R] tailrec') define('sqrt gsra within') Try it out... -.. code:: python +.. code:: ipython3 J('36 sqrt') @@ -216,7 +216,7 @@ Try it out... 6.0 -.. code:: python +.. code:: ipython3 J('23 sqrt') @@ -228,7 +228,7 @@ Try it out... Check it. -.. code:: python +.. code:: ipython3 4.795831523312719**2 @@ -241,7 +241,7 @@ Check it. -.. code:: python +.. code:: ipython3 from math import sqrt diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Ordered_Binary_Trees.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Ordered_Binary_Trees.rst.txt index a625ac3..569d665 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Ordered_Binary_Trees.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Ordered_Binary_Trees.rst.txt @@ -36,7 +36,7 @@ implementation under the hood. (Where does the “type” come from? It has a contingent existence predicated on the disciplined use of these functions on otherwise undistinguished Joy datastructures.) -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V, define, DefinitionWrapper @@ -87,11 +87,11 @@ Definition: Tree-new == swap [[] []] cons cons -.. code:: python +.. code:: ipython2 define('Tree-new == swap [[] []] cons cons') -.. code:: python +.. code:: ipython2 J('"v" "k" Tree-new') @@ -163,11 +163,11 @@ comparison operator: P < == pop roll> pop first < P == pop roll> pop first -.. code:: python +.. code:: ipython2 define('P == pop roll> pop first') -.. code:: python +.. code:: ipython2 J('["old_key" 23 [] []] 17 "new_key" ["..."] P') @@ -242,11 +242,11 @@ And so ``T`` is just: T == cons cons [dipdd] cons infra -.. code:: python +.. code:: ipython2 define('T == cons cons [dipdd] cons infra') -.. code:: python +.. code:: ipython2 J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] T') @@ -266,7 +266,7 @@ This is very very similar to the above: [key_n value_n left right] value key [Tree-add] E [key_n value_n left right] value key [Tree-add] [P <] [Te] [Ee] ifte -.. code:: python +.. code:: ipython2 define('E == [P <] [Te] [Ee] ifte') @@ -278,11 +278,11 @@ instead of the right, so the only difference is that it must use Te == cons cons [dipd] cons infra -.. code:: python +.. code:: ipython2 define('Te == cons cons [dipd] cons infra') -.. code:: python +.. code:: ipython2 J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] Te') @@ -320,11 +320,11 @@ Example: key new_value [ left right] cons cons [key new_value left right] -.. code:: python +.. code:: ipython2 define('Ee == pop swap roll< rest rest cons cons') -.. code:: python +.. code:: ipython2 J('["k" "old_value" "left" "right"] "new_value" "k" ["Tree-add"] Ee') @@ -355,14 +355,14 @@ Putting it all together: Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec -.. code:: python +.. code:: ipython2 define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [[P >] [T] [E] ifte] genrec') Examples ~~~~~~~~ -.. code:: python +.. code:: ipython2 J('[] 23 "b" Tree-add') # Initial @@ -372,7 +372,7 @@ Examples ['b' 23 [] []] -.. code:: python +.. code:: ipython2 J('["b" 23 [] []] 88 "c" Tree-add') # Greater than @@ -382,7 +382,7 @@ Examples ['b' 23 [] ['c' 88 [] []]] -.. code:: python +.. code:: ipython2 J('["b" 23 [] []] 88 "a" Tree-add') # Less than @@ -392,7 +392,7 @@ Examples ['b' 23 ['a' 88 [] []] []] -.. code:: python +.. code:: ipython2 J('["b" 23 [] []] 88 "b" Tree-add') # Equal to @@ -402,7 +402,7 @@ Examples ['b' 88 [] []] -.. code:: python +.. code:: ipython2 J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Series. @@ -412,7 +412,7 @@ Examples ['b' 23 ['a' 88 [] []] ['c' 44 [] []]] -.. code:: python +.. code:: ipython2 J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step') @@ -444,7 +444,7 @@ values: ------------------------- a < b L -.. code:: python +.. code:: ipython2 J("1 0 ['G'] ['E'] ['L'] cmp") @@ -454,7 +454,7 @@ values: 'G' -.. code:: python +.. code:: ipython2 J("1 1 ['G'] ['E'] ['L'] cmp") @@ -464,7 +464,7 @@ values: 'E' -.. code:: python +.. code:: ipython2 J("0 1 ['G'] ['E'] ['L'] cmp") @@ -514,7 +514,7 @@ Or just: P == over [popop popop first] nullary -.. code:: python +.. code:: ipython2 define('P == over [popop popop first] nullary') @@ -541,11 +541,11 @@ to understand: Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec -.. code:: python +.. code:: ipython2 define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec') -.. code:: python +.. code:: ipython2 J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Still works. @@ -685,14 +685,14 @@ Working backward: Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec -.. code:: python +.. code:: ipython2 define('Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec') Examples ~~~~~~~~ -.. code:: python +.. code:: ipython2 J('[] [foo] Tree-iter') # It doesn't matter what F is as it won't be used. @@ -702,7 +702,7 @@ Examples -.. code:: python +.. code:: ipython2 J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [first] Tree-iter") @@ -712,7 +712,7 @@ Examples 'b' 'a' 'c' -.. code:: python +.. code:: ipython2 J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [second] Tree-iter") @@ -731,7 +731,7 @@ to it will only occur once within it, and we can query it in `:math:`O(\log_2 N)` `__ time. -.. code:: python +.. code:: ipython2 J('[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step') @@ -741,11 +741,11 @@ time. [3 0 [2 0 [] []] [9 0 [5 0 [4 0 [] []] [8 0 [6 0 [] [7 0 [] []]] []]] []]] -.. code:: python +.. code:: ipython2 define('to_set == [] swap [0 swap Tree-add] step') -.. code:: python +.. code:: ipython2 J('[3 9 5 2 8 6 7 8 4] to_set') @@ -758,11 +758,11 @@ time. And with that we can write a little program ``unique`` to remove duplicate items from a list. -.. code:: python +.. code:: ipython2 define('unique == [to_set [first] Tree-iter] cons run') -.. code:: python +.. code:: ipython2 J('[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique') # Filter duplicate items. @@ -872,7 +872,7 @@ Let’s do a little semantic factoring: Now we can sort sequences. -.. code:: python +.. code:: ipython2 #define('Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec') @@ -892,7 +892,7 @@ Now we can sort sequences. -.. code:: python +.. code:: ipython2 J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order') @@ -1070,7 +1070,7 @@ So: Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec -.. code:: python +.. code:: ipython2 # I don't want to deal with name conflicts with the above so I'm inlining everything here. # The original Joy system has "hide" which is a meta-command which allows you to use named @@ -1088,7 +1088,7 @@ So: ] genrec ''') -.. code:: python +.. code:: ipython2 J('["gary" 23 [] []] "mike" [popd " not in tree" +] Tree-get') @@ -1098,7 +1098,7 @@ So: 'mike not in tree' -.. code:: python +.. code:: ipython2 J('["gary" 23 [] []] "gary" [popop "err"] Tree-get') @@ -1108,7 +1108,7 @@ So: 23 -.. code:: python +.. code:: ipython2 J(''' @@ -1124,7 +1124,7 @@ So: 2 -.. code:: python +.. code:: ipython2 J(''' @@ -1500,7 +1500,7 @@ Refactoring By the standards of the code I’ve written so far, this is a *huge* Joy program. -.. code:: python +.. code:: ipython2 DefinitionWrapper.add_definitions(''' first_two == uncons uncons pop @@ -1519,7 +1519,7 @@ program. Tree-Delete == [pop not] [pop] [R0] [R1] genrec ''', D) -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' Tree-Delete ") @@ -1529,7 +1529,7 @@ program. ['a' 23 [] ['b' 88 [] []]] -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' Tree-Delete ") @@ -1539,7 +1539,7 @@ program. ['a' 23 [] ['c' 44 [] []]] -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' Tree-Delete ") @@ -1549,7 +1549,7 @@ program. ['b' 88 [] ['c' 44 [] []]] -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' Tree-Delete ") @@ -1559,7 +1559,7 @@ program. ['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] -.. code:: python +.. code:: ipython2 J('[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step') @@ -1569,7 +1569,7 @@ program. [4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] -.. code:: python +.. code:: ipython2 J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete ") @@ -1579,7 +1579,7 @@ program. [4 0 [2 0 [1 0 [] []] []] [6 0 [5 0 [] []] [7 0 [] []]]] -.. code:: python +.. code:: ipython2 J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete ") diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Quadratic.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Quadratic.rst.txt index 5afb8e2..3262e84 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Quadratic.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Quadratic.rst.txt @@ -1,4 +1,4 @@ -.. code:: python +.. code:: ipython2 from notebook_preamble import J, V, define @@ -81,13 +81,13 @@ the variables: 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:: python +.. code:: ipython2 define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2') Let’s try it out: -.. code:: python +.. code:: ipython2 J('3 1 1 quadratic') @@ -102,7 +102,7 @@ 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:: python +.. code:: ipython2 V('-5 1 4 quadratic') diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Recursion_Combinators.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Recursion_Combinators.rst.txt index 2298cfd..9159882 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Recursion_Combinators.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Recursion_Combinators.rst.txt @@ -1,4 +1,4 @@ -.. code:: python +.. code:: ipython2 from notebook_preamble import D, DefinitionWrapper, J, V, define @@ -80,7 +80,7 @@ is a recursive function ``H :: A -> C`` that converts a value of type It may be helpful to see this function implemented in imperative Python code. -.. code:: python +.. code:: ipython2 def hylomorphism(c, F, P, G): '''Return a hylomorphism function H.''' @@ -185,7 +185,7 @@ the left so we have a definition for ``hylomorphism``: hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec -.. code:: python +.. code:: ipython2 define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec') @@ -203,13 +203,13 @@ To sum a range of integers from 0 to *n* - 1: - ``[G]`` is ``[-- dup]`` - ``[F]`` is ``[+]`` -.. code:: python +.. code:: ipython2 define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism') Let’s try it: -.. code:: python +.. code:: ipython2 J('5 triangular_number') @@ -219,7 +219,7 @@ Let’s try it: 10 -.. code:: python +.. code:: ipython2 J('[0 1 2 3 4 5 6] [triangular_number] map') @@ -391,10 +391,8 @@ 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*. +``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. @@ -407,11 +405,11 @@ Each of the above variations can be used to make four slightly different H1 == [P] [pop c] [G] [dip F] genrec == [0 <=] [pop []] [-- dup] [dip swons] genrec -.. code:: python +.. code:: ipython2 define('range == [0 <=] [] [-- dup] [swons] hylomorphism') -.. code:: python +.. code:: ipython2 J('5 range') @@ -429,11 +427,11 @@ Each of the above variations can be used to make four slightly different H2 == c swap [P] [pop] [G [F] dip] primrec == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec -.. code:: python +.. code:: ipython2 define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec') -.. code:: python +.. code:: ipython2 J('5 range_reverse') @@ -451,11 +449,11 @@ Each of the above variations can be used to make four slightly different H3 == [P] [pop c] [[G] dupdip] [dip F] genrec == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec -.. code:: python +.. code:: ipython2 define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec') -.. code:: python +.. code:: ipython2 J('5 ranger') @@ -473,11 +471,11 @@ Each of the above variations can be used to make four slightly different H4 == c swap [P] [pop] [[F] dupdip G ] primrec == [] swap [0 <=] [pop] [[swons] dupdip --] primrec -.. code:: python +.. code:: ipython2 define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec') -.. code:: python +.. code:: ipython2 J('5 ranger_reverse') @@ -503,7 +501,7 @@ and makes some new value. C == [not] c [uncons swap] [F] hylomorphism -.. code:: python +.. code:: ipython2 define('swuncons == uncons swap') # Awkward name. @@ -513,11 +511,11 @@ An example of a catamorphism is the sum function. sum == [not] 0 [swuncons] [+] hylomorphism -.. code:: python +.. code:: ipython2 define('sum == [not] 0 [swuncons] [+] hylomorphism') -.. code:: python +.. code:: ipython2 J('[5 4 3 2 1] sum') @@ -533,7 +531,7 @@ The ``step`` combinator The ``step`` combinator will usually be better to use than ``catamorphism``. -.. code:: python +.. code:: ipython2 J('[step] help') @@ -562,11 +560,11 @@ The ``step`` combinator will usually be better to use than -.. code:: python +.. code:: ipython2 define('sum == 0 swap [+] step') -.. code:: python +.. code:: ipython2 J('[5 4 3 2 1] sum') @@ -594,11 +592,11 @@ With: G == -- P == 1 <= -.. code:: python +.. code:: ipython2 define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec') -.. code:: python +.. code:: ipython2 J('5 factorial') @@ -637,11 +635,11 @@ We would use: G == rest dup P == not -.. code:: python +.. code:: ipython2 define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec') -.. code:: python +.. code:: ipython2 J('[1 2 3] tails') diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Replacing.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Replacing.rst.txt index 02ecb3b..0f90445 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Replacing.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Replacing.rst.txt @@ -9,14 +9,14 @@ dictionary. However, there’s no function that does that. Adding a new function to the dictionary is a meta-interpreter action, you have to do it in Python, not Joy. -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V A long trace ------------ -.. code:: python +.. code:: ipython2 V('[23 18] average') @@ -81,7 +81,7 @@ An efficient ``sum`` function is already in the library. But for ``size`` we can use a “compiled” version hand-written in Python to speed up evaluation and make the trace more readable. -.. code:: python +.. code:: ipython2 from joy.library import SimpleFunctionWrapper from joy.utils.stack import iter_stack @@ -99,7 +99,7 @@ up evaluation and make the trace more readable. Now we replace the old version in the dictionary with the new version, and re-evaluate the expression. -.. code:: python +.. code:: ipython2 D['size'] = size @@ -108,7 +108,7 @@ A shorter trace You can see that ``size`` now executes in a single step. -.. code:: python +.. code:: ipython2 V('[23 18] average') diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Square_Spiral.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Square_Spiral.rst.txt new file mode 100644 index 0000000..7b5e67a --- /dev/null +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Square_Spiral.rst.txt @@ -0,0 +1,421 @@ +.. code:: ipython3 + + from notebook_preamble import J, V, define + +Square Spiral Example Joy Code +============================== + +Here is the example of Joy code from the ``README`` file: + +:: + + [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte + +It might seem unreadable but with a little familiarity it becomes just +as legible as any other notation. Some layout helps: + +:: + + [ [[abs] ii <=] + [ + [<>] [pop !-] || + ] && + ] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral). + +Original Form +------------- + +It's adapted from `the original code on +StackOverflow `__: + + If all you're trying to do is generate the first N points in the + spiral (without the original problem's constraint of masking to an N + x M region), the code becomes very simple: + +:: + + void spiral(const int N) + { + int x = 0; + int y = 0; + for(int i = 0; i < N; ++i) + { + cout << x << '\t' << y << '\n'; + if(abs(x) <= abs(y) && (x != y || x >= 0)) + x += ((y >= 0) ? 1 : -1); + else + y += ((x >= 0) ? -1 : 1); + } + } + +Translation to Joy +------------------ + +I'm going to make a function that take two ints (``x`` and ``y``) and +generates the next pair, we'll turn it into a generator later using the +``x`` combinator. + +First Boolean Predicate +~~~~~~~~~~~~~~~~~~~~~~~ + +We need a function that computes ``abs(x) <= abs(y)``, we can use ``ii`` +to apply ``abs`` to both values and then compare them with ``<=``: + +:: + + [abs] ii <= + +I've defined two short-circuiting Boolean combinators ``&&`` and ``||`` +that each accept two quoted predicate programs, run the first, and +conditionally run the second only if required (to compute the final +Boolean value). They run their predicate arguments ``nullary``. + +.. code:: ipython3 + + define('&& [nullary] cons [nullary [0]] dip branch') + define('|| [nullary] cons [nullary] dip [1] branch') + +Given those, we can define ``x != y || x >= 0`` as: + +:: + + [<>] [pop 0 >=] || + +And ``(abs(x) <= abs(y) && (x != y || x >= 0))`` as: + +:: + + [[abs] ii <=] [[<>] [pop 0 >=] ||] && + +It's a little rough, but, as I say, with a little familiarity it becomes +legible. + +The Increment / Decrement Branches +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Turning to the branches of the main ``if`` statement: + +:: + + x += ((y >= 0) ? 1 : -1); + +Rewrite as a hybrid (pseudo-code) ``ifte`` expression: + +:: + + [y >= 0] [x += 1] [X -= 1] ifte + +Change each C phrase to Joy code: + +:: + + [0 >=] [[++] dip] [[--] dip] ifte + +Factor out the dip from each branch: + +:: + + [0 >=] [[++]] [[--]] ifte dip + +Similar logic applies to the other branch: + +:: + + y += ((x >= 0) ? -1 : 1); + + [x >= 0] [y -= 1] [y += 1] ifte + + [pop 0 >=] [--] [++] ifte + +"Not Negative" +~~~~~~~~~~~~~~ + +.. code:: ipython3 + + define('!- 0 >=') + +Putting the Pieces Together +--------------------------- + +We can assemble the three functions we just defined in quotes and give +them them to the ``ifte`` combinator. With some arrangement to show off +the symmetry of the two branches, we have: + +:: + + [[[abs] ii <=] [[<>] [pop !-] ||] &&] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +As I was writing this up I realized that, since the ``&&`` combinator +doesn't consume the stack (below its quoted args), I can unquote the +predicate, swap the branches, and use the ``branch`` combinator instead +of ``ifte``: + +:: + + [[abs] ii <=] [[<>] [pop !-] ||] && + [[pop !-] [--] [++] ifte ] + [[ !-] [[++]] [[--]] ifte dip] + branch + +.. code:: ipython3 + + define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte') + +Let's try it out: + +.. code:: ipython3 + + J('0 0 spiral_next') + + +.. parsed-literal:: + + 1 0 + + +.. code:: ipython3 + + J('1 0 spiral_next') + + +.. parsed-literal:: + + 1 -1 + + +.. code:: ipython3 + + J('1 -1 spiral_next') + + +.. parsed-literal:: + + 0 -1 + + +.. code:: ipython3 + + J('0 -1 spiral_next') + + +.. parsed-literal:: + + -1 -1 + + +Turning it into a Generator with ``x`` +-------------------------------------- + +It can be used with the x combinator to make a kind of generator for +spiral square coordinates. + +We can use ``codireco`` to make a generator + +:: + + codireco ::= cons dip rest cons + +It will look like this: + +:: + + [value [F] codireco] + +Here's a trace of how it works: + +:: + + [0 [dup ++] codireco] . x + [0 [dup ++] codireco] . 0 [dup ++] codireco + [0 [dup ++] codireco] 0 . [dup ++] codireco + [0 [dup ++] codireco] 0 [dup ++] . codireco + [0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons + [0 [dup ++] codireco] [0 dup ++] . dip rest cons + . 0 dup ++ [0 [dup ++] codireco] rest cons + 0 . dup ++ [0 [dup ++] codireco] rest cons + 0 0 . ++ [0 [dup ++] codireco] rest cons + 0 1 . [0 [dup ++] codireco] rest cons + 0 1 [0 [dup ++] codireco] . rest cons + 0 1 [[dup ++] codireco] . cons + 0 [1 [dup ++] codireco] . + +But first we have to change the ``spiral_next`` function to work on a +quoted pair of integers, and leave a copy of the pair on the stack. +From: + +:: + + y x spiral_next + --------------------- + y' x' + +to: + +:: + + [x y] [spiral_next] infra + ------------------------------- + [x' y'] + +.. code:: ipython3 + + J('[0 0] [spiral_next] infra') + + +.. parsed-literal:: + + [0 1] + + +So our generator is: + +:: + + [[x y] [dup [spiral_next] infra] codireco] + +Or rather: + +:: + + [[0 0] [dup [spiral_next] infra] codireco] + +There is a function ``make_generator`` that will build the generator for +us out of the value and stepper function: + +:: + + [0 0] [dup [spiral_next] infra] make_generator + ---------------------------------------------------- + [[0 0] [dup [spiral_next] infra] codireco] + +Here it is in action: + +.. code:: ipython3 + + J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop') + + +.. parsed-literal:: + + [0 0] [0 1] [-1 1] [-1 0] + + +Four ``x`` combinators, four pairs of coordinates. + +Conclusion +---------- + +So that's an example of Joy code. It's a straightforward translation of +the original. It's a little long for a single definition, you might +break it up like so: + +:: + + _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] && + + _spn_T ::= [ !-] [[++]] [[--]] ifte dip + _spn_E ::= [pop !-] [--] [++] ifte + + spiral_next ::= _spn_P [_spn_E] [_spn_T] branch + +This way it's easy to see that the function is a branch with two +quasi-symmetrical paths. + +We then used this function to make a simple generator of coordinate +pairs, where the next pair in the series can be generated at any time by +using the ``x`` combinator on the generator (which is just a quoted +expression containing a copy of the current pair and the "stepper +function" to generate the next pair from that.) + +.. code:: ipython3 + + define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&') + define('_spn_T [!-] [[++]] [[--]] ifte dip') + define('_spn_E [pop !-] [--] [++] ifte') + define('spiral_next _spn_P [_spn_E] [_spn_T] branch') + +.. code:: ipython3 + + V('23 18 spiral_next') + + +.. parsed-literal:: + + . 23 18 spiral_next + 23 . 18 spiral_next + 23 18 . spiral_next + 23 18 . _spn_P [_spn_E] [_spn_T] branch + 23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch + 23 18 . 0 [_spn_E] [_spn_T] branch + 23 18 0 . [_spn_E] [_spn_T] branch + 23 18 0 [_spn_E] . [_spn_T] branch + 23 18 0 [_spn_E] [_spn_T] . branch + 23 18 . _spn_E + 23 18 . [pop !-] [--] [++] ifte + 23 18 [pop !-] . [--] [++] ifte + 23 18 [pop !-] [--] . [++] ifte + 23 18 [pop !-] [--] [++] . ifte + 23 18 [pop !-] [--] [++] . [nullary not] dipd branch + 23 18 [pop !-] [--] [++] [nullary not] . dipd branch + 23 18 [pop !-] . nullary not [--] [++] branch + 23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dip infra first not [--] [++] branch + 23 18 . stack [pop !-] infra first not [--] [++] branch + 23 18 [18 23] . [pop !-] infra first not [--] [++] branch + 23 18 [18 23] [pop !-] . infra first not [--] [++] branch + 23 18 . pop !- [18 23] swaack first not [--] [++] branch + 23 . !- [18 23] swaack first not [--] [++] branch + 23 . 0 >= [18 23] swaack first not [--] [++] branch + 23 0 . >= [18 23] swaack first not [--] [++] branch + True . [18 23] swaack first not [--] [++] branch + True [18 23] . swaack first not [--] [++] branch + 23 18 [True] . first not [--] [++] branch + 23 18 True . not [--] [++] branch + 23 18 False . [--] [++] branch + 23 18 False [--] . [++] branch + 23 18 False [--] [++] . branch + 23 18 . -- + 23 17 . + diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Treestep.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Treestep.rst.txt index 7f273d8..6b9081f 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Treestep.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Treestep.rst.txt @@ -148,11 +148,11 @@ Working backwards: Define ``treestep`` ------------------- -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V, define, DefinitionWrapper -.. code:: python +.. code:: ipython2 DefinitionWrapper.add_definitions(''' @@ -173,7 +173,7 @@ all nodes in a tree with this function: sumtree == [pop 0] [] [sum +] treestep -.. code:: python +.. code:: ipython2 define('sumtree == [pop 0] [] [sum +] treestep') @@ -185,7 +185,7 @@ Running this function on an empty tree value gives zero: ------------------------------------ 0 -.. code:: python +.. code:: ipython2 J('[] sumtree') # Empty tree. @@ -205,7 +205,7 @@ Running it on a non-empty node: n m + n+m -.. code:: python +.. code:: ipython2 J('[23] sumtree') # No child trees. @@ -215,7 +215,7 @@ Running it on a non-empty node: 23 -.. code:: python +.. code:: ipython2 J('[23 []] sumtree') # Child tree, empty. @@ -225,7 +225,7 @@ Running it on a non-empty node: 23 -.. code:: python +.. code:: ipython2 J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees. @@ -235,7 +235,7 @@ Running it on a non-empty node: 32 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc... @@ -245,7 +245,7 @@ Running it on a non-empty node: 49 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling". @@ -255,7 +255,7 @@ Running it on a non-empty node: 49 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node. @@ -265,7 +265,7 @@ Running it on a non-empty node: [23 [23 [23] [23]] [23] [23 []]] -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep') @@ -275,7 +275,7 @@ Running it on a non-empty node: [1 [1 [1] [1]] [1] [1 []]] -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree') @@ -285,7 +285,7 @@ Running it on a non-empty node: 6 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function. @@ -295,7 +295,7 @@ Running it on a non-empty node: 6 -.. code:: python +.. code:: ipython2 J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function. @@ -339,7 +339,7 @@ Traversal This doesn’t quite work: -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep') @@ -369,7 +369,7 @@ So: [] [first] [flatten cons] treestep -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep') @@ -401,7 +401,7 @@ So: [] [i roll< swons concat] [first] treestep -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep') @@ -429,7 +429,7 @@ Plugging in our BTree structure: [key value] N [left right] [K] C -.. code:: python +.. code:: ipython2 J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind') @@ -444,7 +444,7 @@ Plugging in our BTree structure: Iteration through the nodes -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind') @@ -456,7 +456,7 @@ Iteration through the nodes Sum the nodes’ keys. -.. code:: python +.. code:: ipython2 J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind') @@ -468,7 +468,7 @@ Sum the nodes’ keys. Rebuild the tree using ``map`` (imitating ``treestep``.) -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind') @@ -574,7 +574,7 @@ Putting it together To me, that seems simpler than the ``genrec`` version. -.. code:: python +.. code:: ipython2 DefinitionWrapper.add_definitions(''' @@ -587,7 +587,7 @@ To me, that seems simpler than the ``genrec`` version. ''', D) -.. code:: python +.. code:: ipython2 J('''\ @@ -603,7 +603,7 @@ To me, that seems simpler than the ``genrec`` version. 15 -.. code:: python +.. code:: ipython2 J('''\ diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/TypeChecking.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/TypeChecking.rst.txt index 4e70a1a..cd85c67 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/TypeChecking.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/TypeChecking.rst.txt @@ -1,7 +1,7 @@ Type Checking ============= -.. code:: python +.. code:: ipython2 import logging, sys @@ -11,7 +11,7 @@ Type Checking level=logging.INFO, ) -.. code:: python +.. code:: ipython2 from joy.utils.types import ( doc_from_stack_effect, @@ -22,7 +22,7 @@ Type Checking JoyTypeError, ) -.. code:: python +.. code:: ipython2 D = FUNCTIONS.copy() del D['product'] @@ -31,7 +31,7 @@ Type Checking An Example ---------- -.. code:: python +.. code:: ipython2 fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0] @@ -46,7 +46,7 @@ An Example 40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘ -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(fi, fo) @@ -56,13 +56,13 @@ An Example ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) -.. code:: python +.. code:: ipython2 from joy.parser import text_to_expression from joy.utils.stack import stack_to_string -.. code:: python +.. code:: ipython2 e = text_to_expression('0 1 2 [3 4]') # reverse order print stack_to_string(e) @@ -73,7 +73,7 @@ An Example [3 4] 2 1 0 -.. code:: python +.. code:: ipython2 u = unify(e, fi)[0] u @@ -87,7 +87,7 @@ An Example -.. code:: python +.. code:: ipython2 g = reify(u, (fi, fo)) print doc_from_stack_effect(*g) @@ -101,11 +101,11 @@ An Example Unification Works “in Reverse” ------------------------------ -.. code:: python +.. code:: ipython2 e = text_to_expression('[2 3]') -.. code:: python +.. code:: ipython2 u = unify(e, fo)[0] # output side, not input side u @@ -119,7 +119,7 @@ Unification Works “in Reverse” -.. code:: python +.. code:: ipython2 g = reify(u, (fi, fo)) print doc_from_stack_effect(*g) @@ -133,7 +133,7 @@ Unification Works “in Reverse” Failing a Check --------------- -.. code:: python +.. code:: ipython2 fi, fo = infer(dup, mul)[0] @@ -146,7 +146,7 @@ Failing a Check 31 (i1 -- i2) ∘ -.. code:: python +.. code:: ipython2 e = text_to_expression('"two"') print stack_to_string(e) @@ -157,7 +157,7 @@ Failing a Check 'two' -.. code:: python +.. code:: ipython2 try: unify(e, fi) diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Types.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Types.rst.txt index 8ca737d..4c91600 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Types.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Types.rst.txt @@ -184,7 +184,7 @@ Compiling ``pop∘swap∘roll<`` The simplest way to “compile” this function would be something like: -.. code:: python +.. code:: ipython2 def poswrd(s, e, d): return rolldown(*swap(*pop(s, e, d))) @@ -200,7 +200,7 @@ Looking ahead for a moment, from the stack effect comment: We should be able to directly write out a Python function like: -.. code:: python +.. code:: ipython2 def poswrd(stack): (_, (a, (b, (c, stack)))) = stack @@ -393,7 +393,7 @@ And there you have it, the stack effect for From this stack effect comment it should be possible to construct the following Python code: -.. code:: python +.. code:: ipython2 def F(stack): (_, (d, (c, ((a, (b, S0)), stack)))) = stack @@ -408,7 +408,7 @@ Representing Stack Effect Comments in Python I’m going to use pairs of tuples of type descriptors, which will be integers or tuples of type descriptors: -.. code:: python +.. code:: ipython2 roll_dn = (1, 2, 3), (2, 3, 1) @@ -419,7 +419,7 @@ integers or tuples of type descriptors: ``compose()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def compose(f, g): @@ -465,7 +465,7 @@ integers or tuples of type descriptors: ``unify()`` ~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -483,7 +483,7 @@ integers or tuples of type descriptors: ``update()`` ~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def update(s, term): if not isinstance(term, tuple): @@ -493,7 +493,7 @@ integers or tuples of type descriptors: ``relabel()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def relabel(left, right): return left, _1000(right) @@ -517,7 +517,7 @@ integers or tuples of type descriptors: ``delabel()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def delabel(f): s = {u: i for i, u in enumerate(sorted(_unique(f)))} @@ -551,7 +551,7 @@ At last we put it all together in a function ``C()`` that accepts two stack effect comments and returns their composition (or raises and exception if they can’t be composed due to type conflicts.) -.. code:: python +.. code:: ipython2 def C(f, g): f, g = relabel(f, g) @@ -560,7 +560,7 @@ exception if they can’t be composed due to type conflicts.) Let’s try it out. -.. code:: python +.. code:: ipython2 C(pop, swap) @@ -573,7 +573,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 C(C(pop, swap), roll_dn) @@ -586,7 +586,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 C(swap, roll_dn) @@ -599,7 +599,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 C(pop, C(swap, roll_dn)) @@ -612,7 +612,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 poswrd = reduce(C, (pop, swap, roll_dn)) poswrd @@ -633,13 +633,13 @@ Here’s that trick to represent functions like ``rest`` and ``cons`` that manipulate stacks. We use a cons-list of tuples and give the tails their own numbers. Then everything above already works. -.. code:: python +.. code:: ipython2 rest = ((1, 2),), (2,) cons = (1, 2), ((1, 2),) -.. code:: python +.. code:: ipython2 C(poswrd, rest) @@ -671,7 +671,7 @@ The translation table, if you will, would be: 0: 0, } -.. code:: python +.. code:: ipython2 F = reduce(C, (pop, swap, roll_dn, rest, rest, cons, cons)) @@ -699,11 +699,11 @@ Dealing with ``cons`` and ``uncons`` However, if we try to compose e.g. ``cons`` and ``uncons`` it won’t work: -.. code:: python +.. code:: ipython2 uncons = ((1, 2),), (1, 2) -.. code:: python +.. code:: ipython2 try: C(cons, uncons) @@ -723,7 +723,7 @@ The problem is that the ``unify()`` function as written doesn’t handle the case when both terms are tuples. We just have to add a clause to deal with this recursively: -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -753,7 +753,7 @@ deal with this recursively: return s -.. code:: python +.. code:: ipython2 C(cons, uncons) @@ -771,7 +771,7 @@ Part III: Compiling Yin Functions Now consider the Python function we would like to derive: -.. code:: python +.. code:: ipython2 def F_python(stack): (_, (d, (c, ((a, (b, S0)), stack)))) = stack @@ -779,7 +779,7 @@ Now consider the Python function we would like to derive: And compare it to the input stack effect comment tuple we just computed: -.. code:: python +.. code:: ipython2 F[0] @@ -816,7 +816,7 @@ Eh? And the return tuple -.. code:: python +.. code:: ipython2 F[1] @@ -848,7 +848,7 @@ Python Identifiers We want to substitute Python identifiers for the integers. I’m going to repurpose ``joy.parser.Symbol`` class for this: -.. code:: python +.. code:: ipython2 from collections import defaultdict from joy.parser import Symbol @@ -874,7 +874,7 @@ effect comment tuples to reasonable text format. There are some details in how this code works that related to stuff later in the notebook, so you should skip it for now and read it later if you’re interested. -.. code:: python +.. code:: ipython2 def doc_from_stack_effect(inputs, outputs): return '(%s--%s)' % ( @@ -914,7 +914,7 @@ Now we can write a compiler function to emit Python source code. (The underscore suffix distiguishes it from the built-in ``compile()`` function.) -.. code:: python +.. code:: ipython2 def compile_(name, f, doc=None): if doc is None: @@ -932,7 +932,7 @@ function.) Here it is in action: -.. code:: python +.. code:: ipython2 source = compile_('F', F) @@ -949,7 +949,7 @@ Here it is in action: Compare: -.. code:: python +.. code:: ipython2 def F_python(stack): (_, (d, (c, ((a, (b, S0)), stack)))) = stack @@ -957,7 +957,7 @@ Compare: Next steps: -.. code:: python +.. code:: ipython2 L = {} @@ -976,16 +976,16 @@ Next steps: Let’s try it out: -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V from joy.library import SimpleFunctionWrapper -.. code:: python +.. code:: ipython2 D['F'] = SimpleFunctionWrapper(L['F']) -.. code:: python +.. code:: ipython2 J('[4 5 ...] 2 3 1 F') @@ -1012,7 +1012,7 @@ Compiling Library Functions We can use ``compile_()`` to generate many primitives in the library from their stack effect comments: -.. code:: python +.. code:: ipython2 def defs(): @@ -1036,7 +1036,7 @@ from their stack effect comments: return locals() -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(defs().items()): print @@ -1205,7 +1205,7 @@ Python class hierarchy of Joy types and use the ``issubclass()`` method to establish domain ordering, as well as other handy behaviour that will make it fairly easy to reuse most of the code above. -.. code:: python +.. code:: ipython2 class AnyJoyType(object): @@ -1251,14 +1251,14 @@ make it fairly easy to reuse most of the code above. Mess with it a little: -.. code:: python +.. code:: ipython2 from itertools import permutations “Any” types can be specialized to numbers and stacks, but not vice versa: -.. code:: python +.. code:: ipython2 for a, b in permutations((A[0], N[0], S[0]), 2): print a, '>=', b, '->', a >= b @@ -1278,7 +1278,7 @@ Our crude `Numerical Tower `__ of *numbers* > *floats* > *integers* works as well (but we’re not going to use it yet): -.. code:: python +.. code:: ipython2 for a, b in permutations((A[0], N[0], FloatJoyType(0), IntJoyType(0)), 2): print a, '>=', b, '->', a >= b @@ -1303,13 +1303,13 @@ Tower `__ of *numbers* > Typing ``sqr`` ~~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 dup = (A[1],), (A[1], A[1]) mul = (N[1], N[2]), (N[3],) -.. code:: python +.. code:: ipython2 dup @@ -1322,7 +1322,7 @@ Typing ``sqr`` -.. code:: python +.. code:: ipython2 mul @@ -1340,7 +1340,7 @@ Modifying the Inferencer Re-labeling still works fine: -.. code:: python +.. code:: ipython2 foo = relabel(dup, mul) @@ -1361,7 +1361,7 @@ Re-labeling still works fine: The ``delabel()`` function needs an overhaul. It now has to keep track of how many labels of each domain it has “seen”. -.. code:: python +.. code:: ipython2 from collections import Counter @@ -1383,7 +1383,7 @@ of how many labels of each domain it has “seen”. return tuple(delabel(inner, seen, c) for inner in f) -.. code:: python +.. code:: ipython2 delabel(foo) @@ -1399,7 +1399,7 @@ of how many labels of each domain it has “seen”. ``unify()`` version 3 ^^^^^^^^^^^^^^^^^^^^^ -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -1449,7 +1449,7 @@ of how many labels of each domain it has “seen”. Rewrite the stack effect comments: -.. code:: python +.. code:: ipython2 def defs(): @@ -1503,11 +1503,11 @@ Rewrite the stack effect comments: return locals() -.. code:: python +.. code:: ipython2 DEFS = defs() -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(DEFS.items()): print name, '=', doc_from_stack_effect(*stack_effect_comment) @@ -1543,14 +1543,14 @@ Rewrite the stack effect comments: uncons = ([a1 .1.] -- a1 [.1.]) -.. code:: python +.. code:: ipython2 globals().update(DEFS) Compose ``dup`` and ``mul`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code:: python +.. code:: ipython2 C(dup, mul) @@ -1565,7 +1565,7 @@ Compose ``dup`` and ``mul`` Revisit the ``F`` function, works fine. -.. code:: python +.. code:: ipython2 F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons)) F @@ -1579,7 +1579,7 @@ Revisit the ``F`` function, works fine. -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*F) @@ -1592,12 +1592,12 @@ Revisit the ``F`` function, works fine. Some otherwise inefficient functions are no longer to be feared. We can also get the effect of combinators in some limited cases. -.. code:: python +.. code:: ipython2 def neato(*funcs): print doc_from_stack_effect(*reduce(C, funcs)) -.. code:: python +.. code:: ipython2 # e.g. [swap] dip neato(rollup, swap, rolldown) @@ -1608,7 +1608,7 @@ also get the effect of combinators in some limited cases. (a1 a2 a3 -- a2 a1 a3) -.. code:: python +.. code:: ipython2 # e.g. [popop] dipd neato(popdd, rolldown, pop) @@ -1619,7 +1619,7 @@ also get the effect of combinators in some limited cases. (a1 a2 a3 a4 -- a3 a4) -.. code:: python +.. code:: ipython2 # Reverse the order of the top three items. neato(rollup, swap) @@ -1636,7 +1636,7 @@ also get the effect of combinators in some limited cases. Because the type labels represent themselves as valid Python identifiers the ``compile_()`` function doesn’t need to generate them anymore: -.. code:: python +.. code:: ipython2 def compile_(name, f, doc=None): inputs, outputs = f @@ -1652,7 +1652,7 @@ the ``compile_()`` function doesn’t need to generate them anymore: %s = stack return %s''' % (name, doc, i, o) -.. code:: python +.. code:: ipython2 print compile_('F', F) @@ -1668,7 +1668,7 @@ the ``compile_()`` function doesn’t need to generate them anymore: But it cannot magically create new functions that involve e.g. math and such. Note that this is *not* a ``sqr`` function implementation: -.. code:: python +.. code:: ipython2 print compile_('sqr', C(dup, mul)) @@ -1696,7 +1696,7 @@ The functions that *can* be compiled are the ones that have only ``AnyJoyType`` and ``StackJoyType`` labels in their stack effect comments. We can write a function to check that: -.. code:: python +.. code:: ipython2 from itertools import imap @@ -1704,7 +1704,7 @@ comments. We can write a function to check that: def compilable(f): return isinstance(f, tuple) and all(imap(compilable, f)) or stacky(f) -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(defs().items()): if compilable(stack_effect_comment): @@ -1828,7 +1828,7 @@ the “truthiness” of ``StackJoyType`` to false to let e.g. ``joy.utils.stack.concat`` work with our stack effect comment cons-list tuples.) -.. code:: python +.. code:: ipython2 def compose(f, g): (f_in, f_out), (g_in, g_out) = f, g @@ -1840,7 +1840,7 @@ tuples.) I don’t want to rewrite all the defs myself, so I’ll write a little conversion function instead. This is programmer’s laziness. -.. code:: python +.. code:: ipython2 def sequence_to_stack(seq, stack=StackJoyType(23)): for item in seq: stack = item, stack @@ -1854,7 +1854,7 @@ conversion function instead. This is programmer’s laziness. NEW_DEFS['swaack'] = (S[1], S[0]), (S[0], S[1]) globals().update(NEW_DEFS) -.. code:: python +.. code:: ipython2 C(stack, uncons) @@ -1867,7 +1867,7 @@ conversion function instead. This is programmer’s laziness. -.. code:: python +.. code:: ipython2 reduce(C, (stack, uncons, uncons)) @@ -1887,7 +1887,7 @@ The display function should be changed too. Clunky junk, but it will suffice for now. -.. code:: python +.. code:: ipython2 def doc_from_stack_effect(inputs, outputs): switch = [False] # Do we need to display the '...' for the rest of the main stack? @@ -1935,7 +1935,7 @@ Clunky junk, but it will suffice for now. a.append(end) return '[%s]' % ' '.join(a) -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(NEW_DEFS.items()): print name, '=', doc_from_stack_effect(*stack_effect_comment) @@ -1973,7 +1973,7 @@ Clunky junk, but it will suffice for now. uncons = ([a1 .1.] -- a1 [.1.]) -.. code:: python +.. code:: ipython2 print ; print doc_from_stack_effect(*stack) print ; print doc_from_stack_effect(*C(stack, uncons)) @@ -1993,7 +1993,7 @@ Clunky junk, but it will suffice for now. (... a1 -- ... a1 [a1 ...]) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*C(ccons, stack)) @@ -2003,7 +2003,7 @@ Clunky junk, but it will suffice for now. (... a2 a1 [.1.] -- ... [a2 a1 .1.] [[a2 a1 .1.] ...]) -.. code:: python +.. code:: ipython2 Q = C(ccons, stack) @@ -2024,7 +2024,7 @@ Clunky junk, but it will suffice for now. This makes the ``compile_()`` function pretty simple as the stack effect comments are now already in the form needed for the Python code: -.. code:: python +.. code:: ipython2 def compile_(name, f, doc=None): i, o = f @@ -2035,7 +2035,7 @@ comments are now already in the form needed for the Python code: %s = stack return %s''' % (name, doc, i, o) -.. code:: python +.. code:: ipython2 print compile_('Q', Q) @@ -2053,12 +2053,12 @@ comments are now already in the form needed for the Python code: -.. code:: python +.. code:: ipython2 unstack = (S[1], S[0]), S[1] enstacken = S[0], (S[0], S[1]) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*unstack) @@ -2068,7 +2068,7 @@ comments are now already in the form needed for the Python code: ([.1.] --) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*enstacken) @@ -2078,7 +2078,7 @@ comments are now already in the form needed for the Python code: (-- [.0.]) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*C(cons, unstack)) @@ -2088,7 +2088,7 @@ comments are now already in the form needed for the Python code: (a1 [.1.] -- a1) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*C(cons, enstacken)) @@ -2098,7 +2098,7 @@ comments are now already in the form needed for the Python code: (a1 [.1.] -- [[a1 .1.] .2.]) -.. code:: python +.. code:: ipython2 C(cons, unstack) @@ -2117,7 +2117,7 @@ Part VI: Multiple Stack Effects … -.. code:: python +.. code:: ipython2 class IntJoyType(NumberJoyType): prefix = 'i' @@ -2125,7 +2125,7 @@ Part VI: Multiple Stack Effects F = map(FloatJoyType, _R) I = map(IntJoyType, _R) -.. code:: python +.. code:: ipython2 muls = [ ((I[2], (I[1], S[0])), (I[3], S[0])), @@ -2134,7 +2134,7 @@ Part VI: Multiple Stack Effects ((F[2], (F[1], S[0])), (F[3], S[0])), ] -.. code:: python +.. code:: ipython2 for f in muls: print doc_from_stack_effect(*f) @@ -2148,7 +2148,7 @@ Part VI: Multiple Stack Effects (f1 f2 -- f3) -.. code:: python +.. code:: ipython2 for f in muls: try: @@ -2164,7 +2164,7 @@ Part VI: Multiple Stack Effects (a1 -- a1 a1) (f1 f2 -- f3) (f1 -- f2) -.. code:: python +.. code:: ipython2 from itertools import product @@ -2180,7 +2180,7 @@ Part VI: Multiple Stack Effects def MC(F, G): return sorted(set(meta_compose(F, G))) -.. code:: python +.. code:: ipython2 for f in MC([dup], [mul]): print doc_from_stack_effect(*f) @@ -2191,7 +2191,7 @@ Part VI: Multiple Stack Effects (n1 -- n2) -.. code:: python +.. code:: ipython2 for f in MC([dup], muls): print doc_from_stack_effect(*f) @@ -2264,7 +2264,7 @@ Giving us two unifiers: {c: a, d: b, .1.: .0.} {c: a, d: e, .1.: A* b .0.} -.. code:: python +.. code:: ipython2 class KleeneStar(object): @@ -2314,7 +2314,7 @@ Giving us two unifiers: Can now return multiple results… -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -2386,7 +2386,7 @@ Can now return multiple results… def stacky(thing): return thing.__class__ in {AnyJoyType, StackJoyType} -.. code:: python +.. code:: ipython2 a = (As[1], S[1]) a @@ -2400,7 +2400,7 @@ Can now return multiple results… -.. code:: python +.. code:: ipython2 b = (A[1], S[2]) b @@ -2414,7 +2414,7 @@ Can now return multiple results… -.. code:: python +.. code:: ipython2 for result in unify(b, a): print result, '->', update(result, a), update(result, b) @@ -2426,7 +2426,7 @@ Can now return multiple results… {a1: a10001, s2: (a1*, s1)} -> (a1*, s1) (a10001, (a1*, s1)) -.. code:: python +.. code:: ipython2 for result in unify(a, b): print result, '->', update(result, a), update(result, b) @@ -2446,7 +2446,7 @@ Can now return multiple results… (a1*, s1) [a1*] (a2, (a1*, s1)) [a2 a1*] -.. code:: python +.. code:: ipython2 sum_ = ((Ns[1], S[1]), S[0]), (N[0], S[0]) @@ -2458,7 +2458,7 @@ Can now return multiple results… ([n1* .1.] -- n0) -.. code:: python +.. code:: ipython2 f = (N[1], (N[2], (N[3], S[1]))), S[0] @@ -2470,7 +2470,7 @@ Can now return multiple results… (-- [n1 n2 n3 .1.]) -.. code:: python +.. code:: ipython2 for result in unify(sum_[0], f): print result, '->', update(result, sum_[1]) @@ -2489,7 +2489,7 @@ Can now return multiple results… This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 def compose(f, g): (f_in, f_out), (g_in, g_out) = f, g @@ -2501,7 +2501,7 @@ This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 def meta_compose(F, G): for f, g in product(F, G): @@ -2517,7 +2517,7 @@ This function has to be modified to yield multiple results. for fg in compose(f, g): yield delabel(fg) -.. code:: python +.. code:: ipython2 for f in MC([dup], muls): print doc_from_stack_effect(*f) @@ -2529,7 +2529,7 @@ This function has to be modified to yield multiple results. (i1 -- i2) -.. code:: python +.. code:: ipython2 @@ -2542,7 +2542,7 @@ This function has to be modified to yield multiple results. ([n1* .1.] -- [n1* .1.] n1) -.. code:: python +.. code:: ipython2 @@ -2556,7 +2556,7 @@ This function has to be modified to yield multiple results. (n1 [n1* .1.] -- n2) -.. code:: python +.. code:: ipython2 sum_ = (((N[1], (Ns[1], S[1])), S[0]), (N[0], S[0])) print doc_from_stack_effect(*cons), @@ -2571,7 +2571,7 @@ This function has to be modified to yield multiple results. (a1 [.1.] -- [a1 .1.]) ([n1 n1* .1.] -- n0) (n1 [n1* .1.] -- n2) -.. code:: python +.. code:: ipython2 a = (A[4], (As[1], (A[3], S[1]))) a @@ -2585,7 +2585,7 @@ This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 b = (A[1], (A[2], S[2])) b @@ -2599,7 +2599,7 @@ This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 for result in unify(b, a): print result @@ -2611,7 +2611,7 @@ This function has to be modified to yield multiple results. {a1: a4, s2: (a1*, (a3, s1)), a2: a10003} -.. code:: python +.. code:: ipython2 for result in unify(a, b): print result @@ -2681,7 +2681,7 @@ We need a type variable for Joy functions that can go in our expressions and be used by the hybrid inferencer/interpreter. They have to store a name and a list of stack effects. -.. code:: python +.. code:: ipython2 class FunctionJoyType(AnyJoyType): @@ -2703,14 +2703,14 @@ Specialized for Simple Functions and Combinators For non-combinator functions the stack effects list contains stack effect comments (represented by pairs of cons-lists as described above.) -.. code:: python +.. code:: ipython2 class SymbolJoyType(FunctionJoyType): prefix = 'F' For combinators the list contains Python functions. -.. code:: python +.. code:: ipython2 class CombinatorJoyType(FunctionJoyType): @@ -2731,7 +2731,7 @@ For combinators the list contains Python functions. For simple combinators that have only one effect (like ``dip``) you only need one function and it can be the combinator itself. -.. code:: python +.. code:: ipython2 import joy.library @@ -2741,7 +2741,7 @@ For combinators that can have more than one effect (like ``branch``) you have to write functions that each implement the action of one of the effects. -.. code:: python +.. code:: ipython2 def branch_true(stack, expression, dictionary): (then, (else_, (flag, stack))) = stack @@ -2771,7 +2771,7 @@ updated along with the stack effects after doing unification or we risk losing useful information. This was a straightforward, if awkward, modification to the call structure of ``meta_compose()`` et. al. -.. code:: python +.. code:: ipython2 ID = S[0], S[0] # Identity function. @@ -2833,7 +2833,7 @@ cruft to convert the definitions in ``DEFS`` to the new ``SymbolJoyType`` objects, and some combinators. Here is an example of output from the current code : -.. code:: python +.. code:: ipython2 1/0 # (Don't try to run this cell! It's not going to work. This is "read only" code heh..) @@ -2956,7 +2956,7 @@ module. But if you’re interested in all that you should just use Prolog! Anyhow, type *checking* is a few easy steps away. -.. code:: python +.. code:: ipython2 def _ge(self, other): return (issubclass(other.__class__, self.__class__) diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/Zipper.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/Zipper.rst.txt index c44343a..dc4f996 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/Zipper.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/Zipper.rst.txt @@ -10,7 +10,7 @@ Huet `__ out of sequences. -.. code:: python +.. code:: ipython2 J('[1 [2 [3 4 25 6] 7] 8]') @@ -54,14 +54,14 @@ show the trace so you can see how it works. If we were going to use these a lot it would make sense to write Python versions for efficiency, but see below. -.. code:: python +.. code:: ipython2 define('z-down == [] swap uncons swap') define('z-up == swons swap shunt') define('z-right == [swons] cons dip uncons swap') define('z-left == swons [uncons swap] dip swap') -.. code:: python +.. code:: ipython2 V('[1 [2 [3 4 25 6] 7] 8] z-down') @@ -77,7 +77,7 @@ but see below. [] [[2 [3 4 25 6] 7] 8] 1 . -.. code:: python +.. code:: ipython2 V('[] [[2 [3 4 25 6] 7] 8] 1 z-right') @@ -101,7 +101,7 @@ but see below. [1] [8] [2 [3 4 25 6] 7] . -.. code:: python +.. code:: ipython2 J('[1] [8] [2 [3 4 25 6] 7] z-down') @@ -111,7 +111,7 @@ but see below. [1] [8] [] [[3 4 25 6] 7] 2 -.. code:: python +.. code:: ipython2 J('[1] [8] [] [[3 4 25 6] 7] 2 z-right') @@ -121,7 +121,7 @@ but see below. [1] [8] [2] [7] [3 4 25 6] -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [3 4 25 6] z-down') @@ -131,7 +131,7 @@ but see below. [1] [8] [2] [7] [] [4 25 6] 3 -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [] [4 25 6] 3 z-right') @@ -141,7 +141,7 @@ but see below. [1] [8] [2] [7] [3] [25 6] 4 -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [3] [25 6] 4 z-right') @@ -151,7 +151,7 @@ but see below. [1] [8] [2] [7] [4 3] [6] 25 -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [4 3] [6] 25 sqr') @@ -161,7 +161,7 @@ but see below. [1] [8] [2] [7] [4 3] [6] 625 -.. code:: python +.. code:: ipython2 V('[1] [8] [2] [7] [4 3] [6] 625 z-up') @@ -184,7 +184,7 @@ but see below. [1] [8] [2] [7] [3 4 625 6] . -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [3 4 625 6] z-up') @@ -194,7 +194,7 @@ but see below. [1] [8] [2 [3 4 625 6] 7] -.. code:: python +.. code:: ipython2 J('[1] [8] [2 [3 4 625 6] 7] z-up') @@ -210,7 +210,7 @@ but see below. In Joy we have the ``dip`` and ``infra`` combinators which can “target” or “address” any particular item in a Joy tree structure. -.. code:: python +.. code:: ipython2 V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra') @@ -270,13 +270,13 @@ been embedded in a nested series of quoted programs, e.g.: The ``Z`` function isn’t hard to make. -.. code:: python +.. code:: ipython2 define('Z == [[] cons cons] step i') Here it is in action in a simplified scenario. -.. code:: python +.. code:: ipython2 V('1 [2 3 4] Z') @@ -314,7 +314,7 @@ Here it is in action in a simplified scenario. And here it is doing the main thing. -.. code:: python +.. code:: ipython2 J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z') diff --git a/docs/sphinx_docs/_build/html/_sources/notebooks/index.rst.txt b/docs/sphinx_docs/_build/html/_sources/notebooks/index.rst.txt index c14aafa..dbb23a5 100644 --- a/docs/sphinx_docs/_build/html/_sources/notebooks/index.rst.txt +++ b/docs/sphinx_docs/_build/html/_sources/notebooks/index.rst.txt @@ -16,6 +16,7 @@ These essays are adapted from Jupyter notebooks. I hope to have those hosted so Treestep Generator_Programs Newton-Raphson + Square_Spiral Zipper Types TypeChecking diff --git a/docs/sphinx_docs/_build/html/index.html b/docs/sphinx_docs/_build/html/index.html index 4e3c3be..24307ce 100644 --- a/docs/sphinx_docs/_build/html/index.html +++ b/docs/sphinx_docs/_build/html/index.html @@ -54,6 +54,29 @@ additional joy interpreter (the binary in the archive from La Trobe seems to run just fine on my modern Linux machine!) But I also hope that you can read and understand the Python code and play with the implementation itself.

+
+

Example Code¶

+

Here is an example of Joy code:

+
[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
+
+
+

It might seem unreadable but with a little familiarity it becomes just as +legible as any other notation. Some layout helps:

+
[   [[abs] ii <=]
+    [
+        [<>] [pop !-] ||
+    ] &&
+]
+[[    !-] [[++]] [[--]] ifte dip]
+[[pop !-]  [--]   [++]  ifte    ]
+ifte
+
+
+

This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral). For more information see Square Spiral Example Joy Code

+

Quick Start¶

Install from PyPI in the usual way:

@@ -145,6 +168,7 @@ interesting aspects. It’s quite a treasure trove.

  • Treating Trees II: treestep
  • Using x to Generate Values
  • Newton’s method
  • +
  • Square Spiral Example Joy Code
  • Traversing Datastructures with Zippers
  • The Blissful Elegance of Typing Joy
  • Type Checking
  • diff --git a/docs/sphinx_docs/_build/html/notebooks/Derivatives_of_Regular_Expressions.html b/docs/sphinx_docs/_build/html/notebooks/Derivatives_of_Regular_Expressions.html index 57d7180..80ade99 100644 --- a/docs/sphinx_docs/_build/html/notebooks/Derivatives_of_Regular_Expressions.html +++ b/docs/sphinx_docs/_build/html/notebooks/Derivatives_of_Regular_Expressions.html @@ -96,14 +96,14 @@ R∘λ = λ∘R = R

    Implementation¶

    -
    from functools import partial as curry
    +
    from functools import partial as curry
     from itertools import product
     

    ϕ and λ¶

    The empty set and the set of just the empty string.

    -
    phi = frozenset()   # ϕ
    +
    phi = frozenset()   # ϕ
     y = frozenset({''}) # λ
     
    @@ -115,7 +115,7 @@ illustrate the algorithm and because you can represent any other alphabet with two symbols (if you had to.)

    I chose the names O and l (uppercase “o” and lowercase “L”) to look like 0 and 1 (zero and one) respectively.

    -
    syms = O, l = frozenset({'0'}), frozenset({'1'})
    +
    syms = O, l = frozenset({'0'}), frozenset({'1'})
     
    @@ -133,7 +133,7 @@ expression is one of:

    Where R and S stand for regular expressions.

    -
    AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split()  # Tags are just strings.
    +
    AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split()  # Tags are just strings.
     

    Because they are formed of frozenset, tuple and str objects @@ -141,7 +141,7 @@ only, these datastructures are immutable.

    String Representation of RE Datastructures¶

    -
    def stringy(re):
    +
    def stringy(re):
         '''
         Return a nice string repr for a regular expression datastructure.
         '''
    @@ -180,10 +180,10 @@ only, these datastructures are immutable.

    I = (0|1)*
     
    -
    I = (KSTAR, (OR, O, l))
    +
    I = (KSTAR, (OR, O, l))
     
    -
    print stringy(I)
    +
    print stringy(I)
     
    .
    @@ -198,13 +198,13 @@ only, these datastructures are immutable.

    Note that it contains one of everything.

    -
    a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I))))
    +
    a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I))))
     b = (CONS, I, (CONS, O, l))
     c = (CONS, l, (KSTAR, l))
     it = (AND, a, (NOT, (OR, b, c)))
     
    -
    print stringy(it)
    +
    print stringy(it)
     
    (.111.) & ((.01 | 11*)')
    @@ -214,7 +214,7 @@ only, these datastructures are immutable.

    nully()¶

    Let’s get that auxiliary predicate function δ out of the way.

    -
    def nully(R):
    +
    def nully(R):
         '''
         δ - Return λ if λ ⊆ R otherwise ϕ.
         '''
    @@ -252,7 +252,7 @@ only, these datastructures are immutable.

    This is the straightforward version with no “compaction”. It works fine, but does waaaay too much work because the expressions grow each derivation.

    -
    def D(symbol):
    +
    def D(symbol):
     
         def derv(R):
     
    @@ -296,7 +296,7 @@ derivation.

    Compaction Rules¶

    -
    def _compaction_rule(relation, one, zero, a, b):
    +
    def _compaction_rule(relation, one, zero, a, b):
         return (
             b if a == one else  # R*1 = 1*R = R
             a if b == one else
    @@ -306,7 +306,7 @@ derivation.

    An elegant symmetry.

    -
    # R ∧ I = I ∧ R = R
    +
    # R ∧ I = I ∧ R = R
     # R ∧ ϕ = ϕ ∧ R = ϕ
     _and = curry(_compaction_rule, AND, I, phi)
     
    @@ -325,7 +325,7 @@ derivation.

    We can save re-processing by remembering results we have already computed. RE datastructures are immutable and the derv() functions are pure so this is fine.

    -
    class Memo(object):
    +
    class Memo(object):
     
         def __init__(self, f):
             self.f = f
    @@ -347,7 +347,7 @@ are pure so this is fine.

    With “Compaction”¶

    This version uses the rules above to perform compaction. It keeps the expressions from growing too large.

    -
    def D_compaction(symbol):
    +
    def D_compaction(symbol):
     
         @Memo
         def derv(R):
    @@ -395,7 +395,7 @@ expressions from growing too large.

    Let’s try it out…¶

    (FIXME: redo.)

    -
    o, z = D_compaction('0'), D_compaction('1')
    +
    o, z = D_compaction('0'), D_compaction('1')
     REs = set()
     N = 5
     names = list(product(*(N * [(0, 1)])))
    @@ -500,8 +500,8 @@ machine transition table.

    Says, “Three or more 1’s and not ending in 01 nor composed of all 1’s.”

    -State Machine Graph
    -

    State Machine Graph¶

    +omg.svg
    +

    omg.svg¶

    Start at a and follow the transition arrows according to their @@ -555,18 +555,18 @@ a --1--> ∂1(a)

    You can see the one-way nature of the g state and the hij “trap” in the way that the .111. on the left-hand side of the & disappears once it has been matched.

    -
    from collections import defaultdict
    +
    from collections import defaultdict
     from pprint import pprint
     from string import ascii_lowercase
     
    -
    d0, d1 = D_compaction('0'), D_compaction('1')
    +
    d0, d1 = D_compaction('0'), D_compaction('1')
     

    explore()¶

    -
    def explore(re):
    +
    def explore(re):
     
         # Don't have more than 26 states...
         names = defaultdict(iter(ascii_lowercase).next)
    @@ -592,7 +592,7 @@ disappears once it has been matched.

    return table, accepting
    -
    table, accepting = explore(it)
    +
    table, accepting = explore(it)
     table
     
    @@ -618,7 +618,7 @@ disappears once it has been matched.

    ('j', 1): 'h'}
    -
    accepting
    +
    accepting
     
    {'h', 'i'}
    @@ -629,7 +629,7 @@ disappears once it has been matched.

    Generate Diagram¶

    Once we have the FSM table and the set of accepting states we can generate the diagram above.

    -
    _template = '''\
    +
    _template = '''\
     digraph finite_state_machine {
       rankdir=LR;
       size="8,5"
    @@ -653,7 +653,7 @@ generate the diagram above.

    )
    -
    print make_graph(table, accepting)
    +
    print make_graph(table, accepting)
     
    digraph finite_state_machine {
    @@ -699,7 +699,7 @@ hard-code the information in the table into a little patch of branches.

    Trampoline Function¶

    Python has no GOTO statement but we can fake it with a “trampoline” function.

    -
    def trampoline(input_, jump_from, accepting):
    +
    def trampoline(input_, jump_from, accepting):
         I = iter(input_)
         while True:
             try:
    @@ -714,7 +714,7 @@ function.

    Stream Functions¶

    Little helpers to process the iterator of our data (a “stream” of “1” and “0” characters, not bits.)

    -
    getch = lambda I: int(next(I))
    +
    getch = lambda I: int(next(I))
     
     
     def _1(I):
    @@ -735,7 +735,7 @@ and “0” characters, not bits.)

    code. (You have to imagine that these are GOTO statements in C or branches in assembly and that the state names are branch destination labels.)

    -
    a = lambda I: c if getch(I) else b
    +
    a = lambda I: c if getch(I) else b
     b = lambda I: _0(I) or d
     c = lambda I: e if getch(I) else b
     d = lambda I: f if getch(I) else b
    @@ -750,11 +750,11 @@ labels.)

    Note that the implementations of h and g are identical ergo h = g and we could eliminate one in the code but h is an accepting state and g isn’t.

    -
    def acceptable(input_):
    +
    def acceptable(input_):
         return trampoline(input_, a, {h, i})
     
    -
    for n in range(2**5):
    +
    for n in range(2**5):
         s = bin(n)[2:]
         print '%05s' % s, acceptable(s)
     
    @@ -878,6 +878,7 @@ derivative-with-respect-to-N of some other state/RE:

  • Treating Trees II: treestep
  • Using x to Generate Values
  • Newton’s method
  • +
  • Square Spiral Example Joy Code
  • Traversing Datastructures with Zippers
  • The Blissful Elegance of Typing Joy
  • Type Checking
  • diff --git a/docs/sphinx_docs/_build/html/notebooks/Generator_Programs.html b/docs/sphinx_docs/_build/html/notebooks/Generator_Programs.html index 19aa59b..441434a 100644 --- a/docs/sphinx_docs/_build/html/notebooks/Generator_Programs.html +++ b/docs/sphinx_docs/_build/html/notebooks/Generator_Programs.html @@ -36,7 +36,7 @@

    Using x to Generate Values¶

    Cf. jp-reprod.html

    -
    from notebook_preamble import J, V, define
    +
    from notebook_preamble import J, V, define
     

    Consider the x combinator:

    @@ -76,7 +76,7 @@ function C

    Let’s try it:

    -
    V('[0 swap [dup ++] dip rest cons] x')
    +
    V('[0 swap [dup ++] dip rest cons] x')
     
                                               . [0 swap [dup ++] dip rest cons] x
    @@ -95,7 +95,7 @@ function C
     

    After one application of x the quoted program contains 1 and 0 is below it on the stack.

    -
    J('[0 swap [dup ++] dip rest cons] x x x x x pop')
    +
    J('[0 swap [dup ++] dip rest cons] x x x x x pop')
     
    0 1 2 3 4
    @@ -103,10 +103,10 @@ function C
     

    direco¶

    -
    define('direco == dip rest cons')
    +
    define('direco == dip rest cons')
     
    -
    V('[0 swap [dup ++] direco] x')
    +
    V('[0 swap [dup ++] direco] x')
     
                                        . [0 swap [dup ++] direco] x
    @@ -147,17 +147,17 @@ our quoted program:

    G == [direco] cons [swap] swoncat cons
    -
    define('G == [direco] cons [swap] swoncat cons')
    +
    define('G == [direco] cons [swap] swoncat cons')
     

    Let’s try it out:

    -
    J('0 [dup ++] G')
    +
    J('0 [dup ++] G')
     
    [0 swap [dup ++] direco]
     
    -
    J('0 [dup ++] G x x x pop')
    +
    J('0 [dup ++] G x x x pop')
     
    0 1 2
    @@ -165,7 +165,7 @@ our quoted program:

    Powers of 2¶

    -
    J('1 [dup 1 <<] G x x x x x x x x x pop')
    +
    J('1 [dup 1 <<] G x x x x x x x x x pop')
     
    1 2 4 8 16 32 64 128 256
    @@ -176,7 +176,7 @@ our quoted program:

    [x] times¶

    If we have one of these quoted programs we can drive it using times with the x combinator.

    -
    J('23 [dup ++] G 5 [x] times')
    +
    J('23 [dup ++] G 5 [x] times')
     
    23 24 25 26 27 [28 swap [dup ++] direco]
    @@ -200,10 +200,10 @@ int:

    And pick them off by masking with 3 (binary 11) and then shifting the int right two bits.

    -
    define('PE1.1 == dup [3 &] dip 2 >>')
    +
    define('PE1.1 == dup [3 &] dip 2 >>')
     
    -
    V('14811 PE1.1')
    +
    V('14811 PE1.1')
     
                      . 14811 PE1.1
    @@ -220,14 +220,14 @@ int right two bits.

    If we plug 14811 and [PE1.1] into our generator form…

    -
    J('14811 [PE1.1] G')
    +
    J('14811 [PE1.1] G')
     
    [14811 swap [PE1.1] direco]
     

    …we get a generator that works for seven cycles before it reaches zero:

    -
    J('[14811 swap [PE1.1] direco] 7 [x] times')
    +
    J('[14811 swap [PE1.1] direco] 7 [x] times')
     
    3 2 1 3 1 2 3 [0 swap [PE1.1] direco]
    @@ -237,16 +237,16 @@ int right two bits.

    Reset at Zero¶

    We need a function that checks if the int has reached zero and resets it if so.

    -
    define('PE1.1.check == dup [pop 14811] [] branch')
    +
    define('PE1.1.check == dup [pop 14811] [] branch')
     
    -
    J('14811 [PE1.1.check PE1.1] G')
    +
    J('14811 [PE1.1.check PE1.1] G')
     
    [14811 swap [PE1.1.check PE1.1] direco]
     
    -
    J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
    +
    J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
     
    3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 [0 swap [PE1.1.check PE1.1] direco]
    @@ -262,20 +262,20 @@ say.)

    In the PE1 problem we are asked to sum all the multiples of three and five less than 1000. It’s worked out that we need to use all seven numbers sixty-six times and then four more.

    -
    J('7 66 * 4 +')
    +
    J('7 66 * 4 +')
     
    466
     

    If we drive our generator 466 times and sum the stack we get 999.

    -
    J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')
    +
    J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')
     
    3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco]
     
    -
    J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')
    +
    J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')
     
    999
    @@ -285,11 +285,11 @@ numbers sixty-six times and then four more.

    Project Euler Problem One¶

    -
    define('PE1.2 == + dup [+] dip')
    +
    define('PE1.2 == + dup [+] dip')
     

    Now we can add PE1.2 to the quoted program given to G.

    -
    J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop')
    +
    J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop')
     
    233168
    @@ -351,13 +351,13 @@ numbers sixty-six times and then four more.

    fib_gen == [1 1 F]
    -
    define('fib == + [popdd over] cons infra uncons')
    +
    define('fib == + [popdd over] cons infra uncons')
     
    -
    define('fib_gen == [1 1 fib]')
    +
    define('fib_gen == [1 1 fib]')
     
    -
    J('fib_gen 10 [x] times')
    +
    J('fib_gen 10 [x] times')
     
    1 2 3 5 8 13 21 34 55 89 [144 89 fib]
    @@ -373,21 +373,21 @@ not exceed four million, find the sum of the even-valued terms.

    Now that we have a generator for the Fibonacci sequence, we need a function that adds a term in the sequence to a sum if it is even, and pops it otherwise.

    -
    define('PE2.1 == dup 2 % [+] [pop] branch')
    +
    define('PE2.1 == dup 2 % [+] [pop] branch')
     

    And a predicate function that detects when the terms in the series “exceed four million”.

    -
    define('>4M == 4000000 >')
    +
    define('>4M == 4000000 >')
     

    Now it’s straightforward to define PE2 as a recursive function that generates terms in the Fibonacci sequence until they exceed four million and sums the even ones.

    -
    define('PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec')
    +
    define('PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec')
     
    -
    J('PE2')
    +
    J('PE2')
     
    4613732
    @@ -418,23 +418,23 @@ and sums the even ones.

    Every third term is even.

    -
    J('[1 0 fib] x x x')  # To start the sequence with 1 1 2 3 instead of 1 2 3.
    +
    J('[1 0 fib] x x x')  # To start the sequence with 1 1 2 3 instead of 1 2 3.
     
    1 1 2 [3 2 fib]
     

    Drive the generator three times and popop the two odd terms.

    -
    J('[1 0 fib] x x x [popop] dipd')
    +
    J('[1 0 fib] x x x [popop] dipd')
     
    2 [3 2 fib]
     
    -
    define('PE2.2 == x x x [popop] dipd')
    +
    define('PE2.2 == x x x [popop] dipd')
     
    -
    J('[1 0 fib] 10 [PE2.2] times')
    +
    J('[1 0 fib] 10 [PE2.2] times')
     
    2 8 34 144 610 2584 10946 46368 196418 832040 [1346269 832040 fib]
    @@ -442,7 +442,7 @@ and sums the even ones.

    Replace x with our new driver function PE2.2 and start our fib generator at 1 0.

    -
    J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec')
    +
    J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec')
     
    4613732
    @@ -457,10 +457,10 @@ modifications to the default 
     

    An Interesting Variation¶

    -
    define('codireco == cons dip rest cons')
    +
    define('codireco == cons dip rest cons')
     
    -
    V('[0 [dup ++] codireco] x')
    +
    V('[0 [dup ++] codireco] x')
     
                                     . [0 [dup ++] codireco] x
    @@ -479,10 +479,10 @@ modifications to the default 0 [1 [dup ++] codireco] .
     
    -
    define('G == [codireco] cons cons')
    +
    define('G == [codireco] cons cons')
     
    -
    J('230 [dup ++] G 5 [x] times pop')
    +
    J('230 [dup ++] G 5 [x] times pop')
     
    230 231 232 233 234
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Newton-Raphson.html b/docs/sphinx_docs/_build/html/notebooks/Newton-Raphson.html
    index 59279b8..b1ea797 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/Newton-Raphson.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/Newton-Raphson.html
    @@ -40,7 +40,7 @@
     to write a function that can compute the square root of a number.

    Cf. “Why Functional Programming Matters” by John Hughes

    -
    from notebook_preamble import J, V, define
    +
    from notebook_preamble import J, V, define
     
    @@ -92,10 +92,10 @@ function we’re writing. If we let 1 be the initial approximation:

    1 [dup 23 over / + 2 /] make_generator
    -
    define('gsra 1 swap [over / + 2 /] cons [dup] swoncat make_generator')
    +
    define('gsra 1 swap [over / + 2 /] cons [dup] swoncat make_generator')
     
    -
    J('23 gsra')
    +
    J('23 gsra')
     
    [1 [dup 23 over / + 2 /] codireco]
    @@ -103,7 +103,7 @@ function we’re writing. If we let 1 be the initial approximation:

    Let’s drive the generator a few time (with the x combinator) and square the approximation to see how well it works…

    -
    J('23 gsra 6 [x popd] times first sqr')
    +
    J('23 gsra 6 [x popd] times first sqr')
     
    23.0000000001585
    @@ -145,7 +145,7 @@ generated already and epsilon ε is handy on the stack…

    (abs(a-b)<=ε)
    -
    define('_within_P [first - abs] dip <=')
    +
    define('_within_P [first - abs] dip <=')
     
    @@ -157,7 +157,7 @@ generated already and epsilon ε is handy on the stack…

    b
    -
    define('_within_B roll< popop first')
    +
    define('_within_B roll< popop first')
     
    @@ -182,7 +182,7 @@ generated already and epsilon ε is handy on the stack…

    b [c G] ε within
    -
    define('_within_R [popd x] dip')
    +
    define('_within_R [popd x] dip')
     
    @@ -194,31 +194,31 @@ generated already and epsilon ε is handy on the stack…

    a [b G] ε ...
    -
    define('within x 0.000000001 [_within_P] [_within_B] [_within_R] tailrec')
    +
    define('within x 0.000000001 [_within_P] [_within_B] [_within_R] tailrec')
     define('sqrt gsra within')
     

    Try it out…

    -
    J('36 sqrt')
    +
    J('36 sqrt')
     
    6.0
     
    -
    J('23 sqrt')
    +
    J('23 sqrt')
     
    4.795831523312719
     

    Check it.

    -
    4.795831523312719**2
    +
    4.795831523312719**2
     
    22.999999999999996
     
    -
    from math import sqrt
    +
    from math import sqrt
     
     sqrt(23)
     
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Ordered_Binary_Trees.html b/docs/sphinx_docs/_build/html/notebooks/Ordered_Binary_Trees.html index eabfaba..d4bce1f 100644 --- a/docs/sphinx_docs/_build/html/notebooks/Ordered_Binary_Trees.html +++ b/docs/sphinx_docs/_build/html/notebooks/Ordered_Binary_Trees.html @@ -63,7 +63,7 @@ the Sufficiently Smart Compiler can be modified to use an optimized implementation under the hood. (Where does the “type” come from? It has a contingent existence predicated on the disciplined use of these functions on otherwise undistinguished Joy datastructures.)

    -
    from notebook_preamble import D, J, V, define, DefinitionWrapper
    +
    from notebook_preamble import D, J, V, define, DefinitionWrapper
     
    @@ -100,10 +100,10 @@ functions on otherwise undistinguished Joy datastructures.)

    Tree-new == swap [[] []] cons cons
     
    -
    define('Tree-new == swap [[] []] cons cons')
    +
    define('Tree-new == swap [[] []] cons cons')
     
    -
    J('"v" "k" Tree-new')
    +
    J('"v" "k" Tree-new')
     
    ['k' 'v' [] []]
    @@ -159,10 +159,10 @@ comparison operator:

    P == pop roll> pop first
    -
    define('P == pop roll> pop first')
    +
    define('P == pop roll> pop first')
     
    -
    J('["old_key" 23 [] []] 17 "new_key" ["..."] P')
    +
    J('["old_key" 23 [] []] 17 "new_key" ["..."] P')
     
    'new_key' 'old_key'
    @@ -217,10 +217,10 @@ stack:

    T == cons cons [dipdd] cons infra
     
    -
    define('T == cons cons [dipdd] cons infra')
    +
    define('T == cons cons [dipdd] cons infra')
     
    -
    J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] T')
    +
    J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] T')
     
    ['old_k' 'old_value' 'left' 'Tree-add' 'new_key' 'new_value' 'right']
    @@ -234,7 +234,7 @@ stack:

    [key_n value_n left right] value key [Tree-add] [P <] [Te] [Ee] ifte
    -
    define('E == [P <] [Te] [Ee] ifte')
    +
    define('E == [P <] [Te] [Ee] ifte')
     

    In this case Te works that same as T but on the left child tree @@ -243,10 +243,10 @@ instead of the right, so the only difference is that it must use

    Te == cons cons [dipd] cons infra
     
    -
    define('Te == cons cons [dipd] cons infra')
    +
    define('Te == cons cons [dipd] cons infra')
     
    -
    J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] Te')
    +
    J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] Te')
     
    ['old_k' 'old_value' 'Tree-add' 'new_key' 'new_value' 'left' 'right']
    @@ -274,10 +274,10 @@ instead of the right, so the only difference is that it must use
                   [key new_value left right]
     
    -
    define('Ee == pop swap roll< rest rest cons cons')
    +
    define('Ee == pop swap roll< rest rest cons cons')
     
    -
    J('["k" "old_value" "left" "right"] "new_value" "k" ["Tree-add"] Ee')
    +
    J('["k" "old_value" "left" "right"] "new_value" "k" ["Tree-add"] Ee')
     
    ['k' 'new_value' 'left' 'right']
    @@ -302,43 +302,43 @@ instead of the right, so the only difference is that it must use
     Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
     
    -
    define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [[P >] [T] [E] ifte] genrec')
    +
    define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [[P >] [T] [E] ifte] genrec')
     

    Examples¶

    -
    J('[] 23 "b" Tree-add')  # Initial
    +
    J('[] 23 "b" Tree-add')  # Initial
     
    ['b' 23 [] []]
     
    -
    J('["b" 23 [] []] 88 "c" Tree-add')  # Greater than
    +
    J('["b" 23 [] []] 88 "c" Tree-add')  # Greater than
     
    ['b' 23 [] ['c' 88 [] []]]
     
    -
    J('["b" 23 [] []] 88 "a" Tree-add')  # Less than
    +
    J('["b" 23 [] []] 88 "a" Tree-add')  # Less than
     
    ['b' 23 ['a' 88 [] []] []]
     
    -
    J('["b" 23 [] []] 88 "b" Tree-add')  # Equal to
    +
    J('["b" 23 [] []] 88 "b" Tree-add')  # Equal to
     
    ['b' 88 [] []]
     
    -
    J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add')  # Series.
    +
    J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add')  # Series.
     
    ['b' 23 ['a' 88 [] []] ['c' 44 [] []]]
     
    -
    J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step')
    +
    J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step')
     
    ['b' 23 ['a' 88 [] []] ['c' 44 [] []]]
    @@ -365,19 +365,19 @@ values:

    L
    -
    J("1 0 ['G'] ['E'] ['L'] cmp")
    +
    J("1 0 ['G'] ['E'] ['L'] cmp")
     
    'G'
     
    -
    J("1 1 ['G'] ['E'] ['L'] cmp")
    +
    J("1 1 ['G'] ['E'] ['L'] cmp")
     
    'E'
     
    -
    J("0 1 ['G'] ['E'] ['L'] cmp")
    +
    J("0 1 ['G'] ['E'] ['L'] cmp")
     
    'L'
    @@ -414,7 +414,7 @@ node key (by throwing everything else away):

    P == over [popop popop first] nullary
     
    -
    define('P == over [popop popop first] nullary')
    +
    define('P == over [popop popop first] nullary')
     

    Using cmp to simplify our code above at @@ -434,10 +434,10 @@ to understand:

    Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec
     
    -
    define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec')
    +
    define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec')
     
    -
    J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add')  # Still works.
    +
    J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add')  # Still works.
     
    ['b' 23 ['a' 88 [] []] ['c' 44 [] []]]
    @@ -545,22 +545,22 @@ with an interesting situation:

    Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec
     
    -
    define('Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec')
    +
    define('Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec')
     

    Examples¶

    -
    J('[] [foo] Tree-iter')  #  It doesn't matter what F is as it won't be used.
    +
    J('[] [foo] Tree-iter')  #  It doesn't matter what F is as it won't be used.
     
    -
    J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [first] Tree-iter")
    +
    J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [first] Tree-iter")
     
    'b' 'a' 'c'
     
    -
    J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [second] Tree-iter")
    +
    J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [second] Tree-iter")
     
    23 88 44
    @@ -575,16 +575,16 @@ to e.g. 0 and ignoring them. It’s set-like in that duplicate items added
     to it will only occur once within it, and we can query it in
     :math:`O(log_2 N) <https://en.wikipedia.org/wiki/Binary_search_tree#cite_note-2>`__
     time.

    -
    J('[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step')
    +
    J('[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step')
     
    [3 0 [2 0 [] []] [9 0 [5 0 [4 0 [] []] [8 0 [6 0 [] [7 0 [] []]] []]] []]]
     
    -
    define('to_set == [] swap [0 swap Tree-add] step')
    +
    define('to_set == [] swap [0 swap Tree-add] step')
     
    -
    J('[3 9 5 2 8 6 7 8 4] to_set')
    +
    J('[3 9 5 2 8 6 7 8 4] to_set')
     
    [3 0 [2 0 [] []] [9 0 [5 0 [4 0 [] []] [8 0 [6 0 [] [7 0 [] []]] []]] []]]
    @@ -592,10 +592,10 @@ time.

    And with that we can write a little program unique to remove duplicate items from a list.

    -
    define('unique == [to_set [first] Tree-iter] cons run')
    +
    define('unique == [to_set [first] Tree-iter] cons run')
     
    -
    J('[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique')  # Filter duplicate items.
    +
    J('[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique')  # Filter duplicate items.
     
    [7 6 8 4 5 9 2 3]
    @@ -679,7 +679,7 @@ right side:

    Now we can sort sequences.

    -
    #define('Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec')
    +
    #define('Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec')
     
     
     DefinitionWrapper.add_definitions('''
    @@ -695,7 +695,7 @@ right side:

    ''', D)
    -
    J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order')
    +
    J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order')
     
    2 3 4 5 6 7 8 9
    @@ -835,7 +835,7 @@ because there’s no value to discard.

    Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec
    -
    # I don't want to deal with name conflicts with the above so I'm inlining everything here.
    +
    # I don't want to deal with name conflicts with the above so I'm inlining everything here.
     # The original Joy system has "hide" which is a meta-command which allows you to use named
     # definitions that are only in scope for a given definition.  I don't want to implement
     # that (yet) so...
    @@ -852,19 +852,19 @@ because there’s no value to discard.

    ''')
    -
    J('["gary" 23 [] []] "mike" [popd " not in tree" +] Tree-get')
    +
    J('["gary" 23 [] []] "mike" [popd " not in tree" +] Tree-get')
     
    'mike not in tree'
     
    -
    J('["gary" 23 [] []] "gary" [popop "err"] Tree-get')
    +
    J('["gary" 23 [] []] "gary" [popop "err"] Tree-get')
     
    23
     
    -
    J('''
    +
    J('''
     
         [] [[0 'a'] [1 'b'] [2 'c']] [i Tree-add] step
     
    @@ -876,7 +876,7 @@ because there’s no value to discard.

    2
     
    -
    J('''
    +
    J('''
     
         [] [[0 'a'] [1 'b'] [2 'c']] [i Tree-add] step
     
    @@ -1175,7 +1175,7 @@ E == [
     

    By the standards of the code I’ve written so far, this is a huge Joy program.

    -
    DefinitionWrapper.add_definitions('''
    +
    DefinitionWrapper.add_definitions('''
     first_two == uncons uncons pop
     fourth == rest rest rest first
     ?fourth == [] [fourth] [] ifte
    @@ -1193,43 +1193,43 @@ program.

    ''', D)
    -
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' Tree-Delete ")
    +
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' Tree-Delete ")
     
    ['a' 23 [] ['b' 88 [] []]]
     
    -
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' Tree-Delete ")
    +
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' Tree-Delete ")
     
    ['a' 23 [] ['c' 44 [] []]]
     
    -
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' Tree-Delete ")
    +
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' Tree-Delete ")
     
    ['b' 88 [] ['c' 44 [] []]]
     
    -
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' Tree-Delete ")
    +
    J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' Tree-Delete ")
     
    ['a' 23 [] ['b' 88 [] ['c' 44 [] []]]]
     
    -
    J('[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step')
    +
    J('[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step')
     
    [4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]]
     
    -
    J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete ")
    +
    J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete ")
     
    [4 0 [2 0 [1 0 [] []] []] [6 0 [5 0 [] []] [7 0 [] []]]]
     
    -
    J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete ")
    +
    J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete ")
     
    [3 0 [2 0 [1 0 [] []] []] [6 0 [5 0 [] []] [7 0 [] []]]]
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Quadratic.html b/docs/sphinx_docs/_build/html/notebooks/Quadratic.html
    index 40c3b6d..93bb733 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/Quadratic.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/Quadratic.html
    @@ -34,7 +34,7 @@
     
               
    -
    from notebook_preamble import J, V, define
    +  
    from notebook_preamble import J, V, define
     
    @@ -100,11 +100,11 @@ the variables:

    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:

    -
    define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
    +
    define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
     

    Let’s try it out:

    -
    J('3 1 1 quadratic')
    +
    J('3 1 1 quadratic')
     
    -0.3819660112501051 -2.618033988749895
    @@ -114,7 +114,7 @@ the right and say it’s the definition of 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.

    -
    V('-5 1 4 quadratic')
    +
    V('-5 1 4 quadratic')
     
                                                       . -5 1 4 quadratic
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Recursion_Combinators.html b/docs/sphinx_docs/_build/html/notebooks/Recursion_Combinators.html
    index e1cdc26..10ce08d 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/Recursion_Combinators.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/Recursion_Combinators.html
    @@ -33,7 +33,7 @@
     
               
    -
    from notebook_preamble import D, DefinitionWrapper, J, V, define
    +  
    from notebook_preamble import D, DefinitionWrapper, J, V, define
     
    @@ -101,7 +101,7 @@ cons list”.

    It may be helpful to see this function implemented in imperative Python code.

    -
    def hylomorphism(c, F, P, G):
    +
    def hylomorphism(c, F, P, G):
         '''Return a hylomorphism function H.'''
     
         def H(a):
    @@ -185,7 +185,7 @@ the left so we have a definition for 
     
    hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec
     
    -
    define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
    +
    define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
     
    @@ -200,17 +200,17 @@ of all positive integers less than that one. (In this case the types
  • [G] is [-- dup]

  • [F] is [+]

  • -
    define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
    +
    define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
     

    Let’s try it:

    -
    J('5 triangular_number')
    +
    J('5 triangular_number')
     
    10
     
    -
    J('[0 1 2 3 4 5 6] [triangular_number] map')
    +
    J('[0 1 2 3 4 5 6] [triangular_number] map')
     
    [0 0 1 3 6 10 15]
    @@ -362,9 +362,8 @@ 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.

    +
    +

    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.

    @@ -373,10 +372,10 @@ values.

    == [0 <=] [pop []] [-- dup] [dip swons] genrec
    -
    define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
    +
    define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
     
    -
    J('5 range')
    +
    J('5 range')
     
    [4 3 2 1 0]
    @@ -389,10 +388,10 @@ values.

    == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec
    -
    define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
    +
    define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
     
    -
    J('5 range_reverse')
    +
    J('5 range_reverse')
     
    [0 1 2 3 4]
    @@ -405,10 +404,10 @@ values.

    == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec
    -
    define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
    +
    define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
     
    -
    J('5 ranger')
    +
    J('5 ranger')
     
    [5 4 3 2 1]
    @@ -421,10 +420,10 @@ values.

    == [] swap [0 <=] [pop] [[swons] dupdip --] primrec
    -
    define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
    +
    define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
     
    -
    J('5 ranger_reverse')
    +
    J('5 ranger_reverse')
     
    [1 2 3 4 5]
    @@ -445,17 +444,17 @@ and makes some new value.

    C == [not] c [uncons swap] [F] hylomorphism
     
    -
    define('swuncons == uncons swap')  # Awkward name.
    +
    define('swuncons == uncons swap')  # Awkward name.
     

    An example of a catamorphism is the sum function.

    sum == [not] 0 [swuncons] [+] hylomorphism
     
    -
    define('sum == [not] 0 [swuncons] [+] hylomorphism')
    +
    define('sum == [not] 0 [swuncons] [+] hylomorphism')
     
    -
    J('[5 4 3 2 1] sum')
    +
    J('[5 4 3 2 1] sum')
     
    15
    @@ -465,7 +464,7 @@ and makes some new value.

    The step combinator¶

    The step combinator will usually be better to use than catamorphism.

    -
    J('[step] help')
    +
    J('[step] help')
     
    Run a quoted program on each item in a sequence.
    @@ -489,10 +488,10 @@ and makes some new value.

    on top of the stack.
    -
    define('sum == 0 swap [+] step')
    +
    define('sum == 0 swap [+] step')
     
    -
    J('[5 4 3 2 1] sum')
    +
    J('[5 4 3 2 1] sum')
     
    15
    @@ -513,10 +512,10 @@ and makes some new value.

    P == 1 <=
    -
    define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
    +
    define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
     
    -
    J('5 factorial')
    +
    J('5 factorial')
     
    120
    @@ -545,10 +544,10 @@ pattern H2P == not
     
    -
    define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
    +
    define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
     
    -
    J('[1 2 3] tails')
    +
    J('[1 2 3] tails')
     
    [[] [3] [2 3]]
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Replacing.html b/docs/sphinx_docs/_build/html/notebooks/Replacing.html
    index 6f1aaf6..67b0722 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/Replacing.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/Replacing.html
    @@ -42,12 +42,12 @@ we can implement e.g. a function that adds new functions to the
     dictionary. However, there’s no function that does that. Adding a new
     function to the dictionary is a meta-interpreter action, you have to do
     it in Python, not Joy.

    -
    from notebook_preamble import D, J, V
    +
    from notebook_preamble import D, J, V
     

    A long trace¶

    -
    V('[23 18] average')
    +
    V('[23 18] average')
     
                                      . [23 18] average
    @@ -105,7 +105,7 @@ it in Python, not Joy.

    An efficient sum function is already in the library. But for size we can use a “compiled” version hand-written in Python to speed up evaluation and make the trace more readable.

    -
    from joy.library import SimpleFunctionWrapper
    +
    from joy.library import SimpleFunctionWrapper
     from joy.utils.stack import iter_stack
     
     
    @@ -121,14 +121,14 @@ up evaluation and make the trace more readable.

    Now we replace the old version in the dictionary with the new version, and re-evaluate the expression.

    -
    D['size'] = size
    +
    D['size'] = size
     

    A shorter trace¶

    You can see that size now executes in a single step.

    -
    V('[23 18] average')
    +
    V('[23 18] average')
     
                                      . [23 18] average
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Square_Spiral.html b/docs/sphinx_docs/_build/html/notebooks/Square_Spiral.html
    new file mode 100644
    index 0000000..474d0b8
    --- /dev/null
    +++ b/docs/sphinx_docs/_build/html/notebooks/Square_Spiral.html
    @@ -0,0 +1,463 @@
    +
    +
    +
    +
    +  
    +    
    +    
    +
    +    Square Spiral Example Joy Code — Thun 0.4.1 documentation
    +    
    +    
    +    
    +    
    +    
    +    
    +    
    +    
    +    
    +    
    +   
    +  
    +  
    +  
    +  
    +
    +  
    +  
    +
    +    
    +
    +
    + + +
    + +
    from notebook_preamble import J, V, define
    +
    +
    +
    +

    Square Spiral Example Joy Code¶

    +

    Here is the example of Joy code from the README file:

    +
    [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
    +
    +
    +

    It might seem unreadable but with a little familiarity it becomes just +as legible as any other notation. Some layout helps:

    +
    [   [[abs] ii <=]
    +    [
    +        [<>] [pop !-] ||
    +    ] &&
    +]
    +[[    !-] [[++]] [[--]] ifte dip]
    +[[pop !-]  [--]   [++]  ifte    ]
    +ifte
    +
    +
    +

    This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral).

    +
    +

    Original Form¶

    +

    It’s adapted from the original code on +StackOverflow:

    +
    +

    If all you’re trying to do is generate the first N points in the +spiral (without the original problem’s constraint of masking to an N +x M region), the code becomes very simple:

    +
    +
    void spiral(const int N)
    +{
    +    int x = 0;
    +    int y = 0;
    +    for(int i = 0; i < N; ++i)
    +    {
    +        cout << x << '\t' << y << '\n';
    +        if(abs(x) <= abs(y) && (x != y || x >= 0))
    +            x += ((y >= 0) ? 1 : -1);
    +        else
    +            y += ((x >= 0) ? -1 : 1);
    +    }
    +}
    +
    +
    +
    +
    +

    Translation to Joy¶

    +

    I’m going to make a function that take two ints (x and y) and +generates the next pair, we’ll turn it into a generator later using the +x combinator.

    +
    +

    First Boolean Predicate¶

    +

    We need a function that computes abs(x) <= abs(y), we can use ii +to apply abs to both values and then compare them with <=:

    +
    [abs] ii <=
    +
    +
    +

    I’ve defined two short-circuiting Boolean combinators && and || +that each accept two quoted predicate programs, run the first, and +conditionally run the second only if required (to compute the final +Boolean value). They run their predicate arguments nullary.

    +
    define('&& [nullary] cons [nullary [0]] dip branch')
    +define('|| [nullary] cons [nullary] dip [1] branch')
    +
    +
    +

    Given those, we can define x != y || x >= 0 as:

    +
    [<>] [pop 0 >=] ||
    +
    +
    +

    And (abs(x) <= abs(y) && (x != y || x >= 0)) as:

    +
    [[abs] ii <=] [[<>] [pop 0 >=] ||] &&
    +
    +
    +

    It’s a little rough, but, as I say, with a little familiarity it becomes +legible.

    +
    +
    +

    The Increment / Decrement Branches¶

    +

    Turning to the branches of the main if statement:

    +
    x += ((y >= 0) ? 1 : -1);
    +
    +
    +

    Rewrite as a hybrid (pseudo-code) ifte expression:

    +
    [y >= 0] [x += 1] [X -= 1] ifte
    +
    +
    +

    Change each C phrase to Joy code:

    +
    [0 >=] [[++] dip] [[--] dip] ifte
    +
    +
    +

    Factor out the dip from each branch:

    +
    [0 >=] [[++]] [[--]] ifte dip
    +
    +
    +

    Similar logic applies to the other branch:

    +
    y += ((x >= 0) ? -1 : 1);
    +
    +[x >= 0] [y -= 1] [y += 1] ifte
    +
    +[pop 0 >=] [--] [++] ifte
    +
    +
    +
    +
    +

    “Not Negative”¶

    +
    define('!- 0 >=')
    +
    +
    +
    +
    +
    +

    Putting the Pieces Together¶

    +

    We can assemble the three functions we just defined in quotes and give +them them to the ifte combinator. With some arrangement to show off +the symmetry of the two branches, we have:

    +
    [[[abs] ii <=] [[<>] [pop !-] ||] &&]
    +[[    !-] [[++]] [[--]] ifte dip]
    +[[pop !-]  [--]   [++]  ifte    ]
    +ifte
    +
    +
    +

    As I was writing this up I realized that, since the && combinator +doesn’t consume the stack (below its quoted args), I can unquote the +predicate, swap the branches, and use the branch combinator instead +of ifte:

    +
    [[abs] ii <=] [[<>] [pop !-] ||] &&
    +[[pop !-]  [--]   [++]  ifte    ]
    +[[    !-] [[++]] [[--]] ifte dip]
    +branch
    +
    +
    +
    define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte')
    +
    +
    +

    Let’s try it out:

    +
    J('0 0 spiral_next')
    +
    +
    +
    1 0
    +
    +
    +
    J('1 0 spiral_next')
    +
    +
    +
    1 -1
    +
    +
    +
    J('1 -1 spiral_next')
    +
    +
    +
    0 -1
    +
    +
    +
    J('0 -1 spiral_next')
    +
    +
    +
    -1 -1
    +
    +
    +
    +
    +

    Turning it into a Generator with x¶

    +

    It can be used with the x combinator to make a kind of generator for +spiral square coordinates.

    +

    We can use codireco to make a generator

    +
    codireco ::= cons dip rest cons
    +
    +
    +

    It will look like this:

    +
    [value [F] codireco]
    +
    +
    +

    Here’s a trace of how it works:

    +
               [0 [dup ++] codireco] . x
    +           [0 [dup ++] codireco] . 0 [dup ++] codireco
    +         [0 [dup ++] codireco] 0 . [dup ++] codireco
    +[0 [dup ++] codireco] 0 [dup ++] . codireco
    +[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
    +[0 [dup ++] codireco] [0 dup ++] . dip rest cons
    +                                 . 0 dup ++ [0 [dup ++] codireco] rest cons
    +                               0 . dup ++ [0 [dup ++] codireco] rest cons
    +                             0 0 . ++ [0 [dup ++] codireco] rest cons
    +                             0 1 . [0 [dup ++] codireco] rest cons
    +       0 1 [0 [dup ++] codireco] . rest cons
    +         0 1 [[dup ++] codireco] . cons
    +         0 [1 [dup ++] codireco] .
    +
    +
    +

    But first we have to change the spiral_next function to work on a +quoted pair of integers, and leave a copy of the pair on the stack. +From:

    +
       y x spiral_next
    +---------------------
    +        y' x'
    +
    +
    +

    to:

    +
       [x y] [spiral_next] infra
    +-------------------------------
    +           [x' y']
    +
    +
    +
    J('[0 0] [spiral_next] infra')
    +
    +
    +
    [0 1]
    +
    +
    +

    So our generator is:

    +
    [[x y] [dup [spiral_next] infra] codireco]
    +
    +
    +

    Or rather:

    +
    [[0 0] [dup [spiral_next] infra] codireco]
    +
    +
    +

    There is a function make_generator that will build the generator for +us out of the value and stepper function:

    +
       [0 0] [dup [spiral_next] infra] make_generator
    +----------------------------------------------------
    +     [[0 0] [dup [spiral_next] infra] codireco]
    +
    +
    +

    Here it is in action:

    +
    J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop')
    +
    +
    +
    [0 0] [0 1] [-1 1] [-1 0]
    +
    +
    +

    Four x combinators, four pairs of coordinates.

    +
    +
    +

    Conclusion¶

    +

    So that’s an example of Joy code. It’s a straightforward translation of +the original. It’s a little long for a single definition, you might +break it up like so:

    +
         _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&
    +
    +     _spn_T ::= [    !-] [[++]] [[--]] ifte dip
    +     _spn_E ::= [pop !-]  [--]   [++]  ifte
    +
    +spiral_next ::= _spn_P [_spn_E] [_spn_T] branch
    +
    +
    +

    This way it’s easy to see that the function is a branch with two +quasi-symmetrical paths.

    +

    We then used this function to make a simple generator of coordinate +pairs, where the next pair in the series can be generated at any time by +using the x combinator on the generator (which is just a quoted +expression containing a copy of the current pair and the “stepper +function” to generate the next pair from that.)

    +
    define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&')
    +define('_spn_T [!-] [[++]] [[--]] ifte dip')
    +define('_spn_E [pop !-] [--] [++] ifte')
    +define('spiral_next _spn_P [_spn_E] [_spn_T] branch')
    +
    +
    +
    V('23 18 spiral_next')
    +
    +
    +
                                                                   . 23 18 spiral_next
    +                                                            23 . 18 spiral_next
    +                                                         23 18 . spiral_next
    +                                                         23 18 . _spn_P [_spn_E] [_spn_T] branch
    +                                                         23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
    +                                           23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
    +                        23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch
    +                        23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
    +              23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
    +              23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch
    +23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch
    +                                           23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                           23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                   23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                   23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                         23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                 23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                   23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                         23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                   23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                   23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                             23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                   23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                            23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                            23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                         23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                   23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                         23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                         23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                         False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                 False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                 23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                                   23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                                               23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
    +                  23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch
    +                                                         23 18 . 0 [_spn_E] [_spn_T] branch
    +                                                       23 18 0 . [_spn_E] [_spn_T] branch
    +                                              23 18 0 [_spn_E] . [_spn_T] branch
    +                                     23 18 0 [_spn_E] [_spn_T] . branch
    +                                                         23 18 . _spn_E
    +                                                         23 18 . [pop !-] [--] [++] ifte
    +                                                23 18 [pop !-] . [--] [++] ifte
    +                                           23 18 [pop !-] [--] . [++] ifte
    +                                      23 18 [pop !-] [--] [++] . ifte
    +                                      23 18 [pop !-] [--] [++] . [nullary not] dipd branch
    +                        23 18 [pop !-] [--] [++] [nullary not] . dipd branch
    +                                                23 18 [pop !-] . nullary not [--] [++] branch
    +                                                23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch
    +                                        23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch
    +                                        23 18 [pop !-] [stack] . dip infra first not [--] [++] branch
    +                                                         23 18 . stack [pop !-] infra first not [--] [++] branch
    +                                                 23 18 [18 23] . [pop !-] infra first not [--] [++] branch
    +                                        23 18 [18 23] [pop !-] . infra first not [--] [++] branch
    +                                                         23 18 . pop !- [18 23] swaack first not [--] [++] branch
    +                                                            23 . !- [18 23] swaack first not [--] [++] branch
    +                                                            23 . 0 >= [18 23] swaack first not [--] [++] branch
    +                                                          23 0 . >= [18 23] swaack first not [--] [++] branch
    +                                                          True . [18 23] swaack first not [--] [++] branch
    +                                                  True [18 23] . swaack first not [--] [++] branch
    +                                                  23 18 [True] . first not [--] [++] branch
    +                                                    23 18 True . not [--] [++] branch
    +                                                   23 18 False . [--] [++] branch
    +                                              23 18 False [--] . [++] branch
    +                                         23 18 False [--] [++] . branch
    +                                                         23 18 . --
    +                                                         23 17 .
    +
    +
    +
    +
    + + +
    + +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/docs/sphinx_docs/_build/html/notebooks/Treestep.html b/docs/sphinx_docs/_build/html/notebooks/Treestep.html index 91fea34..7c01ae0 100644 --- a/docs/sphinx_docs/_build/html/notebooks/Treestep.html +++ b/docs/sphinx_docs/_build/html/notebooks/Treestep.html @@ -148,10 +148,10 @@ the desired outcome.

    Define treestep¶

    -
    from notebook_preamble import D, J, V, define, DefinitionWrapper
    +
    from notebook_preamble import D, J, V, define, DefinitionWrapper
     
    -
    DefinitionWrapper.add_definitions('''
    +
    DefinitionWrapper.add_definitions('''
     
         _treestep_0 == [[not] swap] dip
         _treestep_1 == [dip] cons [uncons] swoncat
    @@ -169,7 +169,7 @@ all nodes in a tree with this function:

    sumtree == [pop 0] [] [sum +] treestep
     
    -
    define('sumtree == [pop 0] [] [sum +] treestep')
    +
    define('sumtree == [pop 0] [] [sum +] treestep')
     

    Running this function on an empty tree value gives zero:

    @@ -178,7 +178,7 @@ all nodes in a tree with this function:

    0
    -
    J('[] sumtree')  # Empty tree.
    +
    J('[] sumtree')  # Empty tree.
     
    0
    @@ -192,61 +192,61 @@ all nodes in a tree with this function:

    n+m
    -
    J('[23] sumtree')  # No child trees.
    +
    J('[23] sumtree')  # No child trees.
     
    23
     
    -
    J('[23 []] sumtree')  # Child tree, empty.
    +
    J('[23 []] sumtree')  # Child tree, empty.
     
    23
     
    -
    J('[23 [2 [4]] [3]] sumtree')  # Non-empty child trees.
    +
    J('[23 [2 [4]] [3]] sumtree')  # Non-empty child trees.
     
    32
     
    -
    J('[23 [2 [8] [9]] [3] [4 []]] sumtree')  # Etc...
    +
    J('[23 [2 [8] [9]] [3] [4 []]] sumtree')  # Etc...
     
    49
     
    -
    J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep')  # Alternate "spelling".
    +
    J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep')  # Alternate "spelling".
     
    49
     
    -
    J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep')  # Replace each node.
    +
    J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep')  # Replace each node.
     
    [23 [23 [23] [23]] [23] [23 []]]
     
    -
    J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
    +
    J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
     
    [1 [1 [1] [1]] [1] [1 []]]
     
    -
    J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
    +
    J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
     
    6
     
    -
    J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep')  # Combine replace and sum into one function.
    +
    J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep')  # Combine replace and sum into one function.
     
    6
     
    -
    J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep')  # Combine replace and sum into one function.
    +
    J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep')  # Combine replace and sum into one function.
     
    3
    @@ -277,7 +277,7 @@ all nodes in a tree with this function:

    This doesn’t quite work:

    -
    J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
    +
    J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
     
    3 'B' 'B'
    @@ -299,7 +299,7 @@ depositing our results directly on the stack.

    [] [first] [flatten cons] treestep
     
    -
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [first] [flatten cons] treestep')
    +
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [first] [flatten cons] treestep')
     
    [3 2 9 5 4 8 6 7]
    @@ -322,7 +322,7 @@ depositing our results directly on the stack.

    [] [i roll< swons concat] [first] treestep
     
    -
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [uncons pop] [i roll< swons concat] treestep')
    +
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [uncons pop] [i roll< swons concat] treestep')
     
    [2 3 4 5 6 7 8 9]
    @@ -343,7 +343,7 @@ non-empty node is:

    [key value] N [left right] [K] C
     
    -
    J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
    +
    J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
     
    ['key' 'value'] 'N' [['left'] ['right']] [[not] ['B'] [uncons ['N'] dip] ['C'] genrec] 'C'
    @@ -353,21 +353,21 @@ non-empty node is:

    treegrind with step¶

    Iteration through the nodes

    -
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [pop] ["N"] [step] treegrind')
    +
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [pop] ["N"] [step] treegrind')
     
    [3 0] 'N' [2 0] 'N' [9 0] 'N' [5 0] 'N' [4 0] 'N' [8 0] 'N' [6 0] 'N' [7 0] 'N'
     

    Sum the nodes’ keys.

    -
    J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [pop] [first +] [step] treegrind')
    +
    J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [pop] [first +] [step] treegrind')
     
    44
     

    Rebuild the tree using map (imitating treestep.)

    -
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [[100 +] infra] [map cons] treegrind')
    +
    J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [[100 +] infra] [map cons] treegrind')
     
    [[103 0] [[102 0] [] []] [[109 0] [[105 0] [[104 0] [] []] [[108 0] [[106 0] [] [[107 0] [] []]] []]] []]]
    @@ -449,7 +449,7 @@ equal):

    To me, that seems simpler than the genrec version.

    -
    DefinitionWrapper.add_definitions('''
    +
    DefinitionWrapper.add_definitions('''
     
         T> == pop [first] dip i
         T< == pop [second] dip i
    @@ -461,7 +461,7 @@ equal):

    ''', D)
    -
    J('''\
    +
    J('''\
     
     [[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
     
    @@ -473,7 +473,7 @@ equal):

    15
     
    -
    J('''\
    +
    J('''\
     
     [[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
     
    diff --git a/docs/sphinx_docs/_build/html/notebooks/TypeChecking.html b/docs/sphinx_docs/_build/html/notebooks/TypeChecking.html
    index 6e5002d..5f201ce 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/TypeChecking.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/TypeChecking.html
    @@ -35,7 +35,7 @@
                 
       

    Type Checking¶

    -
    import logging, sys
    +
    import logging, sys
     
     logging.basicConfig(
       format='%(message)s',
    @@ -44,7 +44,7 @@
       )
     
    -
    from joy.utils.types import (
    +
    from joy.utils.types import (
         doc_from_stack_effect,
         infer,
         reify,
    @@ -54,14 +54,14 @@
     )
     
    -
    D = FUNCTIONS.copy()
    +
    D = FUNCTIONS.copy()
     del D['product']
     globals().update(D)
     

    An Example¶

    -
    fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
    +
    fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
     
    25 (--) ∘ pop swap rolldown rrest ccons
    @@ -72,31 +72,31 @@
     40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
     
    -
    print doc_from_stack_effect(fi, fo)
    +
    print doc_from_stack_effect(fi, fo)
     
    ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
     
    -
    from joy.parser import text_to_expression
    +
    from joy.parser import text_to_expression
     from joy.utils.stack import stack_to_string
     
    -
    e = text_to_expression('0 1 2 [3 4]')  # reverse order
    +
    e = text_to_expression('0 1 2 [3 4]')  # reverse order
     print stack_to_string(e)
     
    [3 4] 2 1 0
     
    -
    u = unify(e, fi)[0]
    +
    u = unify(e, fi)[0]
     u
     
    {a1: 0, a2: 1, a3: 2, a4: 3, a5: 4, s2: (), s1: ()}
     
    -
    g = reify(u, (fi, fo))
    +
    g = reify(u, (fi, fo))
     print doc_from_stack_effect(*g)
     
    @@ -106,17 +106,17 @@

    Unification Works “in Reverse”¶

    -
    e = text_to_expression('[2 3]')
    +
    e = text_to_expression('[2 3]')
     
    -
    u = unify(e, fo)[0]  # output side, not input side
    +
    u = unify(e, fo)[0]  # output side, not input side
     u
     
    {a2: 2, a3: 3, s2: (), s1: ()}
     
    -
    g = reify(u, (fi, fo))
    +
    g = reify(u, (fi, fo))
     print doc_from_stack_effect(*g)
     
    @@ -126,7 +126,7 @@

    Failing a Check¶

    -
    fi, fo = infer(dup, mul)[0]
    +
    fi, fo = infer(dup, mul)[0]
     
    25 (--) ∘ dup mul
    @@ -135,14 +135,14 @@
     31 (i1 -- i2) ∘
     
    -
    e = text_to_expression('"two"')
    +
    e = text_to_expression('"two"')
     print stack_to_string(e)
     
    'two'
     
    -
    try:
    +
    try:
         unify(e, fi)
     except JoyTypeError, err:
         print err
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Types.html b/docs/sphinx_docs/_build/html/notebooks/Types.html
    index 92d9131..e8b8ab9 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/Types.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/Types.html
    @@ -182,7 +182,7 @@ terms in the forms:

    Compiling pop∘swap∘roll<¶

    The simplest way to “compile” this function would be something like:

    -
    def poswrd(s, e, d):
    +
    def poswrd(s, e, d):
         return rolldown(*swap(*pop(s, e, d)))
     
    @@ -193,7 +193,7 @@ terms in the forms:

    We should be able to directly write out a Python function like:

    -
    def poswrd(stack):
    +
    def poswrd(stack):
         (_, (a, (b, (c, stack)))) = stack
         return (c, (b, (a, stack)))
     
    @@ -335,7 +335,7 @@ actually pretty easy. I’ll explain below.

    From this stack effect comment it should be possible to construct the following Python code:

    -
    def F(stack):
    +
    def F(stack):
         (_, (d, (c, ((a, (b, S0)), stack)))) = stack
         return (d, (c, S0)), stack
     
    @@ -348,7 +348,7 @@ following Python code:

    Representing Stack Effect Comments in Python¶

    I’m going to use pairs of tuples of type descriptors, which will be integers or tuples of type descriptors:

    -
    roll_dn = (1, 2, 3), (2, 3, 1)
    +
    roll_dn = (1, 2, 3), (2, 3, 1)
     
     pop = (1,), ()
     
    @@ -358,7 +358,7 @@ integers or tuples of type descriptors:

    compose()¶

    -
    def compose(f, g):
    +
    def compose(f, g):
     
         (f_in, f_out), (g_in, g_out) = f, g
     
    @@ -403,7 +403,7 @@ integers or tuples of type descriptors:

    unify()¶

    -
    def unify(u, v, s=None):
    +
    def unify(u, v, s=None):
         if s is None:
             s = {}
     
    @@ -420,7 +420,7 @@ integers or tuples of type descriptors:

    update()¶

    -
    def update(s, term):
    +
    def update(s, term):
         if not isinstance(term, tuple):
             return s.get(term, term)
         return tuple(update(s, inner) for inner in term)
    @@ -429,7 +429,7 @@ integers or tuples of type descriptors:

    relabel()¶

    -
    def relabel(left, right):
    +
    def relabel(left, right):
         return left, _1000(right)
     
     def _1000(right):
    @@ -446,7 +446,7 @@ integers or tuples of type descriptors:

    delabel()¶

    -
    def delabel(f):
    +
    def delabel(f):
         s = {u: i for i, u in enumerate(sorted(_unique(f)))}
         return update(s, f)
     
    @@ -472,38 +472,38 @@ integers or tuples of type descriptors:

    At last we put it all together in a function C() that accepts two stack effect comments and returns their composition (or raises and exception if they can’t be composed due to type conflicts.)

    -
    def C(f, g):
    +
    def C(f, g):
         f, g = relabel(f, g)
         fg = compose(f, g)
         return delabel(fg)
     

    Let’s try it out.

    -
    C(pop, swap)
    +
    C(pop, swap)
     
    ((1, 2, 0), (2, 1))
     
    -
    C(C(pop, swap), roll_dn)
    +
    C(C(pop, swap), roll_dn)
     
    ((3, 1, 2, 0), (2, 1, 3))
     
    -
    C(swap, roll_dn)
    +
    C(swap, roll_dn)
     
    ((2, 0, 1), (1, 0, 2))
     
    -
    C(pop, C(swap, roll_dn))
    +
    C(pop, C(swap, roll_dn))
     
    ((3, 1, 2, 0), (2, 1, 3))
     
    -
    poswrd = reduce(C, (pop, swap, roll_dn))
    +
    poswrd = reduce(C, (pop, swap, roll_dn))
     poswrd
     
    @@ -516,12 +516,12 @@ exception if they can’t be composed due to type conflicts.)

    Here’s that trick to represent functions like rest and cons that manipulate stacks. We use a cons-list of tuples and give the tails their own numbers. Then everything above already works.

    -
    rest = ((1, 2),), (2,)
    +
    rest = ((1, 2),), (2,)
     
     cons = (1, 2), ((1, 2),)
     
    -
    C(poswrd, rest)
    +
    C(poswrd, rest)
     
    (((3, 4), 1, 2, 0), (2, 1, 4))
    @@ -542,7 +542,7 @@ own numbers. Then everything above already works.

    }
    -
    F = reduce(C, (pop, swap, roll_dn, rest, rest, cons, cons))
    +
    F = reduce(C, (pop, swap, roll_dn, rest, rest, cons, cons))
     
     F
     
    @@ -560,10 +560,10 @@ own numbers. Then everything above already works.

    Dealing with cons and uncons¶

    However, if we try to compose e.g. cons and uncons it won’t work:

    -
    uncons = ((1, 2),), (1, 2)
    +
    uncons = ((1, 2),), (1, 2)
     
    -
    try:
    +
    try:
         C(cons, uncons)
     except Exception, e:
         print e
    @@ -577,7 +577,7 @@ work:

    The problem is that the unify() function as written doesn’t handle the case when both terms are tuples. We just have to add a clause to deal with this recursively:

    -
    def unify(u, v, s=None):
    +
    def unify(u, v, s=None):
         if s is None:
             s = {}
         elif s:
    @@ -606,7 +606,7 @@ deal with this recursively:

    return s
    -
    C(cons, uncons)
    +
    C(cons, uncons)
     
    ((0, 1), (0, 1))
    @@ -618,13 +618,13 @@ deal with this recursively:

    Part III: Compiling Yin Functions¶

    Now consider the Python function we would like to derive:

    -
    def F_python(stack):
    +
    def F_python(stack):
         (_, (d, (c, ((a, (b, S0)), stack)))) = stack
         return (d, (c, S0)), stack
     

    And compare it to the input stack effect comment tuple we just computed:

    -
    F[0]
    +
    F[0]
     
    ((3, (4, 5)), 1, 2, 0)
    @@ -646,7 +646,7 @@ stack effect comment tuple, just in the reverse order:

    Eh?

    And the return tuple

    -
    F[1]
    +
    F[1]
     
    ((2, (1, 5)),)
    @@ -666,7 +666,7 @@ effect.)

    Python Identifiers¶

    We want to substitute Python identifiers for the integers. I’m going to repurpose joy.parser.Symbol class for this:

    -
    from collections import defaultdict
    +
    from collections import defaultdict
     from joy.parser import Symbol
     
     
    @@ -690,7 +690,7 @@ repurpose joy.parse
     effect comment tuples to reasonable text format. There are some details
     in how this code works that related to stuff later in the notebook, so
     you should skip it for now and read it later if you’re interested.

    -
    def doc_from_stack_effect(inputs, outputs):
    +
    def doc_from_stack_effect(inputs, outputs):
         return '(%s--%s)' % (
             ' '.join(map(_to_str, inputs + ('',))),
             ' '.join(map(_to_str, ('',) + outputs))
    @@ -728,7 +728,7 @@ you should skip it for now and read it later if you’re interested.

    Now we can write a compiler function to emit Python source code. (The underscore suffix distiguishes it from the built-in compile() function.)

    -
    def compile_(name, f, doc=None):
    +
    def compile_(name, f, doc=None):
         if doc is None:
             doc = doc_from_stack_effect(*f)
         inputs, outputs = identifiers(f)
    @@ -744,7 +744,7 @@ function.)

    Here it is in action:

    -
    source = compile_('F', F)
    +
    source = compile_('F', F)
     
     print source
     
    @@ -756,13 +756,13 @@ function.)

    Compare:

    -
    def F_python(stack):
    +
    def F_python(stack):
         (_, (d, (c, ((a, (b, S0)), stack)))) = stack
         return ((d, (c, S0)), stack)
     

    Next steps:

    -
    L = {}
    +
    L = {}
     
     eval(compile(source, '__main__', 'single'), {}, L)
     
    @@ -773,14 +773,14 @@ function.)

    Let’s try it out:

    -
    from notebook_preamble import D, J, V
    +
    from notebook_preamble import D, J, V
     from joy.library import SimpleFunctionWrapper
     
    -
    D['F'] = SimpleFunctionWrapper(L['F'])
    +
    D['F'] = SimpleFunctionWrapper(L['F'])
     
    -
    J('[4 5 ...] 2 3 1 F')
    +
    J('[4 5 ...] 2 3 1 F')
     
    [3 2 ...]
    @@ -800,7 +800,7 @@ this might be less helpful.

    Compiling Library Functions¶

    We can use compile_() to generate many primitives in the library from their stack effect comments:

    -
    def defs():
    +
    def defs():
     
         rolldown = (1, 2, 3), (2, 3, 1)
     
    @@ -823,7 +823,7 @@ from their stack effect comments:

    return locals()
    -
    for name, stack_effect_comment in sorted(defs().items()):
    +
    for name, stack_effect_comment in sorted(defs().items()):
         print
         print compile_(name, stack_effect_comment)
         print
    @@ -966,7 +966,7 @@ and t
     Python class hierarchy of Joy types and use the issubclass() method
     to establish domain ordering, as well as other handy behaviour that will
     make it fairly easy to reuse most of the code above.

    -
    class AnyJoyType(object):
    +
    class AnyJoyType(object):
     
         prefix = 'a'
     
    @@ -1010,12 +1010,12 @@ make it fairly easy to reuse most of the code above.

    Mess with it a little:

    -
    from itertools import permutations
    +
    from itertools import permutations
     

    “Any” types can be specialized to numbers and stacks, but not vice versa:

    -
    for a, b in permutations((A[0], N[0], S[0]), 2):
    +
    for a, b in permutations((A[0], N[0], S[0]), 2):
         print a, '>=', b, '->', a >= b
     
    @@ -1030,7 +1030,7 @@ versa:

    Our crude Numerical Tower of numbers > floats > integers works as well (but we’re not going to use it yet):

    -
    for a, b in permutations((A[0], N[0], FloatJoyType(0), IntJoyType(0)), 2):
    +
    for a, b in permutations((A[0], N[0], FloatJoyType(0), IntJoyType(0)), 2):
         print a, '>=', b, '->', a >= b
     
    @@ -1051,18 +1051,18 @@ Tower of numbers >

    Typing sqr¶

    -
    dup = (A[1],), (A[1], A[1])
    +
    dup = (A[1],), (A[1], A[1])
     
     mul = (N[1], N[2]), (N[3],)
     
    -
    dup
    +
    dup
     
    ((a1,), (a1, a1))
     
    -
    mul
    +
    mul
     
    ((n1, n2), (n3,))
    @@ -1072,7 +1072,7 @@ Tower of numbers >
     

    Modifying the Inferencer¶

    Re-labeling still works fine:

    -
    foo = relabel(dup, mul)
    +
    foo = relabel(dup, mul)
     
     foo
     
    @@ -1084,7 +1084,7 @@ Tower of numbers >

    delabel() version 2¶

    The delabel() function needs an overhaul. It now has to keep track of how many labels of each domain it has “seen”.

    -
    from collections import Counter
    +
    from collections import Counter
     
     
     def delabel(f, seen=None, c=None):
    @@ -1105,7 +1105,7 @@ of how many labels of each domain it has “seen”.

    return tuple(delabel(inner, seen, c) for inner in f)
    -
    delabel(foo)
    +
    delabel(foo)
     
    (((a1,), (a1, a1)), ((n1, n2), (n3,)))
    @@ -1114,7 +1114,7 @@ of how many labels of each domain it has “seen”.

    unify() version 3¶

    -
    def unify(u, v, s=None):
    +
    def unify(u, v, s=None):
         if s is None:
             s = {}
         elif s:
    @@ -1162,7 +1162,7 @@ of how many labels of each domain it has “seen”.

    Rewrite the stack effect comments:

    -
    def defs():
    +
    def defs():
     
         rolldown = (A[1], A[2], A[3]), (A[2], A[3], A[1])
     
    @@ -1215,10 +1215,10 @@ of how many labels of each domain it has “seen”.

    return locals()
    -
    DEFS = defs()
    +
    DEFS = defs()
     
    -
    for name, stack_effect_comment in sorted(DEFS.items()):
    +
    for name, stack_effect_comment in sorted(DEFS.items()):
         print name, '=', doc_from_stack_effect(*stack_effect_comment)
     
    @@ -1250,27 +1250,27 @@ of how many labels of each domain it has “seen”.

    uncons = ([a1 .1.] -- a1 [.1.])
    -
    globals().update(DEFS)
    +
    globals().update(DEFS)
     

    Compose dup and mul¶

    -
    C(dup, mul)
    +
    C(dup, mul)
     
    ((n1,), (n2,))
     

    Revisit the F function, works fine.

    -
    F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
    +
    F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
     F
     
    (((a1, (a2, s1)), a3, a4, a5), ((a4, (a3, s1)),))
     
    -
    print doc_from_stack_effect(*F)
    +
    print doc_from_stack_effect(*F)
     
    ([a1 a2 .1.] a3 a4 a5 -- [a4 a3 .1.])
    @@ -1278,25 +1278,25 @@ of how many labels of each domain it has “seen”.

    Some otherwise inefficient functions are no longer to be feared. We can also get the effect of combinators in some limited cases.

    -
    def neato(*funcs):
    +
    def neato(*funcs):
         print doc_from_stack_effect(*reduce(C, funcs))
     
    -
    # e.g. [swap] dip
    +
    # e.g. [swap] dip
     neato(rollup, swap, rolldown)
     
    (a1 a2 a3 -- a2 a1 a3)
     
    -
    # e.g. [popop] dipd
    +
    # e.g. [popop] dipd
     neato(popdd, rolldown, pop)
     
    (a1 a2 a3 a4 -- a3 a4)
     
    -
    # Reverse the order of the top three items.
    +
    # Reverse the order of the top three items.
     neato(rollup, swap)
     
    @@ -1308,7 +1308,7 @@ also get the effect of combinators in some limited cases.

    compile_() version 2¶

    Because the type labels represent themselves as valid Python identifiers the compile_() function doesn’t need to generate them anymore:

    -
    def compile_(name, f, doc=None):
    +
    def compile_(name, f, doc=None):
         inputs, outputs = f
         if doc is None:
             doc = doc_from_stack_effect(inputs, outputs)
    @@ -1323,7 +1323,7 @@ the compile_()    return %s''' % (name, doc, i, o)
     
    -
    print compile_('F', F)
    +
    print compile_('F', F)
     
    def F(stack):
    @@ -1334,7 +1334,7 @@ the compile_()
     

    But it cannot magically create new functions that involve e.g. math and such. Note that this is not a sqr function implementation:

    -
    print compile_('sqr', C(dup, mul))
    +
    print compile_('sqr', C(dup, mul))
     
    def sqr(stack):
    @@ -1356,14 +1356,14 @@ functions (at least) are already wrappers it should be straightforward.)

    The functions that can be compiled are the ones that have only AnyJoyType and StackJoyType labels in their stack effect comments. We can write a function to check that:

    -
    from itertools import imap
    +
    from itertools import imap
     
     
     def compilable(f):
         return isinstance(f, tuple) and all(imap(compilable, f)) or stacky(f)
     
    -
    for name, stack_effect_comment in sorted(defs().items()):
    +
    for name, stack_effect_comment in sorted(defs().items()):
         if compilable(stack_effect_comment):
             print name, '=', doc_from_stack_effect(*stack_effect_comment)
     
    @@ -1465,7 +1465,7 @@ first two rules’ the “truthiness” of StackJoyType to false to let e.g. joy.utils.stack.concat work with our stack effect comment cons-list tuples.)

    -
    def compose(f, g):
    +
    def compose(f, g):
         (f_in, f_out), (g_in, g_out) = f, g
         s = unify(g_in, f_out)
         if s == False:  # s can also be the empty dict, which is ok.
    @@ -1475,7 +1475,7 @@ tuples.)

    I don’t want to rewrite all the defs myself, so I’ll write a little conversion function instead. This is programmer’s laziness.

    -
    def sequence_to_stack(seq, stack=StackJoyType(23)):
    +
    def sequence_to_stack(seq, stack=StackJoyType(23)):
         for item in seq: stack = item, stack
         return stack
     
    @@ -1488,13 +1488,13 @@ conversion function instead. This is programmer’s laziness.

    globals().update(NEW_DEFS)
    -
    C(stack, uncons)
    +
    C(stack, uncons)
     
    ((a1, s1), (s1, (a1, (a1, s1))))
     
    -
    reduce(C, (stack, uncons, uncons))
    +
    reduce(C, (stack, uncons, uncons))
     
    ((a1, (a2, s1)), (s1, (a2, (a1, (a1, (a2, s1))))))
    @@ -1506,7 +1506,7 @@ conversion function instead. This is programmer’s laziness.

    doc_from_stack_effect() version 2¶

    Clunky junk, but it will suffice for now.

    -
    def doc_from_stack_effect(inputs, outputs):
    +
    def doc_from_stack_effect(inputs, outputs):
         switch = [False]  # Do we need to display the '...' for the rest of the main stack?
         i, o = _f(inputs, switch), _f(outputs, switch)
         if switch[0]:
    @@ -1553,7 +1553,7 @@ conversion function instead. This is programmer’s laziness.

    return '[%s]' % ' '.join(a)
    -
    for name, stack_effect_comment in sorted(NEW_DEFS.items()):
    +
    for name, stack_effect_comment in sorted(NEW_DEFS.items()):
         print name, '=', doc_from_stack_effect(*stack_effect_comment)
     
    @@ -1587,7 +1587,7 @@ conversion function instead. This is programmer’s laziness.

    uncons = ([a1 .1.] -- a1 [.1.])
    -
    print ; print doc_from_stack_effect(*stack)
    +
    print ; print doc_from_stack_effect(*stack)
     print ; print doc_from_stack_effect(*C(stack, uncons))
     print ; print doc_from_stack_effect(*reduce(C, (stack, uncons, uncons)))
     print ; print doc_from_stack_effect(*reduce(C, (stack, uncons, cons)))
    @@ -1602,13 +1602,13 @@ conversion function instead. This is programmer’s laziness.

    (... a1 -- ... a1 [a1 ...])
    -
    print doc_from_stack_effect(*C(ccons, stack))
    +
    print doc_from_stack_effect(*C(ccons, stack))
     
    (... a2 a1 [.1.] -- ... [a2 a1 .1.] [[a2 a1 .1.] ...])
     
    -
    Q = C(ccons, stack)
    +
    Q = C(ccons, stack)
     
     Q
     
    @@ -1620,7 +1620,7 @@ conversion function instead. This is programmer’s laziness.

    compile_() version 3¶

    This makes the compile_() function pretty simple as the stack effect comments are now already in the form needed for the Python code:

    -
    def compile_(name, f, doc=None):
    +
    def compile_(name, f, doc=None):
         i, o = f
         if doc is None:
             doc = doc_from_stack_effect(i, o)
    @@ -1630,7 +1630,7 @@ comments are now already in the form needed for the Python code:

    return %s''' % (name, doc, i, o)
    -
    print compile_('Q', Q)
    +
    print compile_('Q', Q)
     
    def Q(stack):
    @@ -1639,35 +1639,35 @@ comments are now already in the form needed for the Python code:

    return (((a2, (a1, s1)), s2), ((a2, (a1, s1)), s2))
    -
    unstack = (S[1], S[0]), S[1]
    +
    unstack = (S[1], S[0]), S[1]
     enstacken = S[0], (S[0], S[1])
     
    -
    print doc_from_stack_effect(*unstack)
    +
    print doc_from_stack_effect(*unstack)
     
    ([.1.] --)
     
    -
    print doc_from_stack_effect(*enstacken)
    +
    print doc_from_stack_effect(*enstacken)
     
    (-- [.0.])
     
    -
    print doc_from_stack_effect(*C(cons, unstack))
    +
    print doc_from_stack_effect(*C(cons, unstack))
     
    (a1 [.1.] -- a1)
     
    -
    print doc_from_stack_effect(*C(cons, enstacken))
    +
    print doc_from_stack_effect(*C(cons, enstacken))
     
    (a1 [.1.] -- [[a1 .1.] .2.])
     
    -
    C(cons, unstack)
    +
    C(cons, unstack)
     
    ((s1, (a1, s2)), (a1, s1))
    @@ -1679,14 +1679,14 @@ comments are now already in the form needed for the Python code:

    Part VI: Multiple Stack Effects¶

    …

    -
    class IntJoyType(NumberJoyType): prefix = 'i'
    +
    class IntJoyType(NumberJoyType): prefix = 'i'
     
     
     F = map(FloatJoyType, _R)
     I = map(IntJoyType, _R)
     
    -
    muls = [
    +
    muls = [
          ((I[2], (I[1], S[0])), (I[3], S[0])),
          ((F[2], (I[1], S[0])), (F[3], S[0])),
          ((I[2], (F[1], S[0])), (F[3], S[0])),
    @@ -1694,7 +1694,7 @@ comments are now already in the form needed for the Python code:

    ]
    -
    for f in muls:
    +
    for f in muls:
         print doc_from_stack_effect(*f)
     
    @@ -1704,7 +1704,7 @@ comments are now already in the form needed for the Python code:

    (f1 f2 -- f3)
    -
    for f in muls:
    +
    for f in muls:
         try:
             e = C(dup, f)
         except TypeError:
    @@ -1716,7 +1716,7 @@ comments are now already in the form needed for the Python code:

    (a1 -- a1 a1) (f1 f2 -- f3) (f1 -- f2)
    -
    from itertools import product
    +
    from itertools import product
     
     
     def meta_compose(F, G):
    @@ -1731,14 +1731,14 @@ comments are now already in the form needed for the Python code:

    return sorted(set(meta_compose(F, G)))
    -
    for f in MC([dup], [mul]):
    +
    for f in MC([dup], [mul]):
         print doc_from_stack_effect(*f)
     
    (n1 -- n2)
     
    -
    for f in MC([dup], muls):
    +
    for f in MC([dup], muls):
         print doc_from_stack_effect(*f)
     
    @@ -1793,7 +1793,7 @@ disappears:

    {c: a, d: e, .1.: A* b .0.}
    -
    class KleeneStar(object):
    +
    class KleeneStar(object):
     
         kind = AnyJoyType
     
    @@ -1840,7 +1840,7 @@ disappears:

    unify() version 4¶

    Can now return multiple results…

    -
    def unify(u, v, s=None):
    +
    def unify(u, v, s=None):
         if s is None:
             s = {}
         elif s:
    @@ -1911,21 +1911,21 @@ disappears:

    return thing.__class__ in {AnyJoyType, StackJoyType}
    -
    a = (As[1], S[1])
    +
    a = (As[1], S[1])
     a
     
    (a1*, s1)
     
    -
    b = (A[1], S[2])
    +
    b = (A[1], S[2])
     b
     
    (a1, s2)
     
    -
    for result in unify(b, a):
    +
    for result in unify(b, a):
         print result, '->', update(result, a), update(result, b)
     
    @@ -1933,7 +1933,7 @@ disappears:

    {a1: a10001, s2: (a1*, s1)} -> (a1*, s1) (a10001, (a1*, s1))
    -
    for result in unify(a, b):
    +
    for result in unify(a, b):
         print result, '->', update(result, a), update(result, b)
     
    @@ -1948,7 +1948,7 @@ disappears:

    (a1*, s1) [a1*] (a2, (a1*, s1)) [a2 a1*]
    -
    sum_ = ((Ns[1], S[1]), S[0]), (N[0], S[0])
    +
    sum_ = ((Ns[1], S[1]), S[0]), (N[0], S[0])
     
     print doc_from_stack_effect(*sum_)
     
    @@ -1956,7 +1956,7 @@ disappears:

    ([n1* .1.] -- n0)
     
    -
    f = (N[1], (N[2], (N[3], S[1]))), S[0]
    +
    f = (N[1], (N[2], (N[3], S[1]))), S[0]
     
     print doc_from_stack_effect(S[0], f)
     
    @@ -1964,7 +1964,7 @@ disappears:

    (-- [n1 n2 n3 .1.])
     
    -
    for result in unify(sum_[0], f):
    +
    for result in unify(sum_[0], f):
         print result, '->', update(result, sum_[1])
     
    @@ -1978,7 +1978,7 @@ disappears:

    compose() version 3¶

    This function has to be modified to yield multiple results.

    -
    def compose(f, g):
    +
    def compose(f, g):
         (f_in, f_out), (g_in, g_out) = f, g
         s = unify(g_in, f_out)
         if not s:
    @@ -1987,7 +1987,7 @@ disappears:

    yield update(result, (f_in, g_out))
    -
    def meta_compose(F, G):
    +
    def meta_compose(F, G):
         for f, g in product(F, G):
             try:
                 for result in C(f, g):
    @@ -2002,7 +2002,7 @@ disappears:

    yield delabel(fg)
    -
    for f in MC([dup], muls):
    +
    for f in MC([dup], muls):
         print doc_from_stack_effect(*f)
     
    @@ -2010,14 +2010,14 @@ disappears:

    (i1 -- i2)
    -
    for f in MC([dup], [sum_]):
    +
    for f in MC([dup], [sum_]):
         print doc_from_stack_effect(*f)
     
    ([n1* .1.] -- [n1* .1.] n1)
     
    -
    for f in MC([cons], [sum_]):
    +
    for f in MC([cons], [sum_]):
         print doc_from_stack_effect(*f)
     
    @@ -2025,7 +2025,7 @@ disappears:

    (n1 [n1* .1.] -- n2)
    -
    sum_ = (((N[1], (Ns[1], S[1])), S[0]), (N[0], S[0]))
    +
    sum_ = (((N[1], (Ns[1], S[1])), S[0]), (N[0], S[0]))
     print doc_from_stack_effect(*cons),
     print doc_from_stack_effect(*sum_),
     
    @@ -2036,21 +2036,21 @@ disappears:

    (a1 [.1.] -- [a1 .1.]) ([n1 n1* .1.] -- n0) (n1 [n1* .1.] -- n2)
     
    -
    a = (A[4], (As[1], (A[3], S[1])))
    +
    a = (A[4], (As[1], (A[3], S[1])))
     a
     
    (a4, (a1*, (a3, s1)))
     
    -
    b = (A[1], (A[2], S[2]))
    +
    b = (A[1], (A[2], S[2]))
     b
     
    (a1, (a2, s2))
     
    -
    for result in unify(b, a):
    +
    for result in unify(b, a):
         print result
     
    @@ -2058,7 +2058,7 @@ disappears:

    {a1: a4, s2: (a1*, (a3, s1)), a2: a10003}
    -
    for result in unify(a, b):
    +
    for result in unify(a, b):
         print result
     
    @@ -2111,7 +2111,7 @@ stack effect we have to “split universes” again and return both.

    We need a type variable for Joy functions that can go in our expressions and be used by the hybrid inferencer/interpreter. They have to store a name and a list of stack effects.

    -
    class FunctionJoyType(AnyJoyType):
    +
    class FunctionJoyType(AnyJoyType):
     
         def __init__(self, name, sec, number):
             self.name = name
    @@ -2131,12 +2131,12 @@ name and a list of stack effects.

    Specialized for Simple Functions and Combinators¶

    For non-combinator functions the stack effects list contains stack effect comments (represented by pairs of cons-lists as described above.)

    -
    class SymbolJoyType(FunctionJoyType):
    +
    class SymbolJoyType(FunctionJoyType):
         prefix = 'F'
     

    For combinators the list contains Python functions.

    -
    class CombinatorJoyType(FunctionJoyType):
    +
    class CombinatorJoyType(FunctionJoyType):
     
         prefix = 'C'
     
    @@ -2155,7 +2155,7 @@ effect comments (represented by pairs of cons-lists as described above.)

    For simple combinators that have only one effect (like dip) you only need one function and it can be the combinator itself.

    -
    import joy.library
    +
    import joy.library
     
     dip = CombinatorJoyType('dip', [joy.library.dip], 23)
     
    @@ -2163,7 +2163,7 @@ need one function and it can be the combinator itself.

    For combinators that can have more than one effect (like branch) you have to write functions that each implement the action of one of the effects.

    -
    def branch_true(stack, expression, dictionary):
    +
    def branch_true(stack, expression, dictionary):
         (then, (else_, (flag, stack))) = stack
         return stack, concat(then, expression), dictionary
     
    @@ -2189,7 +2189,7 @@ that expression.

    updated along with the stack effects after doing unification or we risk losing useful information. This was a straightforward, if awkward, modification to the call structure of meta_compose() et. al.

    -
    ID = S[0], S[0]  # Identity function.
    +
    ID = S[0], S[0]  # Identity function.
     
     
     def infer(*expression):
    @@ -2249,7 +2249,7 @@ module (FIXME link to its docs here!) should be explained… There is
     cruft to convert the definitions in DEFS to the new
     SymbolJoyType objects, and some combinators. Here is an example of
     output from the current code :

    -
    1/0  # (Don't try to run this cell!  It's not going to work.  This is "read only" code heh..)
    +
    1/0  # (Don't try to run this cell!  It's not going to work.  This is "read only" code heh..)
     
     logging.basicConfig(format='%(message)s', stream=sys.stdout, level=logging.INFO)
     
    @@ -2366,7 +2366,7 @@ relational nature of the stack effect comments to “compute in reverse”
     as it were. There’s a working demo of this at the end of the types
     module. But if you’re interested in all that you should just use Prolog!

    Anyhow, type checking is a few easy steps away.

    -
    def _ge(self, other):
    +
    def _ge(self, other):
         return (issubclass(other.__class__, self.__class__)
                 or hasattr(self, 'accept')
                 and isinstance(other, self.accept))
    diff --git a/docs/sphinx_docs/_build/html/notebooks/Zipper.html b/docs/sphinx_docs/_build/html/notebooks/Zipper.html
    index 4653021..55e3585 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/Zipper.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/Zipper.html
    @@ -42,7 +42,7 @@ the original paper: 
    from notebook_preamble import J, V, define
    +
    from notebook_preamble import J, V, define
     
    @@ -52,7 +52,7 @@ strings, Symbols (strings that are names of functions) and sequences (aka lists, aka quoted literals, aka aggregates, etc…), but we can build trees out of sequences.

    -
    J('[1 [2 [3 4 25 6] 7] 8]')
    +
    J('[1 [2 [3 4 25 6] 7] 8]')
     
    [1 [2 [3 4 25 6] 7] 8]
    @@ -75,13 +75,13 @@ datastructure used to keep track of these items is the zipper.)

    show the trace so you can see how it works. If we were going to use these a lot it would make sense to write Python versions for efficiency, but see below.

    -
    define('z-down == [] swap uncons swap')
    +
    define('z-down == [] swap uncons swap')
     define('z-up == swons swap shunt')
     define('z-right == [swons] cons dip uncons swap')
     define('z-left == swons [uncons swap] dip swap')
     
    -
    V('[1 [2 [3 4 25 6] 7] 8] z-down')
    +
    V('[1 [2 [3 4 25 6] 7] 8] z-down')
     
                              . [1 [2 [3 4 25 6] 7] 8] z-down
    @@ -93,7 +93,7 @@ but see below.

    [] [[2 [3 4 25 6] 7] 8] 1 .
    -
    V('[] [[2 [3 4 25 6] 7] 8] 1 z-right')
    +
    V('[] [[2 [3 4 25 6] 7] 8] 1 z-right')
     
                                      . [] [[2 [3 4 25 6] 7] 8] 1 z-right
    @@ -113,43 +113,43 @@ but see below.

    [1] [8] [2 [3 4 25 6] 7] .
    -
    J('[1] [8] [2 [3 4 25 6] 7] z-down')
    +
    J('[1] [8] [2 [3 4 25 6] 7] z-down')
     
    [1] [8] [] [[3 4 25 6] 7] 2
     
    -
    J('[1] [8] [] [[3 4 25 6] 7] 2 z-right')
    +
    J('[1] [8] [] [[3 4 25 6] 7] 2 z-right')
     
    [1] [8] [2] [7] [3 4 25 6]
     
    -
    J('[1] [8] [2] [7] [3 4 25 6] z-down')
    +
    J('[1] [8] [2] [7] [3 4 25 6] z-down')
     
    [1] [8] [2] [7] [] [4 25 6] 3
     
    -
    J('[1] [8] [2] [7] [] [4 25 6] 3 z-right')
    +
    J('[1] [8] [2] [7] [] [4 25 6] 3 z-right')
     
    [1] [8] [2] [7] [3] [25 6] 4
     
    -
    J('[1] [8] [2] [7] [3] [25 6] 4 z-right')
    +
    J('[1] [8] [2] [7] [3] [25 6] 4 z-right')
     
    [1] [8] [2] [7] [4 3] [6] 25
     
    -
    J('[1] [8] [2] [7] [4 3] [6] 25 sqr')
    +
    J('[1] [8] [2] [7] [4 3] [6] 25 sqr')
     
    [1] [8] [2] [7] [4 3] [6] 625
     
    -
    V('[1] [8] [2] [7] [4 3] [6] 625 z-up')
    +
    V('[1] [8] [2] [7] [4 3] [6] 625 z-up')
     
                                  . [1] [8] [2] [7] [4 3] [6] 625 z-up
    @@ -168,13 +168,13 @@ but see below.

    [1] [8] [2] [7] [3 4 625 6] .
    -
    J('[1] [8] [2] [7] [3 4 625 6] z-up')
    +
    J('[1] [8] [2] [7] [3 4 625 6] z-up')
     
    [1] [8] [2 [3 4 625 6] 7]
     
    -
    J('[1] [8] [2 [3 4 625 6] 7] z-up')
    +
    J('[1] [8] [2 [3 4 625 6] 7] z-up')
     
    [1 [2 [3 4 625 6] 7] 8]
    @@ -185,7 +185,7 @@ but see below.

    dip and infra¶

    In Joy we have the dip and infra combinators which can “target” or “address” any particular item in a Joy tree structure.

    -
    V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra')
    +
    V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra')
     
                                                                    . [1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra
    @@ -236,11 +236,11 @@ been embedded in a nested series of quoted programs, e.g.:

    The Z function isn’t hard to make.

    -
    define('Z == [[] cons cons] step i')
    +
    define('Z == [[] cons cons] step i')
     

    Here it is in action in a simplified scenario.

    -
    V('1 [2 3 4] Z')
    +
    V('1 [2 3 4] Z')
     
                                 . 1 [2 3 4] Z
    @@ -273,7 +273,7 @@ been embedded in a nested series of quoted programs, e.g.:

    And here it is doing the main thing.

    -
    J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z')
    +
    J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z')
     
    [1 [2 [3 4 625 6] 7] 8]
    diff --git a/docs/sphinx_docs/_build/html/notebooks/index.html b/docs/sphinx_docs/_build/html/notebooks/index.html
    index 6ab069e..e742b6c 100644
    --- a/docs/sphinx_docs/_build/html/notebooks/index.html
    +++ b/docs/sphinx_docs/_build/html/notebooks/index.html
    @@ -110,6 +110,14 @@
     
  • Finding Consecutive Approximations within a Tolerance
  • +
  • Square Spiral Example Joy Code +
  • Traversing Datastructures with Zippers
    • Trees
    • Zipper in Joy
    • @@ -194,6 +202,7 @@
    • Treating Trees II: treestep
    • Using x to Generate Values
    • Newton’s method
    • +
    • Square Spiral Example Joy Code
    • Traversing Datastructures with Zippers
    • The Blissful Elegance of Typing Joy
    • Type Checking
    • diff --git a/docs/sphinx_docs/_build/html/objects.inv b/docs/sphinx_docs/_build/html/objects.inv index 617d17f..0496afc 100644 Binary files a/docs/sphinx_docs/_build/html/objects.inv and b/docs/sphinx_docs/_build/html/objects.inv differ diff --git a/docs/sphinx_docs/_build/html/searchindex.js b/docs/sphinx_docs/_build/html/searchindex.js index 4d40e64..c4d0fd9 100644 --- a/docs/sphinx_docs/_build/html/searchindex.js +++ b/docs/sphinx_docs/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["index","joy","lib","library","notebooks/Categorical","notebooks/Derivatives_of_Regular_Expressions","notebooks/Developing","notebooks/Generator_Programs","notebooks/Intro","notebooks/Newton-Raphson","notebooks/NoUpdates","notebooks/Ordered_Binary_Trees","notebooks/Quadratic","notebooks/Recursion_Combinators","notebooks/Replacing","notebooks/The_Four_Operations","notebooks/Treestep","notebooks/TypeChecking","notebooks/Types","notebooks/Zipper","notebooks/index","parser","pretty","stack","types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst","joy.rst","lib.rst","library.rst","notebooks/Categorical.rst","notebooks/Derivatives_of_Regular_Expressions.rst","notebooks/Developing.rst","notebooks/Generator_Programs.rst","notebooks/Intro.rst","notebooks/Newton-Raphson.rst","notebooks/NoUpdates.rst","notebooks/Ordered_Binary_Trees.rst","notebooks/Quadratic.rst","notebooks/Recursion_Combinators.rst","notebooks/Replacing.rst","notebooks/The_Four_Operations.rst","notebooks/Treestep.rst","notebooks/TypeChecking.rst","notebooks/Types.rst","notebooks/Zipper.rst","notebooks/index.rst","parser.rst","pretty.rst","stack.rst","types.rst"],objects:{"joy.joy":[[1,1,1,"","UnknownSymbolError"],[1,2,1,"","interp"],[1,2,1,"","joy"],[1,2,1,"","repl"],[1,2,1,"","run"]],"joy.library":[[3,2,1,"","BinaryBuiltinWrapper"],[3,3,1,"","Def"],[3,2,1,"","FunctionWrapper"],[3,2,1,"","SimpleFunctionWrapper"],[3,2,1,"","UnaryBuiltinWrapper"],[3,2,1,"","add_aliases"],[3,2,1,"","app1"],[3,2,1,"","app2"],[3,2,1,"","app3"],[3,2,1,"","b"],[3,2,1,"","branch"],[3,2,1,"","choice"],[3,2,1,"","clear"],[3,2,1,"","cmp_"],[3,2,1,"","concat_"],[3,2,1,"","cond"],[3,2,1,"","dip"],[3,2,1,"","dipd"],[3,2,1,"","dipdd"],[3,2,1,"","disenstacken"],[3,2,1,"","divmod_"],[3,2,1,"","drop"],[3,2,1,"","dupdip"],[3,2,1,"","floor"],[3,2,1,"","gcd2"],[3,2,1,"","genrec"],[3,2,1,"","getitem"],[3,2,1,"","help_"],[3,2,1,"","i"],[3,2,1,"","id_"],[3,2,1,"","infra"],[3,2,1,"","initialize"],[3,2,1,"","inscribe"],[3,2,1,"","inscribe_"],[3,2,1,"","loop"],[3,2,1,"","map_"],[3,2,1,"","max_"],[3,2,1,"","min_"],[3,2,1,"","parse"],[3,2,1,"","pm"],[3,2,1,"","pred"],[3,2,1,"","primrec"],[3,2,1,"","remove"],[3,2,1,"","reverse"],[3,2,1,"","select"],[3,2,1,"","sharing"],[3,2,1,"","shunt"],[3,2,1,"","sort_"],[3,2,1,"","sqrt"],[3,2,1,"","step"],[3,2,1,"","succ"],[3,2,1,"","sum_"],[3,2,1,"","take"],[3,2,1,"","times"],[3,2,1,"","unique"],[3,2,1,"","void"],[3,2,1,"","warranty"],[3,2,1,"","words"],[3,2,1,"","x"],[3,2,1,"","zip_"]],"joy.parser":[[21,1,1,"","ParseError"],[21,3,1,"","Symbol"],[21,2,1,"","text_to_expression"]],"joy.utils":[[3,0,0,"-","generated_library"],[22,0,0,"-","pretty_print"],[23,0,0,"-","stack"]],"joy.utils.generated_library":[[3,2,1,"","ccons"],[3,2,1,"","cons"],[3,2,1,"","dup"],[3,2,1,"","dupd"],[3,2,1,"","dupdd"],[3,2,1,"","first"],[3,2,1,"","first_two"],[3,2,1,"","fourth"],[3,2,1,"","over"],[3,2,1,"","pop"],[3,2,1,"","popd"],[3,2,1,"","popdd"],[3,2,1,"","popop"],[3,2,1,"","popopd"],[3,2,1,"","popopdd"],[3,2,1,"","rest"],[3,2,1,"","rolldown"],[3,2,1,"","rollup"],[3,2,1,"","rrest"],[3,2,1,"","second"],[3,2,1,"","stack"],[3,2,1,"","stuncons"],[3,2,1,"","stununcons"],[3,2,1,"","swaack"],[3,2,1,"","swap"],[3,2,1,"","swons"],[3,2,1,"","third"],[3,2,1,"","tuck"],[3,2,1,"","uncons"],[3,2,1,"","unit"],[3,2,1,"","unswons"]],"joy.utils.pretty_print":[[22,3,1,"","TracePrinter"],[22,2,1,"","trace"]],"joy.utils.pretty_print.TracePrinter":[[22,4,1,"","go"],[22,4,1,"","viewer"]],"joy.utils.stack":[[23,2,1,"","concat"],[23,2,1,"","dnd"],[23,2,1,"","expression_to_string"],[23,2,1,"","iter_stack"],[23,2,1,"","list_to_stack"],[23,2,1,"","pick"],[23,2,1,"","stack_to_string"]],joy:[[1,0,0,"-","joy"],[3,0,0,"-","library"],[21,0,0,"-","parser"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","function","Python function"],"3":["py","class","Python class"],"4":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:function","3":"py:class","4":"py:method"},terms:{"0":[2,3,5,6,7,8,9,10,11,12,13,14,16,17,18,24],"0000000001585":9,"000000001":9,"01":[6,7],"03":18,"05":5,"0a":18,"0b":[6,7],"0b11100111011011":6,"1":[2,3,5,6,7,8,9,10,11,12,13,14,16,17,18,19,23,24],"10":[2,5,6,7,13,18,24],"100":[5,16,18],"1000":[5,6,7,18],"10000":[5,18],"10001":5,"1001":[5,18],"10010":5,"10011":5,"1002":18,"101":5,"1010":5,"10100":5,"10101":5,"1011":5,"10110":5,"10111":5,"102":16,"1024":2,"103":16,"104":16,"105":16,"106":16,"107":16,"108":16,"109":16,"10946":7,"11":[2,6,7,18,24],"110":[5,6],"1100":5,"11000":5,"11001":5,"1101":5,"11010":5,"11011":5,"1110":5,"11100":5,"11101":5,"1111":5,"11110":5,"11111":5,"12":[2,6,16],"120":13,"122":5,"123":8,"128":7,"13":[2,7,16,24],"1346269":7,"14":[2,6,16],"144":7,"14811":[6,7],"15":[2,6,13,16,18,24],"16":[2,7,12,16,24],"160":2,"17":[11,16],"18":[6,8,14,16,22],"19":[16,18,24],"196418":7,"1a":18,"1b":18,"2":[2,3,5,6,8,9,10,11,13,14,16,17,19,23,24],"20":[2,6,14,18,24],"2006":18,"2017":[8,18],"2020":24,"207":2,"21":[6,7],"22":[9,18,24],"23":[2,6,7,8,9,11,14,16,18,22],"230":7,"231":[6,7],"232":7,"233":7,"233168":[6,7],"234":7,"23rd":18,"24":[2,6,7],"25":[6,7,12,16,17,19,24],"256":7,"2584":7,"26":[2,5,7,18,24],"27":[6,7],"273":10,"28":[7,17,24],"29":[18,24],"2a":18,"2b":18,"3":[2,3,7,8,10,11,12,13,16,17,19,20,23,24],"30":[2,6,18,24],"31":17,"32":[2,7,16],"33":6,"34":[7,17,18,24],"36":9,"37":[17,18,24],"3702":[6,7],"38":[18,24],"3819660112501051":12,"3b":18,"3i":18,"4":[2,6,7,8,9,11,13,16,17,19,23,24],"40":[2,17,18],"4000000":7,"41":[14,18,24],"414":22,"44":[11,16,18,24],"45":[2,6],"46":18,"4613732":7,"46368":7,"466":6,"47":[18,24],"48":[18,24],"49":[16,18,24],"4ac":12,"4m":7,"5":[2,3,5,7,8,11,12,13,14,16,18,20,24],"50":2,"513":22,"529":[2,8],"53":[18,24],"547":8,"55":[6,7],"552":2,"5555555555555554":2,"56":[18,24],"57":[6,7],"5bkei":11,"5d":11,"6":[2,6,9,11,13,16,18,19],"60":6,"610":7,"618033988749895":12,"625":19,"64":7,"66":[6,7],"6945":6,"7":[2,6,7,11,16,18,19,24],"75":2,"795831523312719":[2,9],"8":[2,5,6,7,11,12,16,18,19,24],"80":6,"832040":7,"88":11,"8888":8,"89":7,"9":[2,6,11,12,16,18,24],"90":2,"92":5,"925":6,"978":6,"980":6,"981":6,"984":6,"985":6,"987":6,"99":22,"990":6,"991":6,"992":6,"993":6,"995":6,"996":6,"999":[6,7],"999999999999996":9,"9a9d60354c35":18,"\u03b4":5,"\u03b5":9,"abstract":[8,11],"boolean":[2,3,8,11,15],"break":[5,8,18],"byte":[5,6],"case":[2,3,13,15,16,18,23],"char":5,"class":[3,5,8,18,21,22,23],"default":[3,7,11,23],"do":[2,3,4,5,6,7,8,11,13,14,15,18,19,20],"export":[3,21],"final":[2,11,13],"float":[8,18,19,21],"function":[0,1,4,6,7,10,12,17,19,20,21,22,23,24],"g\u00e9rard":19,"goto":5,"import":[2,5,6,7,9,11,12,13,14,16,17,18,19],"int":[5,7,8,13,18,19,21,23],"long":[11,18,20],"new":[2,3,5,7,8,10,13,14,18],"p\u00f6ial":20,"p\u00f6ial06typingtool":18,"public":10,"return":[1,3,5,6,8,11,13,14,15,16,18,21,22,23],"static":[2,10],"super":18,"switch":[2,18],"throw":[11,24],"true":[2,3,5,6,13,15,18],"try":[7,9,12,13,16,17,18,20],"void":[0,3],"while":[3,5,8,11,18,21,23],A:[1,3,4,8,13,15,18,20,21,22,23],AND:[5,18],And:[5,6,7,9,11,13,15,18,19,23],As:[4,6,11,18],At:[6,13,18],Be:2,But:[0,4,6,7,8,11,14,18],By:[7,11,18],For:[2,3,11,13,14,18,20,23],If:[2,3,5,6,7,8,9,10,12,13,16,18,19],In:[2,3,4,6,7,8,13,15,18,19,20,23],It:[0,2,3,4,5,6,7,8,10,11,13,18,19,23,24],Its:3,NO:8,NOT:5,No:[0,16,20],Not:18,OR:[5,18],Of:6,On:[3,22],One:[2,8,15,18,20],Or:[5,10,11,16,18],TOS:[2,3],That:[6,11],The:[0,1,2,3,4,5,7,9,10,12,19,20,21,22,23,24],Then:[2,3,11,12,13,18],There:[5,12,13,15,16,18,23],These:[15,18,20,23],To:[0,5,6,7,9,11,13,16,18],With:[9,13,18,20,24],_0:5,_1000:18,_1:5,_:[8,14,18],__:11,__add__:18,__call__:5,__class__:18,__eq__:18,__ge__:18,__hash__:18,__init__:[5,18],__main__:18,__radd__:18,__repr__:18,__str__:22,_and:5,_compaction_rul:5,_con:5,_dictionari:18,_f:18,_ge:18,_infer:18,_interpret:18,_log:18,_log_it:18,_names_for:18,_or:5,_r:18,_templat:5,_to_str:18,_tree_add_:11,_tree_add_e:[3,11,24],_tree_add_p:11,_tree_add_r:11,_tree_add_t:11,_tree_delete_:11,_tree_delete_clear_stuff:[3,11,24],_tree_delete_del:11,_tree_delete_r0:[3,11,24],_tree_delete_r1:11,_tree_delete_rightmost:11,_tree_delete_w:11,_tree_get_:[3,11,24],_tree_get_p:11,_tree_get_r:11,_tree_get_t:11,_tree_iter_order_curr:11,_tree_iter_order_left:11,_tree_iter_order_r:11,_tree_iter_order_right:11,_tree_t:11,_treestep_0:16,_treestep_1:16,_uniqu:18,_within_b:9,_within_p:9,_within_r:9,a0:18,a10001:18,a10002:18,a10003:18,a10004:18,a1:[3,17,18,24],a2:[3,17,18,24],a3:[3,17,18,24],a4:[3,17,18,24],a5:[17,18,24],a_:9,a_i:9,aa:13,ab:[3,5,9],abbrevi:16,abl:[5,15,18,24],about:[0,8,11,15,18,19,23],abov:[0,5,6,9,11,13,15,18],absolut:8,ac:5,accept:[1,2,3,5,6,7,8,11,12,14,15,16,18,19],accord:5,accordingli:[11,15],accumul:6,act:[5,24],action:[0,8,14,18,19,20],actual:[2,6,8,11,15,18],ad:[4,5,8,10,14,18,20],adapt:20,add:[3,5,6,7,8,14,18,22,24],add_alias:3,add_def:[],add_definit:[11,16],addit:[0,2,3,6,8,13,14,16],address:20,adjust:11,advantag:18,affect:[3,15],after:[5,6,7,8,13,15,18,23,24],afterward:8,again:[2,3,6,8,11,13,18],against:18,aggreg:19,ahead:18,aka:[5,8,19,24],al:[15,18],albrecht:0,algorithm:[5,8,18],alia:3,alias:[3,8],align:[8,22],all:[3,5,6,7,8,11,13,14,15,16,18,22,23],alloc:18,allow:[10,11,15],almost:11,along:[5,8,13,18],alphabet:[3,20],alreadi:[5,9,14,18,19],also:[0,5,6,8,11,15,18,22,23],alter:[5,18],altern:[4,18],although:[4,11],altogeth:7,alwai:[6,10,13,15],am:[15,20],amend:15,among:18,amort:11,an:[0,1,2,3,4,5,9,13,14,16,20,23,24],analysi:[4,20],anamorph:[8,20],and_:3,ani:[4,5,6,8,10,11,15,18,19,21],annual:8,anonym:11,anoth:[5,11,15,18,23,24],anyhow:[15,18],anyjoytyp:18,anymor:18,anystarjoytyp:18,anyth:[2,3,5,8,18,24],apart:18,api:10,app1:3,app2:[3,8,12,13,14,15],app3:[3,15],app:8,appear:[2,4,5,6,11],append:18,appendix:20,appli:[2,3,6,7,11,13,18],applic:7,approach:6,appropri:5,approxim:20,ar:[1,2,3,5,6,7,8,10,12,13,15,16,18,19,20,21,23,24],archiv:0,aren:19,arg:[2,3],argument:[2,3,8,9,12,13,20,22,23],arithmet:2,ariti:[2,15],around:[6,18,21,23],arrang:16,arriv:[7,16],arrow:5,articl:[0,4,7,13],ascii:5,ascii_lowercas:5,ask:[4,7,18],aspect:0,assembl:5,assert:[5,18],assign:[15,23],associ:11,assum:9,asterisk:16,asterix:[18,24],asyncron:15,attack:8,attempt:[0,1,18],attribut:3,attributeerror:18,author:18,auto:[0,18,24],automat:[4,15,18],auxiliari:[5,16],avail:[0,18,24],averag:[8,14],avoid:11,awai:[11,18],awar:2,awkward:[11,13,18],azur:20,b0:3,b1:[3,18,24],b2:24,b3:24,b:[3,5,7,8,9,11,13,15,16,18],back:[3,11,18],backtrack:24,backward:[10,11,12,16],bad:18,bag:8,banana:13,bar:15,barb:13,base:[0,2,3,10,13,16,18],basic:[2,3,8,11],basicconfig:[17,18],bc:5,bd:5,becaas:5,becaus:[2,3,5,8,11,15,16,18,19,23],becom:[11,16,23],becuas:18,been:[5,9,10,11,18,19],befor:[5,7,8,11],begin:[11,16],behavior:[10,16,24],behaviour:[0,1,18],behind:15,being:[0,15],below:[2,3,5,6,7,11,18,19],bespok:8,best:0,better:[6,11,13,18],between:[0,6],beyond:7,biannual:8,bin:5,binari:[0,7,8,20],binary_search_tre:11,binarybuiltinwrapp:3,bind:8,bingo:19,bit:[5,6,7,11,18],blank:21,bliss:[0,20],block:6,bodi:[2,3,5,8,11,15],body_text:[],booktitl:18,bool:[3,13,18,24],borrow:[8,18],both:[2,6,8,12,13,14,15,18,23],bottom:7,bounce_to:5,bracket:[8,18,21],branch:[3,5,6,7,13,18,20,24],branch_fals:18,branch_tru:18,breakpoint:8,bring:[6,8,18],bruijn:18,brutal:15,brzozowski:[18,20],brzozowskian:5,btree:[11,16],buck:11,bug:[0,8],build:[7,8,12,13,19,23],built:[12,18],bullet:22,bundl:[2,3,13],burgeon:8,c:[0,1,2,3,5,7,9,11,13,15,16],calculu:4,call:[1,2,5,8,10,11,13,15,18,22,23],caller:[11,18],can:[0,2,3,4,5,6,7,8,9,10,12,13,14,15,16,18,19,20,21,23,24],cancel:15,cannot:[17,18,21],captur:8,card:8,care:[6,23],carefulli:19,carri:[7,11],cartesian:4,catamorph:20,categor:[0,20],categori:[4,15],ccc:4,ccon:[3,11,17,18,24],cell:[13,18],certain:[8,23],certainli:11,cf:[7,9,12,13],chain:[3,15],chang:[2,10,11,18,19],charact:[5,19],chat:8,chatter:[0,18],check:[0,7,9,18,20],child:16,choic:[3,13],choos:10,chop:12,chose:5,cinf:11,circl:5,circuit:4,cite_not:11,classmethod:[],claus:[3,18],clean:18,clear:[3,6,8],clear_stuff:11,cleav:[8,12,14],client:23,close:[0,1,4],clunki:[6,18],clv:15,cmp:[3,16,20],cmp_:3,code:[0,1,4,5,12,13,15,18,20,24],codireco:[7,9],collaps:13,collect:[4,5,7,8,18],combin:[0,3,6,7,8,9,12,15,16,19,20,22,24],combinatorjoytyp:18,come:[8,11,18],command:[8,11,18],comment:15,common:[2,6,15],compar:[3,4,5,18],comparison:[0,11],compat:15,compel:4,compil:[2,3,4,5,8,11,14,15,20,24],complement:5,complet:4,complex:[3,15,18,19,24],complic:18,compos:[5,24],composit:18,compostit:18,compound:11,comput:[2,4,5,6,8,12,15,18,24],con:[3,5,6,7,8,9,11,12,13,15,16,19,23,24],conal:[4,15],concat:[3,7,8,15,16,18,23],concat_:3,concaten:[0,5],concatin:[0,3,5,23],concern:15,conclus:20,concurr:2,cond:[3,11],condit:[3,8],confer:18,conflict:[11,18],consecut:20,consid:[5,6,7,11,13,16,18,19],consist:[2,7,8,15,16],constant:11,constitu:13,construct:[15,18],consum:[15,18],contain:[0,2,3,5,7,8,13,18,21],content:18,context:2,conting:11,continu:[0,5,13,18,19],control:8,conveni:[4,15,18],convent:15,convers:18,convert:[13,14,16,18,21,23],cool:11,copi:[2,3,6,11,13,15,16,17,20],copyright:8,correspond:[4,15],could:[2,4,5,6,8,10,11,15,18,19],couldn:15,count:[3,18],counter:[6,18],coupl:16,cours:[6,11,18],cover:18,cp:8,cpu:15,crack:11,crash:11,creat:[0,2,3,6,9,11,15,18],creativ:18,crude:[11,18,21],cruft:18,curent:24,current:[2,3,8,13,15,16,18,19,22,24],curri:5,custom:10,cycl:[6,7],cython:8,d010101:5,d0101:5,d01:5,d0:5,d10:5,d1:5,d:[2,3,5,11,13,14,15,16,17,18,19],d_compact:5,dai:8,data:[2,3,5,13],datastructur:[0,2,13,18,20,21,23],datatyp:23,ddididi:19,de:[18,19],deal:[0,5,11,15],dealt:18,debugg:18,decid:11,declar:18,decor:3,decoupl:13,decrement:3,deduc:[6,18],deeper:0,deepli:4,def:[3,5,8,13,14,18,23],defaultdict:[5,18],defi:[],defin:[2,4,5,6,7,8,9,10,12,13,14,15,18,19,20],definit:[0,2,3,6,7,8,10,11,13,16,18,20,24],definitionwrapp:[11,13,16],defint:15,del:17,deleg:8,delet:20,deliber:18,demo:18,demonstr:4,depend:[3,11,13,15],deposit:16,depth:[18,24],dequot:13,der:11,deriv:[2,3,6,8,9,11,18,20],derv:5,describ:[4,5,11,13,15,16,18,21],descript:[6,8],descriptor:18,design:[2,3,11,15,20],desir:[8,16],destin:5,destruct:11,detail:[8,11,18],detect:[5,7,11,13,18],determin:20,develop:[0,7,8,18,20],diagram:6,dialect:1,dict:[1,3,5,18,22],dictionari:[0,1,3,8,18,20,22],did:18,differ:[0,4,6,9,11,12,13,15,23],differenti:4,difficult:18,difficulti:15,dig:[11,19],digit:6,digraph:5,dinfrirst:[8,18,24],dip:[3,6,7,8,9,11,12,13,14,15,16,18,20,24],dipd:[3,7,8,11,12,13,15,18,19,24],dipdd:[3,11],direco:20,direct:8,directli:[6,15,16,18,23],disappear:[2,5,18],discard:[3,7,9,11,13],disciplin:11,disenstacken:[3,8],disk:8,displac:2,displai:18,distiguish:18,distribut:15,ditch:11,div:[3,8,18,24],dive:16,divis:[11,18],divmod:[3,24],divmod_:[3,18],dnd:23,doc:[2,3,8,18],doc_from_stack_effect:17,docstr:18,document:[18,20,21,23],doe:[0,1,3,4,5,7,8,14,15,18,20,22,24],doesn:[6,10,11,15,16,18,23],domain:[4,18],don:[5,6,8,11,18],done:[2,6,8,10,18],dooooc:18,door:8,dot:[5,22],doubl:[5,6,8,18],doublecircl:5,down:[2,5,9,13,19,24],down_to_zero:8,dozen:8,dr:5,draft:[4,10],drag:23,dream:8,drive:[7,9],driven:6,driver:[5,7],drop:[3,11,23],ds:5,dudipd:8,due:18,dup:[3,6,7,8,9,11,12,13,15,17,19,23,24],dupd:[3,18,24],dupdd:[3,24],dupdip:[3,6,11,12,13],duplic:[3,11,13],durat:2,dure:[2,13],e:[2,3,5,7,8,10,11,14,15,17,18,19,22,23],each:[2,3,4,5,6,8,13,14,15,16,18,22,24],easi:[0,11,16,18,19],easier:[3,11,15],easili:4,eat:5,edit:20,ee:[11,18],effect:[2,3,5,8,15,19,20,24],effici:[7,14,19],efg:18,eh:18,either:[1,2,3,5,11,13,18],el:23,elabor:18,eleg:[0,5,8,11,15,20],element:[2,3],elif:18,elimin:[5,18],elliott:[4,15],els:[2,3,5,13,15,18],else_:18,embed:[4,11,19],emit:18,empti:[3,5,8,16,18,23,24],en:11,encapsul:8,enclos:8,encod:7,encount:18,end:[5,6,11,13,16,18,23],endless:7,enforc:[2,8],engend:8,enough:[5,8,13,22,24],enstacken:[7,8,18],enter:8,enter_guard:18,entir:23,entri:[3,19,22],enumer:18,epsilon:9,eq:[2,3,24],equal:[3,6,16,23],equat:[8,9],equival:15,er:[0,8],ergo:[5,11],err:[11,17],error:[8,18,21],essai:0,establish:18,et:[15,18],etc:[3,16,18,19,21],euler:20,euro:18,eval:[0,18],evalu:[1,2,3,8,9,11,12,13,14,15,16,18,22],event:15,eventu:[15,18],ever:18,everi:[1,7,15],everybodi:15,everyth:[3,5,11,12,15,18],evolv:10,examin:13,exampl:[0,3,5,6,18,20,21,23,24],exce:7,except:[1,5,8,11,17,18,21],execut:[0,1,2,3,8,13,14,15,16,18,19,23,24],exend:18,exercis:[5,11],exist:[4,11,18],expand:11,expect:[2,3,15,16,18,23],experi:[8,16],explain:18,explan:8,explor:[8,18],express:[0,1,2,3,4,11,13,14,18,19,20,22,23],expression_to_str:[18,23],extend:18,extra:[1,6,7],extract:[11,12,20],extrem:8,extrememli:8,f0:18,f1:[17,18,24],f2:[17,18,24],f3:[18,24],f:[2,3,5,6,7,9,13,15,18],f_g:18,f_in:18,f_out:18,f_python:18,facet:0,facil:8,fact:21,factor:[2,6,8,11,18],factori:[3,20],fail:[2,3,11,20,21],fail_fail:[],fairli:18,fake:5,fall:18,fals:[2,3,5,6,13,15,18],falsei:18,far:[9,11,13,18,24],fascin:0,favorit:15,fear:[11,18],few:[6,8,9,12,15,18],fewer:[3,8],fg:18,fg_in:18,fg_out:18,fi:[17,18],fib:7,fib_gen:7,fibonacci:20,figur:[2,3,11,13,18],filter:11,fin:6,find:[2,3,5,6,7,15,16,18,20,24],finder:9,fine:[0,5,6,11,18,24],finite_state_machin:5,first:[3,5,7,8,9,11,12,13,14,16,19,20,23,24],first_two:[3,11,24],fit:[6,8],five:[6,8,20],fix:[2,3,5,13,18],fixm:[5,18],flag:[15,18],flatten:[8,16,18],flesh:5,flexibl:20,floatjoytyp:18,floatstarjoytyp:18,floor:3,floordiv:[3,6,24],flow:8,fn:18,fo:[17,18],follow:[0,2,3,5,8,10,13,15,16,18,19],foo:[8,10,11,15,18],foo_ii:10,fork:15,form:[2,3,4,5,6,7,13,16,18,23],forman:8,format:[17,18,20,22],formula:[0,6,20],forth:[8,18],forum:0,forward:18,found:8,four:[0,2,3,6,7,8,11,20],fourteen:6,fourth:[2,3,11,13,24],fr:5,frac:[9,12],fractal:8,fraction0:8,fraction:[2,8],frame:13,framework:8,free:[4,8,11],freeli:2,from:[0,1,2,3,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,23],from_:5,from_index:23,front:[2,3,13],frozenset:5,fulin:15,full:6,fun:[5,20],func:18,functionjoytyp:18,functionwrapp:3,functool:5,fundament:[0,20],funtion:11,further:[9,18,20],futur:15,g:[2,3,5,7,8,9,10,11,13,14,15,17,18,19,22,23],g_in:18,g_out:18,garbag:8,gari:11,gcd2:3,gcd:[3,8],ge:[2,3,24],gener:[0,2,4,13,15,18,20,23,24],generated_librari:3,genrec:[3,8,11,13,15,16,18],geometr:6,get:[2,4,5,6,7,8,12,13,18,20],getch:5,getitem:3,getrecursionlimit:23,getsourc:8,ghc:4,gi:18,give:[4,6,11,13,16,18,23],given:[2,3,6,7,9,11,13,15,18,19,20,23],global:[17,18],glue:8,go:[5,6,11,12,13,15,16,18,19,22],goe:24,good:[6,11,18],grab:18,grammar:21,grand:8,graph:[5,15],graphic:5,graphviz:5,great:[0,8,18,20],greater:23,grind:18,group:0,grow:5,gsra:9,gt:[2,3,24],guard:[11,18],h:[5,13,18],ha:[0,2,3,5,7,8,9,10,11,13,15,18,19,23],had:[5,6,19],haiku:8,half:[6,18,19],hallmark:15,hand:[5,8,14,18,20],handi:[9,18],handl:[11,18,23,24],happen:[8,18],happi:5,hard:[5,18,19],hardwar:4,hasattr:18,hash:18,haskel:4,have:[2,3,5,6,7,8,9,10,13,14,15,18,19,20,23,24],he:[4,9],head:23,heh:18,help:[3,8,11,13,18],help_:3,helper:5,herd:8,here:[5,6,7,11,16,18,19,24],hg:24,hide:11,hierarchi:18,higher:[5,8,11,18],highli:8,hij:5,histori:[18,22],hit:5,hmm:[5,11],hoist:3,hold:[6,18],hood:11,hope:[0,6,8,20],hopefulli:13,host:20,how:[0,4,5,9,11,13,18,19,20],howev:[13,14,15,18],html:[2,3,7,12,13,20],http:[11,24],huet:19,huge:11,hugh:[9,16],human:8,hybrid:24,hylomorph:20,hypothet:2,i0:18,i1:[17,18,24],i2:[17,18,24],i3:[18,24],i:[0,3,6,7,8,9,13,14,15,16,19,20,22,24],id:[3,18],id_:3,idea:[4,6,8,18],ident:[3,5,13,18,24],if_not_empti:11,ift:[3,11,13,16,18,24],ignor:[1,3,11,18],ii:[0,20],iii:20,illustr:[5,13],imagin:[5,15,19],imap:18,imit:[5,16],immedi:[5,13],immut:[5,8,11],imper:13,implement:[0,1,2,4,8,10,11,13,14,15,20,24],implementaion:15,implicit:8,improv:18,includ:[4,11,15,16,18,24],inclus:6,incom:23,incompat:10,incorpor:12,increas:6,increment:[3,4,6,10,15],index:[0,8,18,23],indexerror:23,indic:[15,16,18,23,24],ineffici:18,infer:[0,17],inferenc:24,info:[17,18],inform:[3,5,18,24],infra:[3,7,8,11,12,14,15,16,18,20,24],infrastructur:3,initi:[2,3,5,8,9,11,18],inlin:11,inner:18,inproceed:18,input:[1,9,15,17,18],input_:5,inscrib:3,inscribe_:3,insert:[18,23],insight:13,inspect:8,inspect_stack:18,instal:0,instanc:18,instanti:[4,22],instead:[5,6,7,11,13,18,19,23,24],instruct:5,integ:[2,3,8,13,16,18,21],integr:3,intend:[0,8],interact:[8,20],interest:[0,6,11,18,20],interfer:15,interlud:20,intermedi:13,intern:[0,18,22,23],interp:1,interpret:[0,4,10,14,21,22,24],interrupt:8,intersect:5,interspers:15,interv:[4,6],intjoytyp:18,introduc:10,introduct:0,intstarjoytyp:18,intuit:18,invari:3,invent:18,involv:18,ipf:8,ipython:18,isinst:[5,18],isn:[5,11,19],issubclass:18,item:[2,3,8,11,13,15,16,18,20,23],iter:[1,3,5,8,13,15,16,18,20,23],iter_stack:[14,23],iteritem:[5,18],itertool:[5,18],its:[0,1,2,3,4,6,8,11,13,15,16,18,23],itself:[0,2,8,11,15,18],iv:20,j05cmp:[2,3,13],j:[2,5,6,7,9,11,12,13,14,16,18,19],jaanu:18,jmp:5,job:[15,20],john:[9,16],joi:[2,4,10,11,12,14,15,17],join:[5,18],joypi:[19,24],joytypeerror:17,jp:[7,12],js:8,jump:5,jump_from:5,junk:18,jupyt:20,just:[0,2,3,5,7,8,10,11,13,15,16,18,19,22],juxtaposit:15,k:[6,11,16,18],keep:[5,11,12,15,18,19],kei:[5,16,20],kevin:0,key_n:11,keyerror:[5,11,18],kind:[2,4,8,11,13,16,18,24],kinda:18,kleen:[16,18],kleenestar:18,kleffner:18,know:[6,11,18],knowledg:18,known:[4,15],kstar:5,l:[3,5,11,18],l_kei:11,l_left:11,l_right:11,l_valu:11,la:0,label:[5,18],lambda:[4,5,18],languag:[3,4,5,8,10,11,14,18],larg:[5,18],larger:[20,23],largest:3,last:[6,11,13,18],lastli:7,later:[5,8,16,18],law:2,lazi:18,lazili:9,lcm:6,le:[2,3,24],lead:[5,8,18],leaf:11,lean:8,learn:0,least:[2,6,13,18,23],least_fract:8,leav:[3,6,15],left:[5,8,12,13,15,16,18,19,22,23],leftov:13,legend:5,len:[5,18],length:[3,6,23],lens:13,less:[6,7,8,13,18,23],let:[7,9,11,12,13,16,18,19,20],letter:18,level:[4,5,11,17,18],librari:[0,5,14],like:[2,3,5,6,8,15,16,18,20,21,22,24],limit:[18,24],line:[8,11,12,18,22,24],linear:23,link:[0,5,18],linux:0,list:[0,3,5,6,8,9,11,13,15,16,18,19,22],list_to_stack:[18,23],liter:[1,11,16,18,19,21],literatur:18,littl:[5,7,11,15,18,20],live:20,lk:16,lkei:16,ll:[5,6,7,8,13,16,18,19],load:[6,8],local:18,locat:2,locu:22,log:[17,18],log_2:11,logic:[0,6,20],longer:[11,18],look:[1,5,7,8,9,11,12,15,18],lookup:8,loop:[0,1,3,5,6,18,20,24],lose:18,lot:[5,8,11,18,19],love:6,low:[4,5],lower:6,lowercas:[5,18],lowest:11,lr:5,lshift:[3,24],lt:[2,3,24],m:[0,5,6,8,11,15,16,18],machin:[0,20],machineri:[11,18],macro:8,made:[0,8,15,18,19],magic:18,mai:[2,13,15,24],mail:0,main:[0,3,8,12,15,18,19],mainloop:10,maintain:19,major:10,make:[2,3,4,6,8,11,13,14,15,16,18,19,20],make_gener:9,make_graph:5,manfr:[0,2,3,4,13],mani:[0,5,8,18],manipul:18,manner:12,map:[1,3,5,6,8,10,13,16,18,22],map_:3,marker:8,mask:[6,7],match:[0,1,18,20],materi:0,math:[0,8,9,11,12,18],mathemat:8,matter:[6,9,11,16],max:3,max_:3,maximum:3,mayb:[11,18],mc:18,me:[8,16,18],mean:[4,6,8,9,11,13,16,18,23],meant:[8,11,13,16,23],mem:5,member:[2,3,13],memo:5,mental:8,mention:2,mercuri:[],mess:18,messag:[17,18],meta:[8,11,14],meta_compos:18,method:[0,8,18,20,22],midpoint:6,might:[4,5,7,11,18],mike:11,million:7,min:3,min_:3,mind:18,minimum:3,minor:11,minu:3,mirror:0,miscellan:0,mismatch:18,mix:[8,18],mod:3,mode:18,model:[4,8],modern:0,modif:[7,18],modifi:[8,11,19],modul:[0,1,3,8,18,21],modulo:18,modulu:[3,8,24],moment:18,month:8,more:[0,3,4,5,6,7,8,9,13,14,15,16,18,21,23,24],most:[5,18,24],mostli:0,move:[5,11],movement:2,ms:20,much:[5,6,7,11,13,18,23],muck:11,mul:[3,8,12,17,19,22,24],multi:[],multipl:[20,24],multipli:3,must:[2,3,6,10,13,15,16,18,21],my:[0,6,8,15],myself:18,n0:18,n10001:18,n10002:18,n10003:18,n1001:18,n1002:18,n1003:18,n1:[18,24],n2:[18,24],n3:[18,24],n4:[18,24],n:[2,3,5,6,8,9,11,13,14,16,18,19,23],name:[1,3,5,8,10,11,13,18,19,20,21,22,23,24],narr:18,natur:[5,6,7,11,18],navig:19,ne:[3,24],nearli:18,neat:11,neato:18,necessarili:18,need:[2,3,6,7,9,10,11,13,15,18],neg:[3,12,24],neither:[15,18],ness:5,nest:[3,8,11,19],net:24,network:8,never:[5,10,13],new_def:18,new_f:18,new_fo:18,new_kei:11,new_valu:11,newton:[0,20],next:[5,6,15,16,18,24],nice:[0,5,13,23],niether:2,nk:6,nm:5,node:[5,16,20],node_kei:11,node_valu:11,non:[5,16,18],none:[1,18],nope:16,nor:5,normal:15,not_:3,notat:[8,11],note:[2,5,6,9,11,13,15,18,23],notebook:[6,7,8,18,19,20],notebook_preambl:[2,6,7,9,11,12,13,14,16,18,19],noth:[2,11,15],notic:6,now:[3,5,6,7,8,13,14,16,18,20],ns:18,nth:[3,23],nullari:[8,11,15,18,24],number:[1,2,3,6,7,9,15,23,24],numberjoytyp:18,numberstarjoytyp:18,numer:18,o:[5,7,11,18],object:[5,18,21],observ:6,obviou:7,obvious:18,occur:11,odd:[6,7],off:[2,3,6,7,12,18,19],often:[5,15],oh:11,ok:18,old:[0,2,14],old_k:11,old_kei:11,old_valu:11,omg:[],omit:[13,18,21],onc:[3,5,10,11],one:[2,3,5,6,7,11,13,15,16,18,22,23,24],ones:[5,7,18],onli:[2,3,5,6,11,13,15,18,19,23],onto:[1,2,3,8,13,23],open:[8,18],oper:[0,3,5,8,11,13,20,23],oppos:18,optim:11,option:[1,8,11,18,23],or_:3,orchestr:15,order:[0,2,3,8,13,15,17,18,20,23],org:[0,11],origin:[0,1,2,3,11,19],osdn:24,other:[0,2,3,4,5,8,11,13,16,18,23],otherwis:[3,5,6,7,11,16,18],our:[5,6,7,8,9,13,16,18],out:[2,3,4,6,7,8,9,11,12,13,15,18,19,20],outcom:16,outlin:5,output:[1,5,9,13,15,17,18,24],outsid:4,over:[3,4,6,7,8,9,11,12,15,16,18,20,24],overhaul:18,overview:[3,18],own:[11,18],p:[2,3,6,11,13,15],pack:23,packag:[0,8],page:[0,11,18,23],pair:[2,3,6,7,11,18],palidrom:6,palindrom:6,pam:8,paper:[4,8,13,15,19],paradigm:20,parallel:[2,20],param:1,paramet:[1,2,3,13,14,21,22,23],parameter:20,paramorph:13,parenthes:[11,23],pariti:7,pars:[0,3,5,8],parse_definit:[],parseerror:21,parser:[0,17,18],part:[2,3,9,13,16,20],partial:[5,18],particular:19,pass:[0,5,11,18,22],patch:5,path:[5,18,20],pattern:[5,6,15,16,20],pe1:[6,7],pe2:7,pearl:19,pend:[3,8,13,18,19,22],peopl:20,per:[8,16],perfectli:15,perform:[5,15,18],perhap:7,period:8,permit:[15,18,23],permut:18,persist:11,phase:2,phi:5,pick:[3,6,7,15,23],pickl:8,pictur:11,piec:13,pip:0,place:[3,6,8,18],plai:0,plu:3,plug:[7,13,16],pm:[3,12,18,24],point:[4,5,8,11,13,15],pointless:2,pool:15,pop:[3,5,6,7,8,11,13,14,16,17,23,24],popd:[3,8,9,11,14,15,18,24],popdd:[3,7,12,18,24],popop:[3,6,7,8,9,11,16,18,24],popopd:[3,24],popopdd:[3,24],posit:[3,6,8,13],possibilit:11,possibl:[11,16,18,20],post:8,poswrd:18,potenti:15,pow:[3,24],power:[8,18],pprint:5,pragmat:6,preambl:9,preceed:15,precis:[0,1],pred:[3,18,24],predecessor:3,predic:[2,3,5,7,13,15],prefix:[18,22],preliminari:5,present:18,preserv:[4,16],pretti:[9,11,12,15,16,18,22,23],pretty_print:0,previou:[8,15],prime:9,primit:[2,3,18,20],primrec:[3,7,8,13],print:[0,1,2,3,5,17,18,22,23],probabl:[7,8,11,18],problem:[8,18,20],proc_curr:11,proc_left:11,proc_right:11,proce:[6,24],process:[5,8,16,18,22],produc:[3,6,11,13,16,18],product:[5,7,8,17,18],program:[0,2,3,7,8,9,11,13,15,18,19],programm:[15,18],progress:15,project:[20,24],prolog:18,promis:15,prompt:8,proper:[2,3,13,15,24],properti:0,provid:[0,4,8,15,18,24],pun:[0,8],punctuat:18,pure:[0,5],puriti:8,purpos:8,push:[2,3,8,13,19,23],put:[1,2,7,8,15,18,20,23],pypi:0,python3:8,python:[0,2,3,5,11,13,15,19,20,21,23,24],q:[2,3,11,13,15,18,19],quadrat:[0,20],queri:[11,16],query_kei:16,queu:13,quit:[0,16],quot:[0,3,7,8,11,12,13,15,16,18,19,22],quotat:[2,3,13],quotient:3,r0:[9,11,16],r1:[2,3,9,11,13,16],r2:[2,3,13],r:[2,3,5,11,13,18],r_kei:11,r_left:11,r_right:11,r_valu:11,rais:[5,11,18,21,23],rang:[5,8,18],range_revers:13,range_to_zero:8,ranger:13,ranger_revers:13,rankdir:5,raphson:9,rather:[6,8,13,16],ratio:8,re:[0,6,7,8,9,14,18,20,21],reach:[5,6,7,13],read:[0,1,6,7,11,18,19],readabl:14,reader:[5,11],readi:18,real:11,realiz:[4,11],rearrang:[2,11,18,23],reason:[6,8,15,18],rebuild:[16,19],rec1:[2,3,13],rec2:[2,3,13],recent:18,recogn:21,recombin:15,record:[8,22],recur:[3,13,18],recurs:[0,2,3,5,7,8,9,15,18,20,23],recus:8,redefin:20,redistribut:[3,8],redo:5,reduc:[2,18],redund:23,refactor:[8,10],refer:[0,2],referenti:15,reflect:15,regard:15,regist:2,regular:[18,20,21],reifi:17,reimplement:[15,20],rel:23,relat:[5,18],releas:10,rem:3,remain:[2,8,10,18],remaind:[3,9],rememb:5,remind:18,remot:23,remov:[3,11,18,23,24],render:20,repeat:6,repeatedli:6,repetit:5,repl:[0,1],replac:[0,2,3,7,12,13,15,16,18,19,20,23],repositori:0,repr:[5,18],repres:[2,8,11,15,21,22],represent:23,reprod:7,repurpos:18,requir:[15,18,23],research:18,resembl:8,resolut:15,resourc:15,respect:[5,6,15],rest:[3,6,7,8,11,13,19,20,23,24],rest_two:11,restart:[],restor:2,result:[1,2,3,5,6,11,12,13,15,16,18,19],resum:8,retir:2,retri:8,reus:[11,18,23],revers:[3,6,7,13,18,19,20,23],revisit:18,rewrit:[3,8,18],rewritten:8,rid:11,right:[7,8,12,16,18,20,22,23],rightest:11,rightmost:6,rigor:15,risk:18,rk:16,rkei:16,rob:18,roll:[3,9,11,16],roll_dn:18,rolldown:[3,17,18,24],rollup:[3,18,24],root:[3,9,12],round:[3,18],row:5,rrest:[3,17,18,24],rshift:[3,24],rtype:1,rule:[15,20],run:[0,1,3,6,8,9,11,12,13,15,16,18,19],runtim:15,runtimeerror:23,s0:18,s1:[17,18,24],s2:[17,18],s3:18,s4:18,s5:18,s:[0,1,2,3,4,7,8,10,12,13,14,15,16,17,19,20,22,23,24],sai:[5,7,11,12,16,18],same:[2,4,6,11,15,18,23],sandwich:[2,3,13],save:[2,5,6,8],scan:[],scanner:[8,21],scenario:19,scm:24,scope:[7,11],script:1,se:18,search:[0,11],sec:18,second:[3,8,11,13,16,23,24],section:13,see:[0,5,7,8,9,10,12,13,14,18,19,22],seem:[0,6,8,16,18,24],seen:[18,19],select:3,self:[5,15,18],semant:[2,3,8,10,11,15,18],semi:8,send:8,sens:[0,2,6,18,19],separ:[8,15,18,21],seq:18,sequenc:[0,1,2,3,6,8,11,13,14,19,20,21,24],sequence_to_stack:18,seri:[6,7,11,19],set:[2,3,5,13,18,20],seven:[6,7],sever:[0,4,8,13],shape:[5,15],share:[3,8],shelf:2,shew:5,shift:[6,7],shorter:20,shorthand:11,should:[2,3,5,6,11,13,15,18],shouldn:8,show:[4,15,18,19],shunt:[3,19],side:[5,11,17,18,24],sign:[],signatur:24,signifi:[8,11],similar:[11,16,18],simon:8,simpl:[1,5,8,13,23,24],simplefunctionwrapp:[3,14,18],simpler:16,simplest:[18,20],simpli:4,simplifi:[6,11,19],sinc:[2,6,11,18],singl:[3,7,8,14,15,18,21,24],singleton:5,situ:11,situat:11,six:[6,7,8],sixti:[6,7],size:[5,8,20],skeptic:8,skip:18,slight:9,slightli:[11,13,18],smallest:3,smart:11,sn:18,so:[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,24],softwar:8,solei:2,solut:[6,7],solvabl:8,some:[2,3,5,7,8,11,13,15,16,18,20,23,24],somehow:[11,18],someth:[2,10,11,18],sometim:11,somewher:[11,20],sort:[3,5,11,15,18],sort_:3,sourc:[0,1,3,18,20,21,22,23],space:[6,22],span:6,spawn:18,special:[7,11,20],specif:[0,4],specifi:[11,15],speed:14,spell:[5,16],sphinx:[20,23],spirit:[0,1,16],split:[5,18],sqr:[3,8,9,12,19],sqrt:[3,9,18,24],squar:[3,9,18,21],ss:18,stack:[0,1,3,6,7,9,11,12,13,14,15,16,17,19,20,21,22,24],stack_effect:18,stack_effect_com:18,stack_to_str:[17,23],stacki:18,stackjoytyp:18,stacklistbox:23,stackstarjoytyp:18,stage:16,stai:[0,1],stand:[4,5],standard:[8,11],star:[16,18],stare:11,start:[5,6,7,8,9,11,13,16,18,24],state:[8,20],state_nam:5,statement:[3,5],stdout:[17,18],step:[3,6,8,11,14,18,19,20],still:[5,11,18],stop:11,stopiter:5,storag:[6,11],store:[6,13,18],stori:13,str:[1,5,18,21,22,23],straightforward:[5,7,9,18,20],stream:[6,17,18],stretch:11,string:[1,2,3,8,18,19,20,21,22,23],stringi:5,structur:[8,15,16,18,19,20,23],stuck:5,studi:5,stuff:[11,18],stuncon:[3,24],stununcon:[3,24],style:[0,4,18],sub:[3,10,15,24],subclass:8,subject:[15,19],subsequ:15,subset:[18,24],substitut:[5,11,18],subtract:6,subtyp:20,succ:[3,18,24],succe:18,success:9,suck:18,suffic:18,suffici:11,suffix:18,suggest:[4,5,11],suitabl:[1,3,4,6],sum:[3,7,8,12,13,14,16],sum_:[3,18],summand:6,sumtre:16,suppli:[11,21],support:[8,18,22,23],sure:15,suspect:2,svg:[],swaack:[3,12,14,18,19,24],swap:[3,6,7,8,9,11,13,14,15,16,17,19,24],swon:[3,7,8,13,16,18,19,24],swoncat:[7,8,9,13,16],swuncon:13,sy:[17,18,23],sym:5,symbol:[1,2,3,5,15,18,19,20,21,22],symboljoytyp:18,symmetr:[6,11],symmetri:5,syntact:8,syntax:[8,23],system:[8,11,15],t0:3,t1:3,t:[2,3,5,6,8,10,11,13,15,18,19,23],tabl:[5,18],tag:[5,18,24],tail:[9,11,18,20,23],tailrec:[3,9],take:[3,5,6,8,9,11,13,15,18,23],talk:[8,11,18,23],target:19,tast:4,tbd:8,te:11,tear:13,technic:2,techniqu:[4,19],technolog:2,temporari:19,ten:6,term:[1,2,5,8,9,13,15,18,20,21,23,24],termin:[2,3,5,13],ternari:8,test:[2,3,13],text:[0,1,18],text_to_express:[8,17,21],textual:8,than:[0,3,5,6,7,8,9,13,15,16,18,23,24],thei:[2,5,6,7,8,11,13,15,18,19,21,23],them:[2,5,6,7,11,13,15,18,19,20,24],themselv:[15,18],theori:[2,3,13,15],therefor:7,thi:[0,1,2,3,4,5,6,7,8,9,12,13,15,16,18,19,20,21,22,23,24],thing:[2,7,11,13,15,18,19,21,23,24],think:[2,6,8,11,13,15,16,18],third:[3,7,8,11,24],thirti:6,those:[2,3,5,11,13,18,20,24],though:[6,15],thought:[8,15],thousand:6,thread:[2,15],three:[2,3,5,6,8,11,12,16,18,20],through:[1,6,8,16,18,19,23,24],thun:[2,3,4,10,13,15],thunder:8,thunk:15,time:[3,5,6,8,9,11,13,15,18,19],titl:18,to_check:5,to_index:23,to_set:11,todai:8,todo:[8,21],togeth:[7,8,15,18,20],token:21,toler:20,too:[5,13,18],tool:[8,18],tooo:18,top:[2,3,8,13,18,22,23],total:6,tower:18,trace:[0,8,12,13,19,20,23],traceback:18,traceprint:22,track:[12,18,19],tracker:0,transform:4,transit:5,translat:[4,12,18],trap:5,travers:[0,20],treasur:0,treat:[0,2,3,13,18,20],treatment:7,tree:[0,8,20],treegrind:20,treestep:[0,20],tri:6,triangl:15,triangular_numb:13,trick:[6,18],tricki:18,trobe:0,trove:0,truediv:24,truthi:[3,8,15,18],ts:16,tuck:[3,8,18,24],tupl:[3,5,8,18,23],turn:[2,3,5,18],twice:[11,13],two:[2,3,6,8,9,11,12,13,15,16,17,18,19,20,23,24],txt:[],type:[0,1,4,8,11,13,15,20,21,22,23],typeerror:18,typeless:18,typic:[2,3,12,13],u:[17,18],uh:18,ui:8,unari:8,unarybuiltinwrapp:3,unbalanc:[11,21],unbound:24,unchang:11,uncompil:18,uncon:[3,7,8,11,13,16,19,24],under:[2,3,8,11],underli:[5,15,18],underscor:18,understand:[0,11],undistinguish:11,undocu:8,unfinish:5,unfortun:23,unicod:18,unif:[18,20],unifi:17,union:5,uniqu:[3,5,11,18],unit:[3,8,13,15,24],univers:[0,8,15,18],unknownsymbolerror:1,unlik:15,unnecessari:20,unnecesssari:18,unpack:[2,3,11,23],unpair:6,unquot:[8,16,21],unrol:5,unstack:18,unswon:[3,24],untangl:13,until:[5,7,15],unus:6,unusu:11,unwrap:5,up:[1,2,3,6,7,8,11,13,14,15,18,19,23],updat:[0,17,20,24],uppercas:5,upward:15,us:[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,19,20,21,23,24],usag:8,user:16,usual:[0,2,13],util:[0,3,14,17,18],uu:18,v0:24,v:[2,6,7,9,11,12,13,14,16,19,20],valid:18,valu:[0,1,2,3,6,8,9,12,13,14,15,16,18,20,21,23,24],value_n:11,valueerror:[5,18,23],variabl:[18,20],variant:11,variat:[13,15,20],varieti:[4,8],variou:0,ve:[11,18],vener:23,verbos:4,veri:[0,1,4,5,8,11,23],versa:[2,18],version:[0,1,2,5,7,10,16,19,20],vi:20,via:8,vice:[2,18],view:[11,20],viewer:[1,8,10,22],vii:20,visibl:18,von:[0,2,3,4,13],vs:18,vv:18,w:[3,11,13,16,18],wa:[2,6,8,11,15,18,23],waaaai:5,wai:[0,2,3,4,5,6,8,13,14,15,18],wait:15,want:[2,6,7,9,11,13,18],warranti:[3,8],wash:8,wast:8,we:[2,5,6,7,8,9,10,12,13,14,15,18,19,20,23],web:23,websit:[0,6],welcom:8,well:[0,4,8,9,11,18,21],went:18,were:[8,18,19],what:[2,3,4,5,8,11,13,15,16,18,22],whatev:[2,3,13,16,23],when:[6,7,8,11,13,15,18,19,21,23,24],where:[2,3,5,8,11,13,18,20,23],whether:[3,13],which:[0,1,3,5,6,8,9,11,13,15,16,18,19,21,23,24],whole:[2,3,6,13,16,18],whose:7,why:[9,15,16],wiki:11,wikipedia:[0,11,19],wildli:8,wind:8,wire:13,within:[8,11,14,20],without:[2,8,11,12,15,18],won:[11,18,23],word:[0,3,6,8,13,19],work:[0,3,5,6,7,8,9,11,12,13,15,16,19,20,23,24],worker:15,worri:15,worth:6,would:[2,6,7,8,9,11,13,15,18,19,23],wrap:[3,8],wrapper:18,write:[4,5,9,11,13,15,16,18,19,20,23],written:[0,1,9,11,14,18,23],wrong:2,wrote:18,x:[0,3,5,6,8,9,15,19,20],xor:3,xrang:18,y:[2,3,5,15],yang:18,yeah:15,year:[8,18],yet:[11,15,18,19],yield:[2,3,13,18,23],yin:20,you:[0,2,3,5,6,7,8,10,11,12,13,14,15,16,18,19,22,23,24],your:[2,3,8,13,18],yourself:[5,8,11],z:[3,5,15,18,20],zero:[3,5,11,13,15,16,18,21,23],zerodivisionerror:18,zip:[3,5,6,18],zip_:3,zipper:[0,20],zstr:19},titles:["Thun 0.4.1 Documentation","Joy Interpreter","Functions Grouped by, er, Function with Examples","Function Reference","Categorical Programming","\u2202RE","Developing a Program in Joy","Using x to Generate Values","Thun: Joy in Python","Newton\u2019s method","No Updates","Treating Trees I: Ordered Binary Trees","Quadratic formula","Recursion Combinators","Replacing Functions in the Dictionary","The Four Fundamental Operations of Definite Action","Treating Trees II: treestep","Type Checking","The Blissful Elegance of Typing Joy","Traversing Datastructures with Zippers","Essays about Programming in Joy","Parsing Text into Joy Expressions","Tracing Joy Execution","Stack or Quote or Sequence or List\u2026","Type Inference of Joy Expressions"],titleterms:{"0":0,"01":5,"1":0,"11":5,"111":5,"2":[7,12,18],"2a":12,"3":[6,18],"4":[0,12,18],"466":7,"5":6,"\u03bb":5,"\u03d5":5,"case":[9,11],"do":16,"function":[2,3,5,8,9,11,13,14,15,16,18],"long":14,"new":11,"p\u00f6ial":18,"try":5,"void":2,"while":[2,15],A:[5,6,7,9,11,14],If:11,In:[11,16],No:[5,10],One:[7,11],The:[6,8,11,13,15,16,18],There:8,With:[5,16],about:20,action:15,ad:11,add:[2,11],address:19,al:13,alphabet:5,altern:16,an:[6,7,8,11,17,18,19],ana:13,analysi:6,anamorph:[2,13],app1:2,app2:2,app3:2,appendix:[11,13,18],appli:15,approxim:9,ar:11,argument:18,auto:3,averag:2,b:[2,12],base:[9,11],binari:[2,11,16],bliss:18,both:11,branch:[2,11,15],brzozowski:5,c:[12,18],can:11,cata:13,catamorph:13,categor:4,chatter:2,check:17,child:11,choic:2,clear:2,cleav:[2,15],cmp:11,code:[8,11],combin:[2,11,13,18],comment:18,compact:5,compar:11,comparison:2,compil:[7,18],compile_:18,compos:18,comput:9,con:[2,18],concat:2,conclus:[13,18],consecut:9,continu:8,current:11,datastructur:[5,8,11,19],deal:18,defin:[11,16],definit:[12,15],delabel:18,delet:11,deriv:[5,12,13,16],design:13,determin:19,develop:6,diagram:5,dialect:0,dictionari:14,dip:[2,19],dipd:2,dipdd:2,direco:7,disenstacken:2,distinguish:18,div:2,doc_from_stack_effect:18,document:0,doe:11,down_to_zero:2,drive:5,drop:2,dup:[2,18],dupd:2,dupdip:2,e:16,effect:18,eleg:18,els:11,empti:11,enstacken:2,equal:11,er:2,essai:20,et:13,euler:[6,7],eval:8,even:7,exampl:[2,8,11,13,16,17],execut:22,explor:5,express:[5,8,21,24],extract:16,f:11,factori:13,fail:17,fibonacci:7,filter:6,find:[9,11,13],finish:15,finit:5,first:[2,6,15,18],five:7,flatten:2,flexibl:16,floordiv:2,formula:12,found:11,four:[13,15],from:[],fsm:5,fulmin:15,fun:13,fundament:15,further:6,gcd:2,gener:[3,5,6,7,9],genrec:2,get:[11,16],getitem:2,given:16,greater:11,group:2,h1:13,h2:13,h3:13,h4:13,handl:15,have:[11,16],help:2,highest:11,host:0,how:[6,7],hybrid:18,hylo:13,hylomorph:13,i:[2,5,11,18],identifi:18,ift:[2,15],ii:[16,18],iii:18,implement:[5,18],indic:0,infer:[18,24],inferenc:18,inform:0,infra:[2,19],integ:6,interest:7,interlud:11,intern:21,interpret:[1,8,18],item:19,iter:[6,11],iv:18,joi:[0,1,3,6,8,13,18,19,20,21,22,23,24],join:15,just:6,kei:11,kind:15,languag:0,larger:5,least_fract:2,left:11,less:11,let:[5,6],letter:5,librari:[3,8,18],like:11,list:[2,23],literari:8,littl:6,logic:[2,18],loop:[2,8,15],lower:11,lshift:2,machin:5,make:[7,9],mani:6,map:[2,15],match:5,math:2,memoiz:5,method:9,min:2,miscellan:2,mod:2,modifi:18,modulu:2,more:11,most:11,mul:[2,18],multipl:[6,7,18],must:11,n:[],name:12,ne:2,neg:2,newton:9,next:9,node:11,non:11,now:11,nullari:2,nulli:5,number:[13,18],one:8,onli:8,oper:15,order:[11,16],osdn:0,other:15,our:11,out:5,over:2,p:16,pack:6,pam:[2,15],para:13,paradigm:18,parallel:15,parameter:[11,16],pars:[2,21],parser:[8,21],part:18,pass:8,path:19,pattern:13,per:11,pop:[2,18],popd:2,popop:2,pow:2,power:7,pred:2,predic:[6,9,11,16],pretty_print:22,primit:13,primrec:2,print:8,problem:[6,7],process:11,product:2,program:[4,6,12,16,20],progress:18,project:[0,6,7],pure:8,put:[11,12,16],python:[8,14,18],quadrat:12,quick:0,quot:[2,23],rang:[2,6,13],range_to_zero:2,re:[5,11],read:8,recur:[9,11],recurs:[11,13,16],redefin:[11,16],refactor:[6,11],refer:3,regular:[5,8],reimplement:16,relabel:18,rem:2,remaind:2,remov:2,render:6,repl:8,replac:[11,14],repres:[5,18],represent:5,reset:7,rest:[2,18],revers:[2,5,17],right:[11,19],rightmost:11,roll:[2,18],rolldown:2,rollup:2,rshift:2,rule:[5,18],run:[2,7],s:[5,6,9,11,18],second:[2,18],select:2,sequenc:[7,15,18,23],set:[9,11],shorter:14,should:8,shunt:2,simpl:18,simplest:6,size:[2,14],sourc:11,special:[13,18],sqr:[2,18],sqrt:[2,12],stack:[2,8,18,23],start:0,state:5,step:[2,13,16],straightforward:12,stream:5,string:5,structur:11,style:8,sub:[2,11],subtyp:18,succ:2,sum:[2,6],swaack:2,swap:[2,18],swon:2,swoncat:2,symbol:[8,13],t:16,tabl:0,tail:13,take:2,term:[6,7,16],ternari:2,text:21,than:11,them:12,thi:11,third:[2,18],three:7,thun:[0,8],time:[2,7],togeth:[11,12,16],token:8,toler:9,trace:[14,22],traceprint:8,trampolin:5,travers:[11,16,19],treat:[11,16],tree:[11,16,19],treegrind:16,treestep:16,triangular:13,truediv:2,truthi:2,tuck:2,two:[5,7],type:[17,18,24],unari:2,unbound:18,uncon:[2,18],unif:17,unifi:18,unit:2,unnecessari:6,unquot:2,unstack:2,up:9,updat:[10,18],us:[7,18],util:[22,23,24],v:18,valu:[7,11],variabl:12,variat:7,version:[6,11,14,18],vi:18,view:8,vii:18,we:[11,16],which:[],within:9,word:2,work:[17,18],write:12,x:[2,7],xor:2,yin:18,z:19,zero:7,zip:2,zipper:19}}) \ No newline at end of file +Search.setIndex({docnames:["index","joy","lib","library","notebooks/Categorical","notebooks/Derivatives_of_Regular_Expressions","notebooks/Developing","notebooks/Generator_Programs","notebooks/Intro","notebooks/Newton-Raphson","notebooks/NoUpdates","notebooks/Ordered_Binary_Trees","notebooks/Quadratic","notebooks/Recursion_Combinators","notebooks/Replacing","notebooks/Square_Spiral","notebooks/The_Four_Operations","notebooks/Treestep","notebooks/TypeChecking","notebooks/Types","notebooks/Zipper","notebooks/index","parser","pretty","stack","types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst","joy.rst","lib.rst","library.rst","notebooks/Categorical.rst","notebooks/Derivatives_of_Regular_Expressions.rst","notebooks/Developing.rst","notebooks/Generator_Programs.rst","notebooks/Intro.rst","notebooks/Newton-Raphson.rst","notebooks/NoUpdates.rst","notebooks/Ordered_Binary_Trees.rst","notebooks/Quadratic.rst","notebooks/Recursion_Combinators.rst","notebooks/Replacing.rst","notebooks/Square_Spiral.rst","notebooks/The_Four_Operations.rst","notebooks/Treestep.rst","notebooks/TypeChecking.rst","notebooks/Types.rst","notebooks/Zipper.rst","notebooks/index.rst","parser.rst","pretty.rst","stack.rst","types.rst"],objects:{"joy.joy":[[1,1,1,"","UnknownSymbolError"],[1,2,1,"","interp"],[1,2,1,"","joy"],[1,2,1,"","repl"],[1,2,1,"","run"]],"joy.library":[[3,2,1,"","BinaryBuiltinWrapper"],[3,3,1,"","Def"],[3,2,1,"","FunctionWrapper"],[3,2,1,"","SimpleFunctionWrapper"],[3,2,1,"","UnaryBuiltinWrapper"],[3,2,1,"","add_aliases"],[3,2,1,"","app1"],[3,2,1,"","app2"],[3,2,1,"","app3"],[3,2,1,"","b"],[3,2,1,"","branch"],[3,2,1,"","choice"],[3,2,1,"","clear"],[3,2,1,"","cmp_"],[3,2,1,"","concat_"],[3,2,1,"","cond"],[3,2,1,"","dip"],[3,2,1,"","dipd"],[3,2,1,"","dipdd"],[3,2,1,"","disenstacken"],[3,2,1,"","divmod_"],[3,2,1,"","drop"],[3,2,1,"","dupdip"],[3,2,1,"","floor"],[3,2,1,"","gcd2"],[3,2,1,"","genrec"],[3,2,1,"","getitem"],[3,2,1,"","help_"],[3,2,1,"","i"],[3,2,1,"","id_"],[3,2,1,"","infra"],[3,2,1,"","initialize"],[3,2,1,"","inscribe"],[3,2,1,"","inscribe_"],[3,2,1,"","loop"],[3,2,1,"","map_"],[3,2,1,"","max_"],[3,2,1,"","min_"],[3,2,1,"","parse"],[3,2,1,"","pm"],[3,2,1,"","pred"],[3,2,1,"","primrec"],[3,2,1,"","remove"],[3,2,1,"","reverse"],[3,2,1,"","select"],[3,2,1,"","sharing"],[3,2,1,"","shunt"],[3,2,1,"","sort_"],[3,2,1,"","sqrt"],[3,2,1,"","step"],[3,2,1,"","succ"],[3,2,1,"","sum_"],[3,2,1,"","take"],[3,2,1,"","times"],[3,2,1,"","unique"],[3,2,1,"","void"],[3,2,1,"","warranty"],[3,2,1,"","words"],[3,2,1,"","x"],[3,2,1,"","zip_"]],"joy.parser":[[22,1,1,"","ParseError"],[22,3,1,"","Symbol"],[22,2,1,"","text_to_expression"]],"joy.utils":[[3,0,0,"-","generated_library"],[23,0,0,"-","pretty_print"],[24,0,0,"-","stack"]],"joy.utils.generated_library":[[3,2,1,"","ccons"],[3,2,1,"","cons"],[3,2,1,"","dup"],[3,2,1,"","dupd"],[3,2,1,"","dupdd"],[3,2,1,"","first"],[3,2,1,"","first_two"],[3,2,1,"","fourth"],[3,2,1,"","over"],[3,2,1,"","pop"],[3,2,1,"","popd"],[3,2,1,"","popdd"],[3,2,1,"","popop"],[3,2,1,"","popopd"],[3,2,1,"","popopdd"],[3,2,1,"","rest"],[3,2,1,"","rolldown"],[3,2,1,"","rollup"],[3,2,1,"","rrest"],[3,2,1,"","second"],[3,2,1,"","stack"],[3,2,1,"","stuncons"],[3,2,1,"","stununcons"],[3,2,1,"","swaack"],[3,2,1,"","swap"],[3,2,1,"","swons"],[3,2,1,"","third"],[3,2,1,"","tuck"],[3,2,1,"","uncons"],[3,2,1,"","unit"],[3,2,1,"","unswons"]],"joy.utils.pretty_print":[[23,3,1,"","TracePrinter"],[23,2,1,"","trace"]],"joy.utils.pretty_print.TracePrinter":[[23,4,1,"","go"],[23,4,1,"","viewer"]],"joy.utils.stack":[[24,2,1,"","concat"],[24,2,1,"","dnd"],[24,2,1,"","expression_to_string"],[24,2,1,"","iter_stack"],[24,2,1,"","list_to_stack"],[24,2,1,"","pick"],[24,2,1,"","stack_to_string"]],joy:[[1,0,0,"-","joy"],[3,0,0,"-","library"],[22,0,0,"-","parser"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","function","Python function"],"3":["py","class","Python class"],"4":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:function","3":"py:class","4":"py:method"},terms:{"0":[2,3,5,6,7,8,9,10,11,12,14,15,17,18,19,25],"0000000001585":9,"000000001":9,"01":[6,7],"03":19,"05":5,"0a":19,"0b":[6,7],"0b11100111011011":6,"1":[2,3,5,6,7,8,9,10,11,12,14,15,17,18,19,20,24,25],"10":[2,5,6,7,13,19,25],"100":[5,17,19],"1000":[5,6,7,19],"10000":[5,19],"10001":5,"1001":[5,19],"10010":5,"10011":5,"1002":19,"101":5,"1010":5,"10100":5,"10101":5,"1011":5,"10110":5,"10111":5,"102":17,"1024":2,"103":17,"104":17,"105":17,"106":17,"107":17,"108":17,"109":17,"10946":7,"11":[2,6,7,19,25],"110":[5,6],"1100":5,"11000":5,"11001":5,"1101":5,"11010":5,"11011":5,"1110":5,"11100":5,"11101":5,"1111":5,"11110":5,"11111":5,"12":[2,6,17],"120":13,"122":5,"123":8,"128":7,"13":[2,7,17,25],"1346269":7,"14":[2,6,17],"144":7,"14811":[6,7],"15":[2,6,13,17,19,25],"16":[2,7,12,17,25],"160":2,"17":[11,15,17],"18":[6,8,14,15,17,23],"19":[17,19,25],"196418":7,"1a":19,"1b":19,"2":[2,3,5,6,8,9,10,11,13,14,17,18,20,24,25],"20":[2,6,14,19,25],"2006":19,"2017":[8,19],"2020":25,"207":2,"21":[6,7],"22":[9,19,25],"23":[2,6,7,8,9,11,14,15,17,19,23],"230":7,"231":[6,7],"232":7,"233":7,"233168":[6,7],"234":7,"23rd":19,"24":[2,6,7],"25":[6,7,12,17,18,20,25],"256":7,"2584":7,"26":[2,5,7,19,25],"27":[6,7],"273":10,"28":[7,18,25],"29":[19,25],"2a":19,"2b":19,"3":[2,3,7,8,10,11,12,13,17,18,20,21,24,25],"30":[2,6,19,25],"31":18,"32":[2,7,17],"33":6,"34":[7,18,19,25],"36":9,"37":[18,19,25],"3702":[6,7],"38":[19,25],"3819660112501051":12,"3b":19,"3i":19,"4":[2,6,7,8,9,11,13,17,18,20,24,25],"40":[2,18,19],"4000000":7,"41":[14,19,25],"414":23,"44":[11,17,19,25],"45":[2,6],"46":19,"4613732":7,"46368":7,"466":6,"47":[19,25],"48":[19,25],"49":[17,19,25],"4ac":12,"4m":7,"5":[2,3,5,7,8,11,12,13,14,17,19,21,25],"50":2,"513":23,"529":[2,8],"53":[19,25],"547":8,"55":[6,7],"552":2,"5555555555555554":2,"56":[19,25],"57":[6,7],"5bkei":11,"5d":11,"6":[2,6,9,11,13,17,19,20],"60":6,"610":7,"618033988749895":12,"625":20,"64":7,"66":[6,7],"6945":6,"7":[2,6,7,11,17,19,20,25],"75":2,"795831523312719":[2,9],"8":[2,5,6,7,11,12,17,19,20,25],"80":6,"832040":7,"88":11,"8888":8,"89":7,"9":[2,6,11,12,17,19,25],"90":2,"92":5,"925":6,"978":6,"980":6,"981":6,"984":6,"985":6,"987":6,"99":23,"990":6,"991":6,"992":6,"993":6,"995":6,"996":6,"999":[6,7],"999999999999996":9,"9a9d60354c35":19,"\u03b4":5,"\u03b5":9,"abstract":[8,11],"boolean":[2,3,8,11,16],"break":[5,8,15,19],"byte":[5,6],"case":[2,3,13,16,17,19,24],"char":5,"class":[3,5,8,19,22,23,24],"const":15,"default":[3,7,11,24],"do":[2,3,4,5,6,7,8,11,13,14,15,16,19,20,21],"export":[3,22],"final":[2,11,13,15],"float":[8,19,20,22],"function":[0,1,4,6,7,10,12,15,18,20,21,22,23,24,25],"g\u00e9rard":20,"goto":5,"import":[2,5,6,7,9,11,12,13,14,15,17,18,19,20],"int":[5,7,8,13,15,19,20,22,24],"long":[11,15,19,21],"new":[0,2,3,5,7,8,10,13,14,15,19],"p\u00f6ial":21,"p\u00f6ial06typingtool":19,"public":10,"return":[1,3,5,6,8,11,13,14,16,17,19,22,23,24],"short":15,"static":[2,10],"super":19,"switch":[2,19],"throw":[11,25],"true":[2,3,5,6,13,15,16,19],"try":[7,9,12,13,15,17,18,19,21],"void":[0,3,15],"while":[3,5,8,11,19,22,24],A:[1,3,4,8,13,16,19,21,22,23,24],AND:[5,19],And:[5,6,7,9,11,13,15,16,19,20,24],As:[4,6,11,15,19],At:[6,13,19],Be:2,But:[0,4,6,7,8,11,14,15,19],By:[7,11,19],For:[0,2,3,11,13,14,19,21,24],If:[2,3,5,6,7,8,9,10,12,13,15,17,19,20],In:[2,3,4,6,7,8,13,16,19,20,21,24],It:[0,2,3,4,5,6,7,8,10,11,13,15,19,20,24,25],Its:3,NO:8,NOT:5,No:[0,17,21],Not:19,OR:[5,19],Of:6,On:[3,23],One:[2,8,16,19,21],Or:[5,10,11,15,17,19],TOS:[2,3],That:[6,11],The:[0,1,2,3,4,5,7,9,10,12,20,21,22,23,24,25],Then:[2,3,11,12,13,19],There:[5,12,13,15,16,17,19,24],These:[16,19,21,24],To:[0,5,6,7,9,11,13,17,19],With:[9,13,15,19,21,25],_0:5,_1000:19,_1:5,_:[8,14,19],__:11,__add__:19,__call__:5,__class__:19,__eq__:19,__ge__:19,__hash__:19,__init__:[5,19],__main__:19,__radd__:19,__repr__:19,__str__:23,_and:5,_compaction_rul:5,_con:5,_dictionari:19,_f:19,_ge:19,_infer:19,_interpret:19,_log:19,_log_it:19,_names_for:19,_or:5,_r:19,_spn_e:15,_spn_p:15,_spn_t:15,_templat:5,_to_str:19,_tree_add_:11,_tree_add_e:[3,11,25],_tree_add_p:11,_tree_add_r:11,_tree_add_t:11,_tree_delete_:11,_tree_delete_clear_stuff:[3,11,25],_tree_delete_del:11,_tree_delete_r0:[3,11,25],_tree_delete_r1:11,_tree_delete_rightmost:11,_tree_delete_w:11,_tree_get_:[3,11,25],_tree_get_p:11,_tree_get_r:11,_tree_get_t:11,_tree_iter_order_curr:11,_tree_iter_order_left:11,_tree_iter_order_r:11,_tree_iter_order_right:11,_tree_t:11,_treestep_0:17,_treestep_1:17,_uniqu:19,_within_b:9,_within_p:9,_within_r:9,a0:19,a10001:19,a10002:19,a10003:19,a10004:19,a1:[3,18,19,25],a2:[3,18,19,25],a3:[3,18,19,25],a4:[3,18,19,25],a5:[18,19,25],a_:9,a_i:9,aa:13,ab:[0,3,5,9,15],abbrevi:17,abl:[5,16,19,25],about:[0,8,11,16,19,20,24],abov:[0,5,6,9,11,13,16,19],absolut:8,ac:5,accept:[0,1,2,3,5,6,7,8,11,12,14,15,16,17,19,20],accord:5,accordingli:[11,16],accumul:6,act:[5,25],action:[0,8,14,15,19,20,21],actual:[2,6,8,11,16,19],ad:[4,5,8,10,14,19,21],adapt:[15,21],add:[3,5,6,7,8,14,19,23,25],add_alias:3,add_def:[],add_definit:[11,17],addit:[0,2,3,6,8,13,14,17],address:21,adjust:11,advantag:19,affect:[3,16],after:[5,6,7,8,13,16,19,24,25],afterward:8,again:[2,3,6,8,11,13,19],against:19,aggreg:20,ahead:19,aka:[5,8,20,25],al:[16,19],albrecht:0,algorithm:[5,8,19],alia:3,alias:[3,8],align:[8,23],all:[3,5,6,7,8,11,13,14,15,16,17,19,23,24],alloc:19,allow:[10,11,16],almost:11,along:[5,8,13,19],alphabet:[3,21],alreadi:[5,9,14,19,20],also:[0,5,6,8,11,16,19,23,24],alter:[5,19],altern:[4,19],although:[4,11],altogeth:7,alwai:[6,10,13,16],am:[16,21],amend:16,among:19,amort:11,an:[0,1,2,3,4,5,9,14,15,17,21,24,25],analysi:[4,21],anamorph:[8,21],and_:3,ani:[0,4,5,6,8,10,11,15,16,19,20,22],annual:8,anonym:11,anoth:[5,11,16,19,24,25],anyhow:[16,19],anyjoytyp:19,anymor:19,anystarjoytyp:19,anyth:[2,3,5,8,19,25],apart:19,api:10,app1:3,app2:[3,8,12,13,14,16],app3:[3,16],app:8,appear:[2,4,5,6,11],append:19,appendix:21,appli:[2,3,6,7,11,13,15,19],applic:7,approach:6,appropri:5,approxim:21,ar:[1,2,3,5,6,7,8,10,12,13,16,17,19,20,21,22,24,25],archiv:0,aren:20,arg:[2,3,15],argument:[2,3,8,9,12,13,15,21,23,24],arithmet:2,ariti:[2,16],around:[6,19,22,24],arrang:[15,17],arriv:[7,17],arrow:5,articl:[0,4,7,13],ascii:5,ascii_lowercas:5,ask:[4,7,19],aspect:0,assembl:[5,15],assert:[5,19],assign:[16,24],associ:11,assum:9,asterisk:17,asterix:[19,25],asyncron:16,attack:8,attempt:[0,1,19],attribut:3,attributeerror:19,author:19,auto:[0,19,25],automat:[4,16,19],auxiliari:[5,17],avail:[0,19,25],averag:[8,14],avoid:11,awai:[11,19],awar:2,awkward:[11,13,19],azur:21,b0:3,b1:[3,19,25],b2:25,b3:25,b:[3,5,7,8,9,11,13,16,17,19],back:[3,11,19],backtrack:25,backward:[10,11,12,17],bad:19,bag:8,banana:13,bar:16,barb:13,base:[0,2,3,10,13,17,19],basic:[2,3,8,11],basicconfig:[18,19],bc:5,bd:5,becaas:5,becaus:[2,3,5,8,11,16,17,19,20,24],becom:[0,11,15,17,24],becuas:19,been:[5,9,10,11,19,20],befor:[5,7,8,11],begin:[11,17],behavior:[10,17,25],behaviour:[0,1,19],behind:16,being:[0,16],below:[2,3,5,6,7,11,15,19,20],bespok:8,best:0,better:[6,11,13,19],between:[0,6],beyond:7,biannual:8,bin:5,binari:[0,7,8,21],binary_search_tre:11,binarybuiltinwrapp:3,bind:8,bingo:20,bit:[5,6,7,11,19],blank:22,bliss:[0,21],block:6,bodi:[2,3,5,8,11,16],body_text:[],booktitl:19,bool:[3,13,19,25],borrow:[8,19],both:[2,6,8,12,13,14,15,16,19,24],bottom:7,bounce_to:5,bracket:[8,19,22],branch:[3,5,6,7,13,19,21,25],branch_fals:19,branch_tru:19,breakpoint:8,bring:[6,8,19],bruijn:19,brutal:16,brzozowski:[19,21],brzozowskian:5,btree:[11,17],buck:11,bug:[0,8],build:[7,8,12,13,15,20,24],built:[12,19],bullet:23,bundl:[2,3,13],burgeon:8,c:[0,1,2,3,5,7,9,11,13,15,16,17],calculu:4,call:[1,2,5,8,10,11,13,16,19,23,24],caller:[11,19],can:[0,2,3,4,5,6,7,8,9,10,12,13,14,15,16,17,19,20,21,22,24,25],cancel:16,cannot:[18,19,22],captur:8,card:8,care:[6,24],carefulli:20,carri:[7,11],cartesian:4,catamorph:21,categor:[0,21],categori:[4,16],ccc:4,ccon:[3,11,18,19,25],cell:[13,19],certain:[8,24],certainli:11,cf:[7,9,12,13],chain:[3,16],chang:[2,10,11,15,19,20],charact:[5,20],chat:8,chatter:[0,19],check:[0,7,9,19,21],child:17,choic:[3,13],choos:10,chop:12,chose:5,cinf:11,circl:5,circuit:[4,15],cite_not:11,classmethod:[],claus:[3,19],clean:19,clear:[3,6,8],clear_stuff:11,cleav:[8,12,14],client:24,close:[0,1,4],clunki:[6,19],clv:16,cmp:[3,17,21],cmp_:3,code:[1,4,5,12,13,16,19,21,25],codireco:[7,9,15],collaps:13,collect:[4,5,7,8,19],combin:[0,3,6,7,8,9,12,15,16,17,20,21,23,25],combinatorjoytyp:19,come:[8,11,19],command:[8,11,19],comment:16,common:[2,6,16],compar:[3,4,5,15,19],comparison:[0,11],compat:16,compel:4,compil:[2,3,4,5,8,11,14,16,21,25],complement:5,complet:4,complex:[3,16,19,20,25],complic:19,compos:[5,25],composit:19,compostit:19,compound:11,comput:[2,4,5,6,8,12,15,16,19,25],con:[3,5,6,7,8,9,11,12,13,15,16,17,20,24,25],conal:[4,16],concat:[3,7,8,16,17,19,24],concat_:3,concaten:[0,5],concatin:[0,3,5,24],concern:16,conclus:21,concurr:2,cond:[3,11],condit:[3,8],condition:15,confer:19,conflict:[11,19],consecut:21,consid:[5,6,7,11,13,17,19,20],consist:[2,7,8,16,17],constant:11,constitu:13,constraint:15,construct:[0,15,16,19],consum:[15,16,19],contain:[0,2,3,5,7,8,13,15,19,22],content:19,context:2,conting:11,continu:[0,5,13,19,20],control:8,conveni:[4,16,19],convent:16,convers:19,convert:[13,14,17,19,22,24],cool:11,coordin:[0,15],copi:[2,3,6,11,13,15,16,17,18,21],copyright:8,correspond:[4,16],could:[2,4,5,6,8,10,11,16,19,20],couldn:16,count:[3,19],counter:[6,19],coupl:17,cours:[6,11,19],cout:15,cover:19,cp:8,cpu:16,crack:11,crash:11,creat:[0,2,3,6,9,11,16,19],creativ:19,crude:[11,19,22],cruft:19,curent:25,current:[2,3,8,13,15,16,17,19,20,23,25],curri:5,custom:10,cycl:[6,7],cython:8,d010101:5,d0101:5,d01:5,d0:5,d10:5,d1:5,d:[2,3,5,11,13,14,16,17,18,19,20],d_compact:5,dai:8,data:[2,3,5,13],datastructur:[0,2,13,19,21,22,24],datatyp:24,ddididi:20,de:[19,20],deal:[0,5,11,16],dealt:19,debugg:19,decid:11,declar:19,decor:3,decoupl:13,decrement:[0,3],deduc:[6,19],deeper:0,deepli:4,def:[3,5,8,13,14,19,24],defaultdict:[5,19],defi:[],defin:[2,4,5,6,7,8,9,10,12,13,14,15,16,19,20,21],definit:[0,2,3,6,7,8,10,11,13,15,17,19,21,25],definitionwrapp:[11,13,17],defint:16,del:18,deleg:8,delet:21,deliber:19,demo:19,demonstr:4,depend:[3,11,13,16],deposit:17,depth:[19,25],dequot:13,der:11,deriv:[2,3,6,8,9,11,19,21],derv:5,describ:[4,5,11,13,16,17,19,22],descript:[6,8],descriptor:19,design:[2,3,11,16,21],desir:[8,17],destin:5,destruct:11,detail:[8,11,19],detect:[5,7,11,13,19],determin:21,develop:[0,7,8,19,21],diagram:6,dialect:1,dict:[1,3,5,19,23],dictionari:[0,1,3,8,19,21,23],did:19,differ:[0,4,6,9,11,12,13,16,24],differenti:4,difficult:19,difficulti:16,dig:[11,20],digit:6,digraph:5,dinfrirst:[8,15,19,25],dip:[0,3,6,7,8,9,11,12,13,14,15,16,17,19,21,25],dipd:[3,7,8,11,12,13,15,16,19,20,25],dipdd:[3,11],direco:21,direct:8,directli:[6,16,17,19,24],disappear:[2,5,19],discard:[3,7,9,11,13],disciplin:11,disenstacken:[3,8],disk:8,displac:2,displai:19,distiguish:19,distribut:16,ditch:11,div:[3,8,19,25],dive:17,divis:[11,19],divmod:[3,25],divmod_:[3,19],dnd:24,doc:[2,3,8,19],doc_from_stack_effect:18,docstr:19,document:[19,21,22,24],doe:[0,1,3,4,5,7,8,14,16,19,21,23,25],doesn:[6,10,11,15,16,17,19,24],domain:[4,19],don:[5,6,8,11,19],done:[2,6,8,10,19],dooooc:19,door:8,dot:[5,23],doubl:[5,6,8,19],doublecircl:5,down:[2,5,9,13,20,25],down_to_zero:8,dozen:8,dr:5,draft:[4,10],drag:24,dream:8,drive:[7,9],driven:6,driver:[5,7],drop:[3,11,24],ds:5,dudipd:8,due:19,dup:[3,6,7,8,9,11,12,13,15,16,18,20,24,25],dupd:[3,19,25],dupdd:[3,25],dupdip:[3,6,11,12,13,15],duplic:[3,11,13],durat:2,dure:[2,13],e:[2,3,5,7,8,10,11,14,16,18,19,20,23,24],each:[2,3,4,5,6,8,13,14,15,16,17,19,23,25],easi:[0,11,15,17,19,20],easier:[3,11,16],easili:4,eat:5,edit:21,ee:[11,19],effect:[2,3,5,8,16,20,21,25],effici:[7,14,20],efg:19,eh:19,either:[1,2,3,5,11,13,19],el:24,elabor:19,eleg:[0,5,8,11,16,21],element:[2,3],elif:19,elimin:[5,19],elliott:[4,16],els:[2,3,5,13,15,16,19],else_:19,embed:[4,11,20],emit:19,empti:[3,5,8,17,19,24,25],en:11,encapsul:8,enclos:8,encod:7,encount:19,end:[5,6,11,13,17,19,24],endless:7,enforc:[2,8],engend:8,enough:[5,8,13,23,25],enstacken:[7,8,19],enter:8,enter_guard:19,entir:24,entri:[3,20,23],enumer:19,epsilon:9,eq:[2,3,25],equal:[3,6,17,24],equat:[8,9],equival:16,er:[0,8],ergo:[5,11],err:[11,18],error:[8,19,22],essai:0,establish:19,et:[16,19],etc:[3,17,19,20,22],euler:21,euro:19,eval:[0,19],evalu:[1,2,3,8,9,11,12,13,14,16,17,19,23],event:16,eventu:[16,19],ever:19,everi:[1,7,16],everybodi:16,everyth:[3,5,11,12,16,19],evolv:10,examin:13,exampl:[3,5,6,19,21,22,24,25],exce:7,except:[1,5,8,11,18,19,22],execut:[0,1,2,3,8,13,14,16,17,19,20,24,25],exend:19,exercis:[5,11],exist:[4,11,19],expand:11,expect:[2,3,16,17,19,24],experi:[8,17],explain:19,explan:8,explor:[8,19],express:[0,1,2,3,4,11,13,14,15,19,20,21,23,24],expression_to_str:[19,24],extend:19,extra:[1,6,7],extract:[11,12,21],extrem:8,extrememli:8,f0:19,f1:[18,19,25],f2:[18,19,25],f3:[19,25],f:[2,3,5,6,7,9,13,15,16,19],f_g:19,f_in:19,f_out:19,f_python:19,facet:0,facil:8,fact:22,factor:[2,6,8,11,15,19],factori:[3,21],fail:[2,3,11,21,22],fail_fail:[],fairli:19,fake:5,fall:19,fals:[2,3,5,6,13,15,16,19],falsei:19,familiar:[0,15],far:[9,11,13,19,25],fascin:0,favorit:16,fear:[11,19],few:[6,8,9,12,16,19],fewer:[3,8],fg:19,fg_in:19,fg_out:19,fi:[18,19],fib:7,fib_gen:7,fibonacci:21,figur:[2,3,11,13,19],file:15,filter:11,fin:6,find:[2,3,5,6,7,16,17,19,21,25],finder:9,fine:[0,5,6,11,19,25],finite_state_machin:5,first:[3,5,7,8,9,11,12,13,14,17,20,21,24,25],first_two:[3,11,25],fit:[6,8],five:[6,8,21],fix:[2,3,5,13,19],fixm:[5,19],flag:[16,19],flatten:[8,17,19],flesh:5,flexibl:21,floatjoytyp:19,floatstarjoytyp:19,floor:3,floordiv:[3,6,25],flow:8,fn:19,fo:[18,19],follow:[0,2,3,5,8,10,13,16,17,19,20],foo:[8,10,11,16,19],foo_ii:10,fork:16,form:[2,3,4,5,6,7,13,17,19,21,24],forman:8,format:[18,19,21,23],formula:[0,6,21],forth:[8,19],forum:0,forward:19,found:8,four:[0,2,3,6,7,8,11,15,21],fourteen:6,fourth:[2,3,11,13,25],fr:5,frac:[9,12],fractal:8,fraction0:8,fraction:[2,8],frame:13,framework:8,free:[4,8,11],freeli:2,from:[0,1,2,3,5,6,7,8,9,11,12,14,15,16,17,18,19,20,21,24],from_:5,from_index:24,front:[2,3,13],frozenset:5,fulin:16,full:6,fun:[5,21],func:19,functionjoytyp:19,functionwrapp:3,functool:5,fundament:[0,21],funtion:11,further:[9,19,21],futur:16,g:[2,3,5,7,8,9,10,11,13,14,16,18,19,20,23,24],g_in:19,g_out:19,garbag:8,gari:11,gcd2:3,gcd:[3,8],ge:[2,3,25],gener:[0,2,4,16,19,21,24,25],generated_librari:3,genrec:[3,8,11,13,16,17,19],geometr:6,get:[2,4,5,6,7,8,12,13,19,21],getch:5,getitem:3,getrecursionlimit:24,getsourc:8,ghc:4,gi:19,give:[4,6,11,13,15,17,19,24],given:[2,3,6,7,9,11,15,16,19,20,21,24],global:[18,19],glue:8,go:[5,6,11,12,13,15,16,17,19,20,23],goe:25,good:[6,11,19],grab:19,grammar:22,grand:8,graph:16,graphic:5,graphviz:5,great:[0,8,19,21],greater:24,grind:19,group:0,grow:5,gsra:9,gt:[2,3,25],guard:[11,19],h:[5,13,19],ha:[0,2,3,5,7,8,9,10,11,13,16,19,20,24],had:[5,6,20],haiku:8,half:[6,19,20],hallmark:16,hand:[5,8,14,19,21],handi:[9,19],handl:[11,19,24,25],happen:[8,19],happi:5,hard:[5,19,20],hardwar:4,hasattr:19,hash:19,haskel:4,have:[2,3,5,6,7,8,9,10,13,14,15,16,19,20,21,24,25],he:[4,9],head:24,heh:19,help:[0,3,8,11,13,15,19],help_:3,helper:5,herd:8,here:[0,5,6,7,11,15,17,19,20,25],hg:25,hide:11,hierarchi:19,higher:[5,8,11,19],highli:8,hij:5,histori:[19,23],hit:5,hmm:[5,11],hoist:3,hold:[6,19],hood:11,hope:[0,6,8,21],hopefulli:13,host:21,how:[0,4,5,9,11,13,15,19,20,21],howev:[13,14,16,19],html:[2,3,7,12,13,21],http:[11,25],huet:20,huge:11,hugh:[9,17],human:8,hybrid:[15,25],hylomorph:21,hypothet:2,i0:19,i1:[18,19,25],i2:[18,19,25],i3:[19,25],i:[0,3,6,7,8,9,13,14,15,16,17,20,21,23,25],id:[3,19],id_:3,idea:[4,6,8,19],ident:[3,5,13,19,25],if_not_empti:11,ift:[0,3,11,13,15,17,19,25],ignor:[1,3,11,19],ii:[0,15,21],iii:21,illustr:[5,13],imagin:[5,16,20],imap:19,imit:[5,17],immedi:[5,13],immut:[5,8,11],imper:13,implement:[0,1,2,4,8,10,11,13,14,16,21,25],implementaion:16,implicit:8,improv:19,includ:[4,11,16,17,19,25],inclus:6,incom:24,incompat:10,incorpor:12,increas:6,increment:[0,3,4,6,10,16],index:[0,8,19,24],indexerror:24,indic:[16,17,19,24,25],ineffici:19,infer:[0,18],inferenc:25,info:[18,19],inform:[3,5,19,25],infra:[3,7,8,11,12,14,15,16,17,19,21,25],infrastructur:3,initi:[2,3,5,8,9,11,19],inlin:11,inner:19,inproceed:19,input:[1,9,16,18,19],input_:5,inscrib:3,inscribe_:3,insert:[19,24],insight:13,inspect:8,inspect_stack:19,instal:0,instanc:19,instanti:[4,23],instead:[5,6,7,11,13,15,19,20,24,25],instruct:5,integ:[0,2,3,8,15,17,19,22],integr:3,intend:[0,8],interact:[8,21],interest:[0,6,11,19,21],interfer:16,interlud:21,intermedi:13,intern:[0,19,23,24],interp:1,interpret:[0,4,10,14,22,23,25],interrupt:8,intersect:5,interspers:16,interv:[4,6],intjoytyp:19,introduc:10,introduct:0,intstarjoytyp:19,intuit:19,invari:3,invent:19,involv:19,ipf:8,ipython:19,isinst:[5,19],isn:[5,11,20],issubclass:19,item:[2,3,8,11,13,16,17,19,21,24],iter:[1,3,5,8,13,16,17,19,21,24],iter_stack:[14,24],iteritem:[5,19],itertool:[5,19],its:[0,1,2,3,4,6,8,11,13,15,16,17,19,24],itself:[0,2,8,11,16,19],iv:21,j05cmp:[2,3,13],j:[2,5,6,7,9,11,12,13,14,15,17,19,20],jaanu:19,jmp:5,job:[16,21],john:[9,17],joi:[2,4,10,11,12,14,16,18],join:[5,19],joypi:[20,25],joytypeerror:18,jp:[7,12],js:8,jump:5,jump_from:5,junk:19,jupyt:21,just:[0,2,3,5,7,8,10,11,13,15,16,17,19,20,23],juxtaposit:16,k:[6,11,17,19],keep:[5,11,12,16,19,20],kei:[5,17,21],kevin:0,key_n:11,keyerror:[5,11,19],kind:[0,2,4,8,11,13,15,17,19,25],kinda:19,kleen:[17,19],kleenestar:19,kleffner:19,know:[6,11,19],knowledg:19,known:[4,16],kstar:5,l:[3,5,11,19],l_kei:11,l_left:11,l_right:11,l_valu:11,la:0,label:[5,19],lambda:[4,5,19],languag:[3,4,5,8,10,11,14,19],larg:[5,19],larger:[21,24],largest:3,last:[6,11,13,19],lastli:7,later:[5,8,15,17,19],law:2,layout:[0,15],lazi:19,lazili:9,lcm:6,le:[2,3,25],lead:[5,8,19],leaf:11,lean:8,learn:0,least:[2,6,13,19,24],least_fract:8,leav:[3,6,15,16],left:[5,8,12,13,16,17,19,20,23,24],leftov:13,legend:5,legibl:[0,15],len:[5,19],length:[3,6,24],lens:13,less:[6,7,8,13,19,24],let:[7,9,11,12,13,15,17,19,20,21],letter:19,level:[4,5,11,18,19],librari:[0,5,14],like:[0,2,3,5,6,8,15,16,17,19,21,22,23,25],limit:[19,25],line:[8,11,12,19,23,25],linear:24,link:[0,5,19],linux:0,list:[0,3,5,6,8,9,11,16,17,19,20,23],list_to_stack:[19,24],liter:[1,11,17,19,20,22],literatur:19,littl:[0,5,7,11,15,16,19,21],live:21,lk:17,lkei:17,ll:[5,6,7,8,13,15,17,19,20],load:[6,8],local:19,locat:2,locu:23,log:[18,19],log_2:11,logic:[0,6,15,21],longer:[11,19],look:[1,5,7,8,9,11,12,15,16,19],lookup:8,loop:[0,1,3,5,6,19,21,25],lose:19,lot:[5,8,11,19,20],love:6,low:[4,5],lower:6,lowercas:[5,19],lowest:11,lr:5,lshift:[3,25],lt:[2,3,25],m:[0,5,6,8,11,15,16,17,19],machin:[0,21],machineri:[11,19],macro:8,made:[0,8,16,19,20],magic:19,mai:[2,13,16,25],mail:0,main:[0,3,8,12,15,16,19,20],mainloop:10,maintain:20,major:10,make:[2,3,4,6,8,11,13,14,15,16,17,19,20,21],make_gener:[9,15],make_graph:5,manfr:[0,2,3,4,13],mani:[0,5,8,19],manipul:19,manner:12,map:[1,3,5,6,8,10,13,17,19,23],map_:3,marker:8,mask:[6,7,15],match:[0,1,19,21],materi:0,math:[0,8,9,11,12,19],mathemat:8,matter:[6,9,11,17],max:3,max_:3,maximum:3,mayb:[11,19],mc:19,me:[8,17,19],mean:[4,6,8,9,11,13,17,19,24],meant:[8,11,13,17,24],mem:5,member:[2,3,13],memo:5,mental:8,mention:2,mercuri:[],mess:19,messag:[18,19],meta:[8,11,14],meta_compos:19,method:[0,8,19,21,23],midpoint:6,might:[0,4,5,7,11,15,19],mike:11,million:7,min:3,min_:3,mind:19,minimum:3,minor:11,minu:3,mirror:0,miscellan:0,mismatch:19,mix:[8,19],mod:3,mode:19,model:[4,8],modern:0,modif:[7,19],modifi:[8,11,20],modul:[0,1,3,8,19,22],modulo:19,modulu:[3,8,25],moment:19,month:8,more:[0,3,4,5,6,7,8,9,13,14,16,17,19,22,24,25],most:[5,19,25],mostli:0,move:[5,11],movement:2,ms:21,much:[5,6,7,11,13,19,24],muck:11,mul:[3,8,12,18,20,23,25],multi:[],multipl:[21,25],multipli:3,must:[2,3,6,10,13,16,17,19,22],my:[0,6,8,16],myself:19,n0:19,n10001:19,n10002:19,n10003:19,n1001:19,n1002:19,n1003:19,n1:[19,25],n2:[19,25],n3:[19,25],n4:[19,25],n:[2,3,5,6,8,9,11,14,15,17,19,20,24],name:[1,3,5,8,10,11,13,19,20,21,22,23,24,25],narr:19,natur:[5,6,7,11,19],navig:20,ne:[3,25],nearli:19,neat:11,neato:19,necessarili:19,need:[2,3,6,7,9,10,11,13,15,16,19],neg:[3,12,25],neither:[16,19],ness:5,nest:[3,8,11,20],net:25,network:8,never:[5,10,13],new_def:19,new_f:19,new_fo:19,new_kei:11,new_valu:11,newton:[0,21],next:[0,5,6,15,16,17,19,25],nice:[0,5,13,24],niether:2,nk:6,nm:5,node:[5,17,21],node_kei:11,node_valu:11,non:[5,17,19],none:[1,19],nope:17,nor:5,normal:16,not_:3,notat:[0,8,11,15],note:[2,5,6,9,11,13,16,19,24],notebook:[6,7,8,19,20,21],notebook_preambl:[2,6,7,9,11,12,13,14,15,17,19,20],noth:[2,11,16],notic:6,now:[3,5,6,7,8,13,14,17,19,21],ns:19,nth:[3,24],nullari:[8,11,15,16,19,25],number:[0,1,2,3,6,7,9,15,16,24,25],numberjoytyp:19,numberstarjoytyp:19,numer:19,o:[5,7,11,19],object:[5,19,22],observ:6,obviou:7,obvious:19,occur:11,odd:[6,7],off:[2,3,6,7,12,15,19,20],often:[5,16],oh:11,ok:19,old:[0,2,14],old_k:11,old_kei:11,old_valu:11,omg:5,omit:[13,19,22],onc:[3,5,10,11],one:[0,2,3,5,6,7,11,13,15,16,17,19,23,24,25],ones:[5,7,19],onli:[2,3,5,6,11,13,15,16,19,20,24],onto:[1,2,3,8,13,24],open:[8,19],oper:[0,3,5,8,11,13,21,24],oppos:19,optim:11,option:[1,8,11,19,24],or_:3,orchestr:16,order:[0,2,3,8,13,16,18,19,21,24],org:[0,11],origin:[0,1,2,3,11,20,21],osdn:25,other:[0,2,3,4,5,8,11,13,15,17,19,24],otherwis:[3,5,6,7,11,17,19],our:[5,6,7,8,9,13,15,17,19],out:[2,3,4,6,7,8,9,11,12,13,15,16,19,20,21],outcom:17,outlin:5,output:[1,5,9,13,16,18,19,25],outsid:4,over:[3,4,6,7,8,9,11,12,16,17,19,21,25],overhaul:19,overview:[3,19],own:[11,19],p:[2,3,6,11,13,16],pack:24,packag:[0,8],page:[0,11,19,24],pair:[0,2,3,6,7,11,15,19],palidrom:6,palindrom:6,pam:8,paper:[4,8,13,16,20],paradigm:21,parallel:[2,21],param:1,paramet:[1,2,3,13,14,22,23,24],parameter:21,paramorph:13,parenthes:[11,24],pariti:7,pars:[0,3,5,8],parse_definit:[],parseerror:22,parser:[0,18,19],part:[2,3,9,13,17,21],partial:[5,19],particular:20,pass:[0,5,11,19,23],patch:5,path:[5,15,19,21],pattern:[5,6,16,17,21],pe1:[6,7],pe2:7,pearl:20,pend:[3,8,13,19,20,23],peopl:21,per:[8,17],perfectli:16,perform:[5,16,19],perhap:7,period:8,permit:[16,19,24],permut:19,persist:11,phase:2,phi:5,phrase:15,pick:[3,6,7,16,24],pickl:8,pictur:11,piec:[13,21],pip:0,place:[3,6,8,19],plai:0,plu:3,plug:[7,13,17],pm:[3,12,19,25],point:[4,5,8,11,13,15,16],pointless:2,pool:16,pop:[0,3,5,6,7,8,11,13,14,15,17,18,24,25],popd:[3,8,9,11,14,16,19,25],popdd:[3,7,12,19,25],popop:[3,6,7,8,9,11,17,19,25],popopd:[3,25],popopdd:[3,25],posit:[3,6,8,13],possibilit:11,possibl:[11,17,19,21],post:8,poswrd:19,potenti:16,pow:[3,25],power:[8,19],pprint:5,pragmat:6,preambl:9,preceed:16,precis:[0,1],pred:[3,19,25],predecessor:3,predic:[2,3,5,7,13,16],prefix:[19,23],preliminari:5,present:19,preserv:[4,17],pretti:[9,11,12,16,17,19,23,24],pretty_print:0,previou:[8,16],prime:9,primit:[2,3,19,21],primrec:[3,7,8,13],print:[0,1,2,3,5,18,19,23,24],probabl:[7,8,11,19],problem:[8,15,19,21],proc_curr:11,proc_left:11,proc_right:11,proce:[6,25],process:[5,8,17,19,23],produc:[3,6,11,13,17,19],product:[5,7,8,18,19],program:[0,2,3,7,8,9,11,13,15,16,19,20],programm:[16,19],progress:16,project:[21,25],prolog:19,promis:16,prompt:8,proper:[2,3,13,16,25],properti:0,provid:[0,4,8,16,19,25],pseudo:15,pun:[0,8],punctuat:19,pure:[0,5],puriti:8,purpos:8,push:[2,3,8,13,20,24],put:[1,2,7,8,16,19,21,24],pypi:0,python3:8,python:[0,2,3,5,11,13,16,20,21,22,24,25],q:[2,3,11,13,16,19,20],quadrat:[0,21],quasi:15,queri:[11,17],query_kei:17,queu:13,quit:[0,17],quot:[0,3,7,8,11,12,13,15,16,17,19,20,23],quotat:[2,3,13],quotient:3,r0:[9,11,17],r1:[2,3,9,11,13,17],r2:[2,3,13],r:[2,3,5,11,13,19],r_kei:11,r_left:11,r_right:11,r_valu:11,rais:[5,11,19,22,24],rang:[5,8,19],range_revers:13,range_to_zero:8,ranger:13,ranger_revers:13,rankdir:5,raphson:9,rather:[6,8,13,15,17],ratio:8,re:[0,6,7,8,9,14,15,19,21,22],reach:[5,6,7,13],read:[0,1,6,7,11,19,20],readabl:14,reader:[5,11],readi:19,readm:15,real:11,realiz:[4,11,15],rearrang:[2,11,19,24],reason:[6,8,16,19],rebuild:[17,20],rec1:[2,3,13],rec2:[2,3,13],recent:19,recogn:22,recombin:16,record:[8,23],recur:[3,13,19],recurs:[0,2,3,5,7,8,9,16,19,21,24],recus:8,redefin:21,redistribut:[3,8],redo:5,reduc:[2,19],redund:24,refactor:[8,10],refer:[0,2],referenti:16,reflect:16,regard:16,region:15,regist:2,regular:[19,21,22],reifi:18,reimplement:[16,21],rel:24,relat:[5,19],releas:10,rem:3,remain:[2,8,10,19],remaind:[3,9],rememb:5,remind:19,remot:24,remov:[3,11,19,24,25],render:21,repeat:6,repeatedli:6,repetit:5,repl:[0,1],replac:[0,2,3,7,12,13,16,17,19,20,21,24],repositori:0,repr:[5,19],repres:[2,8,11,16,22,23],represent:24,reprod:7,repurpos:19,requir:[15,16,19,24],research:19,resembl:8,resolut:16,resourc:16,respect:[5,6,16],rest:[3,6,7,8,11,13,15,20,21,24,25],rest_two:11,restart:[],restor:2,result:[1,2,3,5,6,11,12,13,16,17,19,20],resum:8,retir:2,retri:8,reus:[11,19,24],revers:[3,6,7,13,19,20,21,24],revisit:19,rewrit:[3,8,15,19],rewritten:8,rid:11,right:[7,8,12,17,19,21,23,24],rightest:11,rightmost:6,rigor:16,risk:19,rk:17,rkei:17,rob:19,roll:[3,9,11,17],roll_dn:19,rolldown:[3,18,19,25],rollup:[3,19,25],root:[3,9,12],rough:15,round:[3,19],row:5,rrest:[3,18,19,25],rshift:[3,25],rtype:1,rule:[16,21],run:[0,1,3,6,8,9,11,12,13,15,16,17,19,20],runtim:16,runtimeerror:24,s0:19,s1:[18,19,25],s2:[18,19],s3:19,s4:19,s5:19,s:[0,1,2,3,4,7,8,10,12,13,14,15,16,17,18,20,21,23,24,25],sai:[5,7,11,12,15,17,19],same:[2,4,6,11,16,19,24],sandwich:[2,3,13],save:[2,5,6,8],scan:[],scanner:[8,22],scenario:20,scm:25,scope:[7,11],script:1,se:19,search:[0,11],sec:19,second:[3,8,11,13,15,17,24,25],section:13,see:[0,5,7,8,9,10,12,13,14,15,19,20,23],seem:[0,6,8,15,17,19,25],seen:[19,20],select:3,self:[5,16,19],semant:[2,3,8,10,11,16,19],semi:8,send:8,sens:[0,2,6,19,20],separ:[8,16,19,22],seq:19,sequenc:[0,1,2,3,6,8,11,13,14,20,21,22,25],sequence_to_stack:19,seri:[6,7,11,15,20],set:[2,3,5,13,19,21],seven:[6,7],sever:[0,4,8,13],shape:[5,16],share:[3,8],shelf:2,shew:5,shift:[6,7],shorter:21,shorthand:11,should:[2,3,5,6,11,13,16,19],shouldn:8,show:[4,15,16,19,20],shunt:[3,20],side:[5,11,18,19,25],sign:[],signatur:25,signifi:[8,11],similar:[11,15,17,19],simon:8,simpl:[1,5,8,13,15,24,25],simplefunctionwrapp:[3,14,19],simpler:17,simplest:[19,21],simpli:4,simplifi:[6,11,20],sinc:[2,6,11,15,19],singl:[3,7,8,14,15,16,19,22,25],singleton:5,situ:11,situat:11,six:[6,7,8],sixti:[6,7],size:[5,8,21],skeptic:8,skip:19,slight:9,slightli:[11,13,19],smallest:3,smart:11,sn:19,so:[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,19,20,25],softwar:8,solei:2,solut:[6,7],solvabl:8,some:[0,2,3,5,7,8,11,13,15,16,17,19,21,24,25],somehow:[11,19],someth:[2,10,11,19],sometim:11,somewher:[11,21],sort:[3,5,11,16,19],sort_:3,sourc:[0,1,3,19,21,22,23,24],space:[6,23],span:6,spawn:19,special:[7,11,21],specif:[0,4],specifi:[11,16],speed:14,spell:[5,17],sphinx:[21,24],spiral:[0,21],spiral_next:15,spirit:[0,1,17],split:[5,19],sqr:[3,8,9,12,20],sqrt:[3,9,19,25],squar:[0,3,9,19,21,22],square_spir:[],ss:19,stack:[0,1,3,6,7,9,11,12,13,14,15,16,17,18,20,21,22,23,25],stack_effect:19,stack_effect_com:19,stack_to_str:[18,24],stacki:19,stackjoytyp:19,stacklistbox:24,stackoverflow:15,stackstarjoytyp:19,stage:17,stai:[0,1],stand:[4,5],standard:[8,11],star:[17,19],stare:11,start:[5,6,7,8,9,11,13,17,19,25],state:[8,21],state_nam:5,statement:[3,5,15],stdout:[18,19],step:[3,6,8,11,14,19,20,21],stepper:15,still:[5,11,19],stop:11,stopiter:5,storag:[6,11],store:[6,13,19],stori:13,str:[1,5,19,22,23,24],straightforward:[5,7,9,15,19,21],stream:[6,18,19],stretch:11,string:[1,2,3,8,19,20,21,22,23,24],stringi:5,structur:[8,16,17,19,20,21,24],stuck:5,studi:5,stuff:[11,19],stuncon:[3,25],stununcon:[3,25],style:[0,4,19],sub:[3,10,16,25],subclass:8,subject:[16,20],subsequ:16,subset:[19,25],substitut:[5,11,19],subtract:6,subtyp:21,succ:[3,19,25],succe:19,success:9,suck:19,suffic:19,suffici:11,suffix:19,suggest:[4,5,11],suitabl:[1,3,4,6],sum:[3,7,8,12,13,14,17],sum_:[3,19],summand:6,sumtre:17,suppli:[11,22],support:[8,19,23,24],sure:16,suspect:2,svg:5,swaack:[3,12,14,15,19,20,25],swap:[3,6,7,8,9,11,13,14,15,16,17,18,20,25],swon:[3,7,8,13,17,19,20,25],swoncat:[7,8,9,13,17],swuncon:13,sy:[18,19,24],sym:5,symbol:[1,2,3,5,16,19,20,21,22,23],symboljoytyp:19,symmetr:[6,11,15],symmetri:[5,15],syntact:8,syntax:[8,24],system:[8,11,16],t0:3,t1:3,t:[2,3,5,6,8,10,11,13,15,16,19,20,24],tabl:[5,19],tag:[5,19,25],tail:[9,11,19,21,24],tailrec:[3,9],take:[3,5,6,8,9,11,13,15,16,19,24],talk:[8,11,19,24],target:20,tast:4,tbd:8,te:11,tear:13,technic:2,techniqu:[4,20],technolog:2,temporari:20,ten:6,term:[1,2,5,8,9,13,16,19,21,22,24,25],termin:[2,3,5,13],ternari:8,test:[2,3,13],text:[0,1,19],text_to_express:[8,18,22],textual:8,than:[0,3,5,6,7,8,9,13,16,17,19,24,25],thei:[2,5,6,7,8,11,13,15,16,19,20,22,24],them:[0,2,5,6,7,11,13,15,16,19,20,21,25],themselv:[16,19],theori:[2,3,13,16],therefor:7,thi:[0,1,2,3,4,5,6,7,8,9,12,13,15,16,17,19,20,21,22,23,24,25],thing:[2,7,11,13,16,19,20,22,24,25],think:[2,6,8,11,13,16,17,19],third:[3,7,8,11,25],thirti:6,those:[2,3,5,11,13,15,19,21,25],though:[6,16],thought:[8,16],thousand:6,thread:[2,16],three:[2,3,5,6,8,11,12,15,17,19,21],through:[1,6,8,17,19,20,24,25],thun:[2,3,4,10,13,16],thunder:8,thunk:16,time:[3,5,6,8,9,11,13,15,16,19,20],titl:19,to_check:5,to_index:24,to_set:11,todai:8,todo:[8,22],togeth:[7,8,16,19,21],token:22,toler:21,too:[5,13,19],tool:[8,19],tooo:19,top:[2,3,8,13,19,23,24],total:6,tower:19,trace:[0,8,12,13,15,20,21,24],traceback:19,traceprint:23,track:[12,19,20],tracker:0,transform:4,transit:5,translat:[4,12,19,21],trap:5,travers:[0,21],treasur:0,treat:[0,2,3,13,19,21],treatment:7,tree:[0,8,21],treegrind:21,treestep:[0,21],tri:6,triangl:16,triangular_numb:13,trick:[6,19],tricki:19,trobe:0,trove:0,truediv:25,truthi:[3,8,16,19],ts:17,tuck:[3,8,19,25],tupl:[3,5,8,19,24],turn:[2,3,5,19,21],twice:[11,13],two:[0,2,3,6,8,9,11,12,13,15,16,17,18,19,20,21,24,25],txt:[],type:[0,1,4,8,11,13,16,21,22,23,24],typeerror:19,typeless:19,typic:[2,3,12,13],u:[18,19],uh:19,ui:8,ulam:[0,15],unari:8,unarybuiltinwrapp:3,unbalanc:[11,22],unbound:25,unchang:11,uncompil:19,uncon:[3,7,8,11,13,17,20,25],under:[2,3,8,11],underli:[5,16,19],underscor:19,understand:[0,11],undistinguish:11,undocu:8,unfinish:5,unfortun:24,unicod:19,unif:[19,21],unifi:18,union:5,uniqu:[3,5,11,19],unit:[3,8,13,16,25],univers:[0,8,16,19],unknownsymbolerror:1,unlik:16,unnecessari:21,unnecesssari:19,unpack:[2,3,11,24],unpair:6,unquot:[8,15,17,22],unread:[0,15],unrol:5,unstack:19,unswon:[3,25],untangl:13,until:[5,7,16],unus:6,unusu:11,unwrap:5,up:[1,2,3,6,7,8,11,13,14,15,16,19,20,24],updat:[0,18,21,25],uppercas:5,upward:16,us:[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,20,21,22,24,25],usag:8,user:17,usual:[0,2,13],util:[0,3,14,18,19],uu:19,v0:25,v:[2,6,7,9,11,12,13,14,15,17,20,21],valid:19,valu:[0,1,2,3,6,8,9,12,13,14,15,16,17,19,21,22,24,25],value_n:11,valueerror:[5,19,24],variabl:[19,21],variant:11,variat:[13,16,21],varieti:[4,8],variou:0,ve:[11,15,19],vener:24,verbos:4,veri:[0,1,4,5,8,11,15,24],versa:[2,19],version:[0,1,2,5,7,10,17,20,21],vi:21,via:8,vice:[2,19],view:[11,21],viewer:[1,8,10,23],vii:21,visibl:19,von:[0,2,3,4,13],vs:19,vv:19,w:[3,11,13,17,19],wa:[2,6,8,11,15,16,19,24],waaaai:5,wai:[0,2,3,4,5,6,8,13,14,15,16,19],wait:16,want:[2,6,7,9,11,13,19],warranti:[3,8],wash:8,wast:8,we:[2,5,6,7,8,9,10,12,13,14,15,16,19,20,21,24],web:24,websit:[0,6],welcom:8,well:[0,4,8,9,11,19,22],went:19,were:[8,19,20],what:[2,3,4,5,8,11,13,16,17,19,23],whatev:[2,3,13,17,24],when:[6,7,8,11,13,16,19,20,22,24,25],where:[2,3,5,8,11,13,15,19,21,24],whether:[3,13],which:[0,1,3,5,6,8,9,11,15,16,17,19,20,22,24,25],whole:[2,3,6,13,17,19],whose:7,why:[9,16,17],wiki:11,wikipedia:[0,11,20],wildli:8,wind:8,wire:13,within:[8,11,14,21],without:[2,8,11,12,15,16,19],won:[11,19,24],word:[0,3,6,8,13,20],work:[0,3,5,6,7,8,9,11,12,13,15,16,17,20,21,24,25],worker:16,worri:16,worth:6,would:[2,6,7,8,9,11,13,16,19,20,24],wrap:[3,8],wrapper:19,write:[4,5,9,11,13,15,16,17,19,20,21,24],written:[0,1,9,11,14,19,24],wrong:2,wrote:19,x:[0,3,5,6,8,9,16,20,21],xor:3,xrang:19,y:[2,3,5,15,16],yang:19,yeah:16,year:[8,19],yet:[11,16,19,20],yield:[2,3,13,19,24],yin:21,you:[0,2,3,5,6,7,8,10,11,12,13,14,15,16,17,19,20,23,24,25],your:[2,3,8,13,19],yourself:[5,8,11],z:[3,5,16,19,21],zero:[3,5,11,13,16,17,19,22,24],zerodivisionerror:19,zip:[3,5,6,19],zip_:3,zipper:[0,21],zstr:20},titles:["Thun 0.4.1 Documentation","Joy Interpreter","Functions Grouped by, er, Function with Examples","Function Reference","Categorical Programming","\u2202RE","Developing a Program in Joy","Using x to Generate Values","Thun: Joy in Python","Newton\u2019s method","No Updates","Treating Trees I: Ordered Binary Trees","Quadratic formula","Recursion Combinators","Replacing Functions in the Dictionary","Square Spiral Example Joy Code","The Four Fundamental Operations of Definite Action","Treating Trees II: treestep","Type Checking","The Blissful Elegance of Typing Joy","Traversing Datastructures with Zippers","Essays about Programming in Joy","Parsing Text into Joy Expressions","Tracing Joy Execution","Stack or Quote or Sequence or List\u2026","Type Inference of Joy Expressions"],titleterms:{"0":[0,13],"01":5,"1":[0,13],"11":5,"111":5,"2":[7,12,19],"2a":12,"3":[6,19],"4":[0,12,19],"466":7,"5":6,"\u03bb":5,"\u03d5":5,"boolean":15,"case":[9,11],"do":17,"function":[2,3,5,8,9,11,13,14,16,17,19],"long":14,"new":11,"p\u00f6ial":19,"try":5,"void":2,"while":[2,16],A:[5,6,7,9,11,14],If:11,In:[11,17],No:[5,10],Not:15,One:[7,11],The:[6,8,11,13,15,16,17,19],There:8,With:[5,17],about:21,action:16,ad:11,add:[2,11],address:20,al:13,alphabet:5,altern:17,an:[6,7,8,11,13,18,19,20],ana:13,analysi:6,anamorph:[2,13],app1:2,app2:2,app3:2,appendix:[11,13,19],appli:16,approxim:9,ar:11,argument:19,auto:3,averag:2,b:[2,12],base:[9,11],binari:[2,11,17],bliss:19,both:11,branch:[2,11,15,16],brzozowski:5,c:[12,19],can:11,cata:13,catamorph:13,categor:4,chatter:2,check:18,child:11,choic:2,clear:2,cleav:[2,16],cmp:11,code:[0,8,11,15],combin:[2,11,13,19],comment:19,compact:5,compar:11,comparison:2,compil:[7,19],compile_:19,compos:19,comput:9,con:[2,19],concat:2,conclus:[13,15,19],consecut:9,continu:8,current:11,datastructur:[5,8,11,20],deal:19,decrement:15,defin:[11,17],definit:[12,16],delabel:19,delet:11,deriv:[5,12,13,17],design:13,determin:20,develop:6,diagram:5,dialect:0,dictionari:14,dip:[2,20],dipd:2,dipdd:2,direco:7,disenstacken:2,distinguish:19,div:2,doc_from_stack_effect:19,document:0,doe:11,down_to_zero:2,drive:5,drop:2,dup:[2,19],dupd:2,dupdip:2,e:17,effect:19,eleg:19,els:11,empti:11,enstacken:2,equal:11,er:2,essai:21,et:13,euler:[6,7],eval:8,even:7,exampl:[0,2,8,11,13,15,17,18],execut:23,explor:5,express:[5,8,22,25],extract:17,f:11,factori:13,fail:18,fibonacci:7,filter:6,find:[9,11,13],finish:16,finit:5,first:[2,6,15,16,19],five:7,flatten:2,flexibl:17,floordiv:2,form:15,formula:12,found:11,four:[13,16],from:13,fsm:5,fulmin:16,fun:13,fundament:16,further:6,gcd:2,gener:[3,5,6,7,9,13,15],genrec:2,get:[11,17],getitem:2,given:[13,17],greater:11,group:2,h1:13,h2:13,h3:13,h4:13,handl:16,have:[11,17],help:2,highest:11,host:0,how:[6,7],hybrid:19,hylo:13,hylomorph:13,i:[2,5,11,19],identifi:19,ift:[2,16],ii:[17,19],iii:19,implement:[5,19],increment:15,indic:0,infer:[19,25],inferenc:19,inform:0,infra:[2,20],integ:[6,13],interest:7,interlud:11,intern:22,interpret:[1,8,19],item:20,iter:[6,11],iv:19,joi:[0,1,3,6,8,13,15,19,20,21,22,23,24,25],join:16,just:6,kei:11,kind:16,languag:0,larger:5,least_fract:2,left:11,less:11,let:[5,6],letter:5,librari:[3,8,19],like:11,list:[2,13,24],literari:8,littl:6,logic:[2,19],loop:[2,8,16],lower:11,lshift:2,machin:5,make:[7,9],mani:6,map:[2,16],match:5,math:2,memoiz:5,method:9,min:2,miscellan:2,mod:2,modifi:19,modulu:2,more:11,most:11,mul:[2,19],multipl:[6,7,19],must:11,n:13,name:12,ne:2,neg:[2,15],newton:9,next:9,node:11,non:11,now:11,nullari:2,nulli:5,number:[13,19],one:8,onli:8,oper:16,order:[11,17],origin:15,osdn:0,other:16,our:11,out:5,over:2,p:17,pack:6,pam:[2,16],para:13,paradigm:19,parallel:16,parameter:[11,17],pars:[2,22],parser:[8,22],part:19,pass:8,path:20,pattern:13,per:11,piec:15,pop:[2,19],popd:2,popop:2,pow:2,power:7,pred:2,predic:[6,9,11,15,17],pretty_print:23,primit:13,primrec:2,print:8,problem:[6,7],process:11,product:2,program:[4,6,12,17,21],progress:19,project:[0,6,7],pure:8,put:[11,12,15,17],python:[8,14,19],quadrat:12,quick:0,quot:[2,24],rang:[2,6,13],range_to_zero:2,re:[5,11],read:8,recur:[9,11],recurs:[11,13,17],redefin:[11,17],refactor:[6,11],refer:3,regular:[5,8],reimplement:17,relabel:19,rem:2,remaind:2,remov:2,render:6,repl:8,replac:[11,14],repres:[5,19],represent:5,reset:7,rest:[2,19],revers:[2,5,18],right:[11,20],rightmost:11,roll:[2,19],rolldown:2,rollup:2,rshift:2,rule:[5,19],run:[2,7],s:[5,6,9,11,19],second:[2,19],select:2,sequenc:[7,16,19,24],set:[9,11],shorter:14,should:8,shunt:2,simpl:19,simplest:6,size:[2,14],sourc:11,special:[13,19],spiral:15,sqr:[2,19],sqrt:[2,12],squar:15,stack:[2,8,19,24],start:0,state:5,step:[2,13,17],straightforward:12,stream:5,string:5,structur:11,style:8,sub:[2,11],subtyp:19,succ:2,sum:[2,6],swaack:2,swap:[2,19],swon:2,swoncat:2,symbol:[8,13],t:17,tabl:0,tail:13,take:2,term:[6,7,17],ternari:2,text:22,than:11,them:12,thi:11,third:[2,19],three:7,thun:[0,8],time:[2,7],togeth:[11,12,15,17],token:8,toler:9,trace:[14,23],traceprint:8,trampolin:5,translat:15,travers:[11,17,20],treat:[11,17],tree:[11,17,20],treegrind:17,treestep:17,triangular:13,truediv:2,truthi:2,tuck:2,turn:15,two:[5,7],type:[18,19,25],unari:2,unbound:19,uncon:[2,19],unif:18,unifi:19,unit:2,unnecessari:6,unquot:2,unstack:2,up:9,updat:[10,19],us:[7,19],util:[23,24,25],v:19,valu:[7,11],variabl:12,variat:7,version:[6,11,14,19],vi:19,view:8,vii:19,we:[11,17],which:13,within:9,word:2,work:[18,19],write:12,x:[2,7,15],xor:2,yin:19,z:20,zero:7,zip:2,zipper:20}}) \ No newline at end of file diff --git a/docs/sphinx_docs/index.rst b/docs/sphinx_docs/index.rst index b29fc83..eddc007 100644 --- a/docs/sphinx_docs/index.rst +++ b/docs/sphinx_docs/index.rst @@ -34,6 +34,31 @@ itself. .. _Concatinative: https://en.wikipedia.org/wiki/Concatenative_programming_language +Example Code +-------------------------------------------------- + +Here is an example of Joy code:: + + [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte + +It might seem unreadable but with a little familiarity it becomes just as +legible as any other notation. Some layout helps:: + + [ [[abs] ii <=] + [ + [<>] [pop !-] || + ] && + ] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral). For more information see :doc:`notebooks/Square_Spiral` + + Quick Start -------------------------------------------------- diff --git a/docs/sphinx_docs/notebooks/Derivatives_of_Regular_Expressions.rst b/docs/sphinx_docs/notebooks/Derivatives_of_Regular_Expressions.rst index be09155..29dc9fb 100644 --- a/docs/sphinx_docs/notebooks/Derivatives_of_Regular_Expressions.rst +++ b/docs/sphinx_docs/notebooks/Derivatives_of_Regular_Expressions.rst @@ -76,7 +76,7 @@ E.g.: Implementation -------------- -.. code:: python +.. code:: ipython2 from functools import partial as curry from itertools import product @@ -86,7 +86,7 @@ Implementation The empty set and the set of just the empty string. -.. code:: python +.. code:: ipython2 phi = frozenset() # ϕ y = frozenset({''}) # λ @@ -101,7 +101,7 @@ alphabet with two symbols (if you had to.) I chose the names ``O`` and ``l`` (uppercase “o” and lowercase “L”) to look like ``0`` and ``1`` (zero and one) respectively. -.. code:: python +.. code:: ipython2 syms = O, l = frozenset({'0'}), frozenset({'1'}) @@ -123,7 +123,7 @@ expression* is one of: Where ``R`` and ``S`` stand for *regular expressions*. -.. code:: python +.. code:: ipython2 AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split() # Tags are just strings. @@ -133,7 +133,7 @@ only, these datastructures are immutable. String Representation of RE Datastructures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def stringy(re): ''' @@ -175,11 +175,11 @@ Match anything. Often spelled “.” I = (0|1)* -.. code:: python +.. code:: ipython2 I = (KSTAR, (OR, O, l)) -.. code:: python +.. code:: ipython2 print stringy(I) @@ -201,14 +201,14 @@ The example expression from Brzozowski: Note that it contains one of everything. -.. code:: python +.. code:: ipython2 a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I)))) b = (CONS, I, (CONS, O, l)) c = (CONS, l, (KSTAR, l)) it = (AND, a, (NOT, (OR, b, c))) -.. code:: python +.. code:: ipython2 print stringy(it) @@ -223,7 +223,7 @@ Note that it contains one of everything. Let’s get that auxiliary predicate function ``δ`` out of the way. -.. code:: python +.. code:: ipython2 def nully(R): ''' @@ -263,7 +263,7 @@ This is the straightforward version with no “compaction”. It works fine, but does waaaay too much work because the expressions grow each derivation. -.. code:: python +.. code:: ipython2 def D(symbol): @@ -308,7 +308,7 @@ derivation. Compaction Rules ~~~~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def _compaction_rule(relation, one, zero, a, b): return ( @@ -320,7 +320,7 @@ Compaction Rules An elegant symmetry. -.. code:: python +.. code:: ipython2 # R ∧ I = I ∧ R = R # R ∧ ϕ = ϕ ∧ R = ϕ @@ -341,7 +341,7 @@ We can save re-processing by remembering results we have already computed. RE datastructures are immutable and the ``derv()`` functions are *pure* so this is fine. -.. code:: python +.. code:: ipython2 class Memo(object): @@ -365,7 +365,7 @@ With “Compaction” This version uses the rules above to perform compaction. It keeps the expressions from growing too large. -.. code:: python +.. code:: ipython2 def D_compaction(symbol): @@ -414,7 +414,7 @@ Let’s try it out… (FIXME: redo.) -.. code:: python +.. code:: ipython2 o, z = D_compaction('0'), D_compaction('1') REs = set() @@ -533,10 +533,10 @@ machine transition table. Says, “Three or more 1’s and not ending in 01 nor composed of all 1’s.” -.. figure:: omg.svg - :alt: State Machine Graph +.. figure:: attachment:omg.svg + :alt: omg.svg - State Machine Graph + omg.svg Start at ``a`` and follow the transition arrows according to their labels. Accepting states have a double outline. (Graphic generated with @@ -605,20 +605,20 @@ You can see the one-way nature of the ``g`` state and the ``hij`` “trap” in the way that the ``.111.`` on the left-hand side of the ``&`` disappears once it has been matched. -.. code:: python +.. code:: ipython2 from collections import defaultdict from pprint import pprint from string import ascii_lowercase -.. code:: python +.. code:: ipython2 d0, d1 = D_compaction('0'), D_compaction('1') ``explore()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def explore(re): @@ -645,7 +645,7 @@ disappears once it has been matched. return table, accepting -.. code:: python +.. code:: ipython2 table, accepting = explore(it) table @@ -678,7 +678,7 @@ disappears once it has been matched. -.. code:: python +.. code:: ipython2 accepting @@ -697,7 +697,7 @@ Generate Diagram Once we have the FSM table and the set of accepting states we can generate the diagram above. -.. code:: python +.. code:: ipython2 _template = '''\ digraph finite_state_machine { @@ -722,7 +722,7 @@ generate the diagram above. ) ) -.. code:: python +.. code:: ipython2 print make_graph(table, accepting) @@ -776,7 +776,7 @@ Trampoline Function Python has no GOTO statement but we can fake it with a “trampoline” function. -.. code:: python +.. code:: ipython2 def trampoline(input_, jump_from, accepting): I = iter(input_) @@ -793,7 +793,7 @@ Stream Functions Little helpers to process the iterator of our data (a “stream” of “1” and “0” characters, not bits.) -.. code:: python +.. code:: ipython2 getch = lambda I: int(next(I)) @@ -816,7 +816,7 @@ code. (You have to imagine that these are GOTO statements in C or branches in assembly and that the state names are branch destination labels.) -.. code:: python +.. code:: ipython2 a = lambda I: c if getch(I) else b b = lambda I: _0(I) or d @@ -833,12 +833,12 @@ Note that the implementations of ``h`` and ``g`` are identical ergo ``h = g`` and we could eliminate one in the code but ``h`` is an accepting state and ``g`` isn’t. -.. code:: python +.. code:: ipython2 def acceptable(input_): return trampoline(input_, a, {h, i}) -.. code:: python +.. code:: ipython2 for n in range(2**5): s = bin(n)[2:] diff --git a/docs/sphinx_docs/notebooks/Generator_Programs.rst b/docs/sphinx_docs/notebooks/Generator_Programs.rst index a59df18..55e1679 100644 --- a/docs/sphinx_docs/notebooks/Generator_Programs.rst +++ b/docs/sphinx_docs/notebooks/Generator_Programs.rst @@ -3,7 +3,7 @@ Using ``x`` to Generate Values Cf. jp-reprod.html -.. code:: python +.. code:: ipython2 from notebook_preamble import J, V, define @@ -57,7 +57,7 @@ We can make a generator for the Natural numbers (0, 1, 2, …) by using Let’s try it: -.. code:: python +.. code:: ipython2 V('[0 swap [dup ++] dip rest cons] x') @@ -81,7 +81,7 @@ Let’s try it: After one application of ``x`` the quoted program contains ``1`` and ``0`` is below it on the stack. -.. code:: python +.. code:: ipython2 J('[0 swap [dup ++] dip rest cons] x x x x x pop') @@ -94,11 +94,11 @@ After one application of ``x`` the quoted program contains ``1`` and ``direco`` ---------- -.. code:: python +.. code:: ipython2 define('direco == dip rest cons') -.. code:: python +.. code:: ipython2 V('[0 swap [dup ++] direco] x') @@ -149,13 +149,13 @@ Reading from the bottom up: G == [direco] cons [swap] swap concat cons G == [direco] cons [swap] swoncat cons -.. code:: python +.. code:: ipython2 define('G == [direco] cons [swap] swoncat cons') Let’s try it out: -.. code:: python +.. code:: ipython2 J('0 [dup ++] G') @@ -165,7 +165,7 @@ Let’s try it out: [0 swap [dup ++] direco] -.. code:: python +.. code:: ipython2 J('0 [dup ++] G x x x pop') @@ -178,7 +178,7 @@ Let’s try it out: Powers of 2 ~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 J('1 [dup 1 <<] G x x x x x x x x x pop') @@ -194,7 +194,7 @@ Powers of 2 If we have one of these quoted programs we can drive it using ``times`` with the ``x`` combinator. -.. code:: python +.. code:: ipython2 J('23 [dup ++] G 5 [x] times') @@ -226,11 +226,11 @@ int: And pick them off by masking with 3 (binary 11) and then shifting the int right two bits. -.. code:: python +.. code:: ipython2 define('PE1.1 == dup [3 &] dip 2 >>') -.. code:: python +.. code:: ipython2 V('14811 PE1.1') @@ -252,7 +252,7 @@ int right two bits. If we plug ``14811`` and ``[PE1.1]`` into our generator form… -.. code:: python +.. code:: ipython2 J('14811 [PE1.1] G') @@ -264,7 +264,7 @@ If we plug ``14811`` and ``[PE1.1]`` into our generator form… …we get a generator that works for seven cycles before it reaches zero: -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1] direco] 7 [x] times') @@ -280,11 +280,11 @@ Reset at Zero We need a function that checks if the int has reached zero and resets it if so. -.. code:: python +.. code:: ipython2 define('PE1.1.check == dup [pop 14811] [] branch') -.. code:: python +.. code:: ipython2 J('14811 [PE1.1.check PE1.1] G') @@ -294,7 +294,7 @@ if so. [14811 swap [PE1.1.check PE1.1] direco] -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times') @@ -316,7 +316,7 @@ In the PE1 problem we are asked to sum all the multiples of three and five less than 1000. It’s worked out that we need to use all seven numbers sixty-six times and then four more. -.. code:: python +.. code:: ipython2 J('7 66 * 4 +') @@ -328,7 +328,7 @@ numbers sixty-six times and then four more. If we drive our generator 466 times and sum the stack we get 999. -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times') @@ -338,7 +338,7 @@ If we drive our generator 466 times and sum the stack we get 999. 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco] -.. code:: python +.. code:: ipython2 J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum') @@ -351,13 +351,13 @@ If we drive our generator 466 times and sum the stack we get 999. Project Euler Problem One ------------------------- -.. code:: python +.. code:: ipython2 define('PE1.2 == + dup [+] dip') Now we can add ``PE1.2`` to the quoted program given to ``G``. -.. code:: python +.. code:: ipython2 J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop') @@ -445,15 +445,15 @@ Putting it all together: F == + [popdd over] cons infra uncons fib_gen == [1 1 F] -.. code:: python +.. code:: ipython2 define('fib == + [popdd over] cons infra uncons') -.. code:: python +.. code:: ipython2 define('fib_gen == [1 1 fib]') -.. code:: python +.. code:: ipython2 J('fib_gen 10 [x] times') @@ -473,14 +473,14 @@ Now that we have a generator for the Fibonacci sequence, we need a function that adds a term in the sequence to a sum if it is even, and ``pop``\ s it otherwise. -.. code:: python +.. code:: ipython2 define('PE2.1 == dup 2 % [+] [pop] branch') And a predicate function that detects when the terms in the series “exceed four million”. -.. code:: python +.. code:: ipython2 define('>4M == 4000000 >') @@ -488,11 +488,11 @@ Now it’s straightforward to define ``PE2`` as a recursive function that generates terms in the Fibonacci sequence until they exceed four million and sums the even ones. -.. code:: python +.. code:: ipython2 define('PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec') -.. code:: python +.. code:: ipython2 J('PE2') @@ -535,7 +535,7 @@ So the Fibonacci sequence considered in terms of just parity would be: Every third term is even. -.. code:: python +.. code:: ipython2 J('[1 0 fib] x x x') # To start the sequence with 1 1 2 3 instead of 1 2 3. @@ -547,7 +547,7 @@ Every third term is even. Drive the generator three times and ``popop`` the two odd terms. -.. code:: python +.. code:: ipython2 J('[1 0 fib] x x x [popop] dipd') @@ -557,11 +557,11 @@ Drive the generator three times and ``popop`` the two odd terms. 2 [3 2 fib] -.. code:: python +.. code:: ipython2 define('PE2.2 == x x x [popop] dipd') -.. code:: python +.. code:: ipython2 J('[1 0 fib] 10 [PE2.2] times') @@ -574,7 +574,7 @@ Drive the generator three times and ``popop`` the two odd terms. Replace ``x`` with our new driver function ``PE2.2`` and start our ``fib`` generator at ``1 0``. -.. code:: python +.. code:: ipython2 J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec') @@ -593,11 +593,11 @@ modifications to the default ``x``? An Interesting Variation ------------------------ -.. code:: python +.. code:: ipython2 define('codireco == cons dip rest cons') -.. code:: python +.. code:: ipython2 V('[0 [dup ++] codireco] x') @@ -620,11 +620,11 @@ An Interesting Variation 0 [1 [dup ++] codireco] . -.. code:: python +.. code:: ipython2 define('G == [codireco] cons cons') -.. code:: python +.. code:: ipython2 J('230 [dup ++] G 5 [x] times pop') diff --git a/docs/sphinx_docs/notebooks/Newton-Raphson.rst b/docs/sphinx_docs/notebooks/Newton-Raphson.rst index b580502..cb3f759 100644 --- a/docs/sphinx_docs/notebooks/Newton-Raphson.rst +++ b/docs/sphinx_docs/notebooks/Newton-Raphson.rst @@ -7,7 +7,7 @@ to write a function that can compute the square root of a number. Cf. `"Why Functional Programming Matters" by John Hughes `__ -.. code:: python +.. code:: ipython3 from notebook_preamble import J, V, define @@ -75,11 +75,11 @@ The generator can be written as: 1 [23 over / + 2 /] [dup] swoncat make_generator 1 [dup 23 over / + 2 /] make_generator -.. code:: python +.. code:: ipython3 define('gsra 1 swap [over / + 2 /] cons [dup] swoncat make_generator') -.. code:: python +.. code:: ipython3 J('23 gsra') @@ -92,7 +92,7 @@ The generator can be written as: Let's drive the generator a few time (with the ``x`` combinator) and square the approximation to see how well it works... -.. code:: python +.. code:: ipython3 J('23 gsra 6 [x popd] times first sqr') @@ -142,7 +142,7 @@ Predicate abs(a-b) ε <= (abs(a-b)<=ε) -.. code:: python +.. code:: ipython3 define('_within_P [first - abs] dip <=') @@ -156,7 +156,7 @@ Base-Case [b G] first b -.. code:: python +.. code:: ipython3 define('_within_B roll< popop first') @@ -184,7 +184,7 @@ Pretty straightforward: b [c G] ε within -.. code:: python +.. code:: ipython3 define('_within_R [popd x] dip') @@ -199,14 +199,14 @@ The recursive function we have defined so far needs a slight preamble: [a G] x ε ... a [b G] ε ... -.. code:: python +.. code:: ipython3 define('within x 0.000000001 [_within_P] [_within_B] [_within_R] tailrec') define('sqrt gsra within') Try it out... -.. code:: python +.. code:: ipython3 J('36 sqrt') @@ -216,7 +216,7 @@ Try it out... 6.0 -.. code:: python +.. code:: ipython3 J('23 sqrt') @@ -228,7 +228,7 @@ Try it out... Check it. -.. code:: python +.. code:: ipython3 4.795831523312719**2 @@ -241,7 +241,7 @@ Check it. -.. code:: python +.. code:: ipython3 from math import sqrt diff --git a/docs/sphinx_docs/notebooks/Ordered_Binary_Trees.rst b/docs/sphinx_docs/notebooks/Ordered_Binary_Trees.rst index a625ac3..569d665 100644 --- a/docs/sphinx_docs/notebooks/Ordered_Binary_Trees.rst +++ b/docs/sphinx_docs/notebooks/Ordered_Binary_Trees.rst @@ -36,7 +36,7 @@ implementation under the hood. (Where does the “type” come from? It has a contingent existence predicated on the disciplined use of these functions on otherwise undistinguished Joy datastructures.) -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V, define, DefinitionWrapper @@ -87,11 +87,11 @@ Definition: Tree-new == swap [[] []] cons cons -.. code:: python +.. code:: ipython2 define('Tree-new == swap [[] []] cons cons') -.. code:: python +.. code:: ipython2 J('"v" "k" Tree-new') @@ -163,11 +163,11 @@ comparison operator: P < == pop roll> pop first < P == pop roll> pop first -.. code:: python +.. code:: ipython2 define('P == pop roll> pop first') -.. code:: python +.. code:: ipython2 J('["old_key" 23 [] []] 17 "new_key" ["..."] P') @@ -242,11 +242,11 @@ And so ``T`` is just: T == cons cons [dipdd] cons infra -.. code:: python +.. code:: ipython2 define('T == cons cons [dipdd] cons infra') -.. code:: python +.. code:: ipython2 J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] T') @@ -266,7 +266,7 @@ This is very very similar to the above: [key_n value_n left right] value key [Tree-add] E [key_n value_n left right] value key [Tree-add] [P <] [Te] [Ee] ifte -.. code:: python +.. code:: ipython2 define('E == [P <] [Te] [Ee] ifte') @@ -278,11 +278,11 @@ instead of the right, so the only difference is that it must use Te == cons cons [dipd] cons infra -.. code:: python +.. code:: ipython2 define('Te == cons cons [dipd] cons infra') -.. code:: python +.. code:: ipython2 J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] Te') @@ -320,11 +320,11 @@ Example: key new_value [ left right] cons cons [key new_value left right] -.. code:: python +.. code:: ipython2 define('Ee == pop swap roll< rest rest cons cons') -.. code:: python +.. code:: ipython2 J('["k" "old_value" "left" "right"] "new_value" "k" ["Tree-add"] Ee') @@ -355,14 +355,14 @@ Putting it all together: Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec -.. code:: python +.. code:: ipython2 define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [[P >] [T] [E] ifte] genrec') Examples ~~~~~~~~ -.. code:: python +.. code:: ipython2 J('[] 23 "b" Tree-add') # Initial @@ -372,7 +372,7 @@ Examples ['b' 23 [] []] -.. code:: python +.. code:: ipython2 J('["b" 23 [] []] 88 "c" Tree-add') # Greater than @@ -382,7 +382,7 @@ Examples ['b' 23 [] ['c' 88 [] []]] -.. code:: python +.. code:: ipython2 J('["b" 23 [] []] 88 "a" Tree-add') # Less than @@ -392,7 +392,7 @@ Examples ['b' 23 ['a' 88 [] []] []] -.. code:: python +.. code:: ipython2 J('["b" 23 [] []] 88 "b" Tree-add') # Equal to @@ -402,7 +402,7 @@ Examples ['b' 88 [] []] -.. code:: python +.. code:: ipython2 J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Series. @@ -412,7 +412,7 @@ Examples ['b' 23 ['a' 88 [] []] ['c' 44 [] []]] -.. code:: python +.. code:: ipython2 J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step') @@ -444,7 +444,7 @@ values: ------------------------- a < b L -.. code:: python +.. code:: ipython2 J("1 0 ['G'] ['E'] ['L'] cmp") @@ -454,7 +454,7 @@ values: 'G' -.. code:: python +.. code:: ipython2 J("1 1 ['G'] ['E'] ['L'] cmp") @@ -464,7 +464,7 @@ values: 'E' -.. code:: python +.. code:: ipython2 J("0 1 ['G'] ['E'] ['L'] cmp") @@ -514,7 +514,7 @@ Or just: P == over [popop popop first] nullary -.. code:: python +.. code:: ipython2 define('P == over [popop popop first] nullary') @@ -541,11 +541,11 @@ to understand: Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec -.. code:: python +.. code:: ipython2 define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec') -.. code:: python +.. code:: ipython2 J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Still works. @@ -685,14 +685,14 @@ Working backward: Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec -.. code:: python +.. code:: ipython2 define('Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec') Examples ~~~~~~~~ -.. code:: python +.. code:: ipython2 J('[] [foo] Tree-iter') # It doesn't matter what F is as it won't be used. @@ -702,7 +702,7 @@ Examples -.. code:: python +.. code:: ipython2 J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [first] Tree-iter") @@ -712,7 +712,7 @@ Examples 'b' 'a' 'c' -.. code:: python +.. code:: ipython2 J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [second] Tree-iter") @@ -731,7 +731,7 @@ to it will only occur once within it, and we can query it in `:math:`O(\log_2 N)` `__ time. -.. code:: python +.. code:: ipython2 J('[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step') @@ -741,11 +741,11 @@ time. [3 0 [2 0 [] []] [9 0 [5 0 [4 0 [] []] [8 0 [6 0 [] [7 0 [] []]] []]] []]] -.. code:: python +.. code:: ipython2 define('to_set == [] swap [0 swap Tree-add] step') -.. code:: python +.. code:: ipython2 J('[3 9 5 2 8 6 7 8 4] to_set') @@ -758,11 +758,11 @@ time. And with that we can write a little program ``unique`` to remove duplicate items from a list. -.. code:: python +.. code:: ipython2 define('unique == [to_set [first] Tree-iter] cons run') -.. code:: python +.. code:: ipython2 J('[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique') # Filter duplicate items. @@ -872,7 +872,7 @@ Let’s do a little semantic factoring: Now we can sort sequences. -.. code:: python +.. code:: ipython2 #define('Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec') @@ -892,7 +892,7 @@ Now we can sort sequences. -.. code:: python +.. code:: ipython2 J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order') @@ -1070,7 +1070,7 @@ So: Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec -.. code:: python +.. code:: ipython2 # I don't want to deal with name conflicts with the above so I'm inlining everything here. # The original Joy system has "hide" which is a meta-command which allows you to use named @@ -1088,7 +1088,7 @@ So: ] genrec ''') -.. code:: python +.. code:: ipython2 J('["gary" 23 [] []] "mike" [popd " not in tree" +] Tree-get') @@ -1098,7 +1098,7 @@ So: 'mike not in tree' -.. code:: python +.. code:: ipython2 J('["gary" 23 [] []] "gary" [popop "err"] Tree-get') @@ -1108,7 +1108,7 @@ So: 23 -.. code:: python +.. code:: ipython2 J(''' @@ -1124,7 +1124,7 @@ So: 2 -.. code:: python +.. code:: ipython2 J(''' @@ -1500,7 +1500,7 @@ Refactoring By the standards of the code I’ve written so far, this is a *huge* Joy program. -.. code:: python +.. code:: ipython2 DefinitionWrapper.add_definitions(''' first_two == uncons uncons pop @@ -1519,7 +1519,7 @@ program. Tree-Delete == [pop not] [pop] [R0] [R1] genrec ''', D) -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' Tree-Delete ") @@ -1529,7 +1529,7 @@ program. ['a' 23 [] ['b' 88 [] []]] -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' Tree-Delete ") @@ -1539,7 +1539,7 @@ program. ['a' 23 [] ['c' 44 [] []]] -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' Tree-Delete ") @@ -1549,7 +1549,7 @@ program. ['b' 88 [] ['c' 44 [] []]] -.. code:: python +.. code:: ipython2 J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' Tree-Delete ") @@ -1559,7 +1559,7 @@ program. ['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] -.. code:: python +.. code:: ipython2 J('[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step') @@ -1569,7 +1569,7 @@ program. [4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] -.. code:: python +.. code:: ipython2 J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete ") @@ -1579,7 +1579,7 @@ program. [4 0 [2 0 [1 0 [] []] []] [6 0 [5 0 [] []] [7 0 [] []]]] -.. code:: python +.. code:: ipython2 J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete ") diff --git a/docs/sphinx_docs/notebooks/Quadratic.rst b/docs/sphinx_docs/notebooks/Quadratic.rst index 5afb8e2..3262e84 100644 --- a/docs/sphinx_docs/notebooks/Quadratic.rst +++ b/docs/sphinx_docs/notebooks/Quadratic.rst @@ -1,4 +1,4 @@ -.. code:: python +.. code:: ipython2 from notebook_preamble import J, V, define @@ -81,13 +81,13 @@ the variables: 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:: python +.. code:: ipython2 define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2') Let’s try it out: -.. code:: python +.. code:: ipython2 J('3 1 1 quadratic') @@ -102,7 +102,7 @@ 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:: python +.. code:: ipython2 V('-5 1 4 quadratic') diff --git a/docs/sphinx_docs/notebooks/Recursion_Combinators.rst b/docs/sphinx_docs/notebooks/Recursion_Combinators.rst index 2298cfd..9159882 100644 --- a/docs/sphinx_docs/notebooks/Recursion_Combinators.rst +++ b/docs/sphinx_docs/notebooks/Recursion_Combinators.rst @@ -1,4 +1,4 @@ -.. code:: python +.. code:: ipython2 from notebook_preamble import D, DefinitionWrapper, J, V, define @@ -80,7 +80,7 @@ is a recursive function ``H :: A -> C`` that converts a value of type It may be helpful to see this function implemented in imperative Python code. -.. code:: python +.. code:: ipython2 def hylomorphism(c, F, P, G): '''Return a hylomorphism function H.''' @@ -185,7 +185,7 @@ the left so we have a definition for ``hylomorphism``: hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec -.. code:: python +.. code:: ipython2 define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec') @@ -203,13 +203,13 @@ To sum a range of integers from 0 to *n* - 1: - ``[G]`` is ``[-- dup]`` - ``[F]`` is ``[+]`` -.. code:: python +.. code:: ipython2 define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism') Let’s try it: -.. code:: python +.. code:: ipython2 J('5 triangular_number') @@ -219,7 +219,7 @@ Let’s try it: 10 -.. code:: python +.. code:: ipython2 J('[0 1 2 3 4 5 6] [triangular_number] map') @@ -391,10 +391,8 @@ 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*. +``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. @@ -407,11 +405,11 @@ Each of the above variations can be used to make four slightly different H1 == [P] [pop c] [G] [dip F] genrec == [0 <=] [pop []] [-- dup] [dip swons] genrec -.. code:: python +.. code:: ipython2 define('range == [0 <=] [] [-- dup] [swons] hylomorphism') -.. code:: python +.. code:: ipython2 J('5 range') @@ -429,11 +427,11 @@ Each of the above variations can be used to make four slightly different H2 == c swap [P] [pop] [G [F] dip] primrec == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec -.. code:: python +.. code:: ipython2 define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec') -.. code:: python +.. code:: ipython2 J('5 range_reverse') @@ -451,11 +449,11 @@ Each of the above variations can be used to make four slightly different H3 == [P] [pop c] [[G] dupdip] [dip F] genrec == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec -.. code:: python +.. code:: ipython2 define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec') -.. code:: python +.. code:: ipython2 J('5 ranger') @@ -473,11 +471,11 @@ Each of the above variations can be used to make four slightly different H4 == c swap [P] [pop] [[F] dupdip G ] primrec == [] swap [0 <=] [pop] [[swons] dupdip --] primrec -.. code:: python +.. code:: ipython2 define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec') -.. code:: python +.. code:: ipython2 J('5 ranger_reverse') @@ -503,7 +501,7 @@ and makes some new value. C == [not] c [uncons swap] [F] hylomorphism -.. code:: python +.. code:: ipython2 define('swuncons == uncons swap') # Awkward name. @@ -513,11 +511,11 @@ An example of a catamorphism is the sum function. sum == [not] 0 [swuncons] [+] hylomorphism -.. code:: python +.. code:: ipython2 define('sum == [not] 0 [swuncons] [+] hylomorphism') -.. code:: python +.. code:: ipython2 J('[5 4 3 2 1] sum') @@ -533,7 +531,7 @@ The ``step`` combinator The ``step`` combinator will usually be better to use than ``catamorphism``. -.. code:: python +.. code:: ipython2 J('[step] help') @@ -562,11 +560,11 @@ The ``step`` combinator will usually be better to use than -.. code:: python +.. code:: ipython2 define('sum == 0 swap [+] step') -.. code:: python +.. code:: ipython2 J('[5 4 3 2 1] sum') @@ -594,11 +592,11 @@ With: G == -- P == 1 <= -.. code:: python +.. code:: ipython2 define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec') -.. code:: python +.. code:: ipython2 J('5 factorial') @@ -637,11 +635,11 @@ We would use: G == rest dup P == not -.. code:: python +.. code:: ipython2 define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec') -.. code:: python +.. code:: ipython2 J('[1 2 3] tails') diff --git a/docs/sphinx_docs/notebooks/Replacing.rst b/docs/sphinx_docs/notebooks/Replacing.rst index 02ecb3b..0f90445 100644 --- a/docs/sphinx_docs/notebooks/Replacing.rst +++ b/docs/sphinx_docs/notebooks/Replacing.rst @@ -9,14 +9,14 @@ dictionary. However, there’s no function that does that. Adding a new function to the dictionary is a meta-interpreter action, you have to do it in Python, not Joy. -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V A long trace ------------ -.. code:: python +.. code:: ipython2 V('[23 18] average') @@ -81,7 +81,7 @@ An efficient ``sum`` function is already in the library. But for ``size`` we can use a “compiled” version hand-written in Python to speed up evaluation and make the trace more readable. -.. code:: python +.. code:: ipython2 from joy.library import SimpleFunctionWrapper from joy.utils.stack import iter_stack @@ -99,7 +99,7 @@ up evaluation and make the trace more readable. Now we replace the old version in the dictionary with the new version, and re-evaluate the expression. -.. code:: python +.. code:: ipython2 D['size'] = size @@ -108,7 +108,7 @@ A shorter trace You can see that ``size`` now executes in a single step. -.. code:: python +.. code:: ipython2 V('[23 18] average') diff --git a/docs/sphinx_docs/notebooks/Square_Spiral.rst b/docs/sphinx_docs/notebooks/Square_Spiral.rst new file mode 100644 index 0000000..7b5e67a --- /dev/null +++ b/docs/sphinx_docs/notebooks/Square_Spiral.rst @@ -0,0 +1,421 @@ +.. code:: ipython3 + + from notebook_preamble import J, V, define + +Square Spiral Example Joy Code +============================== + +Here is the example of Joy code from the ``README`` file: + +:: + + [[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte + +It might seem unreadable but with a little familiarity it becomes just +as legible as any other notation. Some layout helps: + +:: + + [ [[abs] ii <=] + [ + [<>] [pop !-] || + ] && + ] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +This function accepts two integers on the stack and increments or +decrements one of them such that the new pair of numbers is the next +coordinate pair in a square spiral (like the kind used to construct an +Ulam Spiral). + +Original Form +------------- + +It's adapted from `the original code on +StackOverflow `__: + + If all you're trying to do is generate the first N points in the + spiral (without the original problem's constraint of masking to an N + x M region), the code becomes very simple: + +:: + + void spiral(const int N) + { + int x = 0; + int y = 0; + for(int i = 0; i < N; ++i) + { + cout << x << '\t' << y << '\n'; + if(abs(x) <= abs(y) && (x != y || x >= 0)) + x += ((y >= 0) ? 1 : -1); + else + y += ((x >= 0) ? -1 : 1); + } + } + +Translation to Joy +------------------ + +I'm going to make a function that take two ints (``x`` and ``y``) and +generates the next pair, we'll turn it into a generator later using the +``x`` combinator. + +First Boolean Predicate +~~~~~~~~~~~~~~~~~~~~~~~ + +We need a function that computes ``abs(x) <= abs(y)``, we can use ``ii`` +to apply ``abs`` to both values and then compare them with ``<=``: + +:: + + [abs] ii <= + +I've defined two short-circuiting Boolean combinators ``&&`` and ``||`` +that each accept two quoted predicate programs, run the first, and +conditionally run the second only if required (to compute the final +Boolean value). They run their predicate arguments ``nullary``. + +.. code:: ipython3 + + define('&& [nullary] cons [nullary [0]] dip branch') + define('|| [nullary] cons [nullary] dip [1] branch') + +Given those, we can define ``x != y || x >= 0`` as: + +:: + + [<>] [pop 0 >=] || + +And ``(abs(x) <= abs(y) && (x != y || x >= 0))`` as: + +:: + + [[abs] ii <=] [[<>] [pop 0 >=] ||] && + +It's a little rough, but, as I say, with a little familiarity it becomes +legible. + +The Increment / Decrement Branches +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Turning to the branches of the main ``if`` statement: + +:: + + x += ((y >= 0) ? 1 : -1); + +Rewrite as a hybrid (pseudo-code) ``ifte`` expression: + +:: + + [y >= 0] [x += 1] [X -= 1] ifte + +Change each C phrase to Joy code: + +:: + + [0 >=] [[++] dip] [[--] dip] ifte + +Factor out the dip from each branch: + +:: + + [0 >=] [[++]] [[--]] ifte dip + +Similar logic applies to the other branch: + +:: + + y += ((x >= 0) ? -1 : 1); + + [x >= 0] [y -= 1] [y += 1] ifte + + [pop 0 >=] [--] [++] ifte + +"Not Negative" +~~~~~~~~~~~~~~ + +.. code:: ipython3 + + define('!- 0 >=') + +Putting the Pieces Together +--------------------------- + +We can assemble the three functions we just defined in quotes and give +them them to the ``ifte`` combinator. With some arrangement to show off +the symmetry of the two branches, we have: + +:: + + [[[abs] ii <=] [[<>] [pop !-] ||] &&] + [[ !-] [[++]] [[--]] ifte dip] + [[pop !-] [--] [++] ifte ] + ifte + +As I was writing this up I realized that, since the ``&&`` combinator +doesn't consume the stack (below its quoted args), I can unquote the +predicate, swap the branches, and use the ``branch`` combinator instead +of ``ifte``: + +:: + + [[abs] ii <=] [[<>] [pop !-] ||] && + [[pop !-] [--] [++] ifte ] + [[ !-] [[++]] [[--]] ifte dip] + branch + +.. code:: ipython3 + + define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte') + +Let's try it out: + +.. code:: ipython3 + + J('0 0 spiral_next') + + +.. parsed-literal:: + + 1 0 + + +.. code:: ipython3 + + J('1 0 spiral_next') + + +.. parsed-literal:: + + 1 -1 + + +.. code:: ipython3 + + J('1 -1 spiral_next') + + +.. parsed-literal:: + + 0 -1 + + +.. code:: ipython3 + + J('0 -1 spiral_next') + + +.. parsed-literal:: + + -1 -1 + + +Turning it into a Generator with ``x`` +-------------------------------------- + +It can be used with the x combinator to make a kind of generator for +spiral square coordinates. + +We can use ``codireco`` to make a generator + +:: + + codireco ::= cons dip rest cons + +It will look like this: + +:: + + [value [F] codireco] + +Here's a trace of how it works: + +:: + + [0 [dup ++] codireco] . x + [0 [dup ++] codireco] . 0 [dup ++] codireco + [0 [dup ++] codireco] 0 . [dup ++] codireco + [0 [dup ++] codireco] 0 [dup ++] . codireco + [0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons + [0 [dup ++] codireco] [0 dup ++] . dip rest cons + . 0 dup ++ [0 [dup ++] codireco] rest cons + 0 . dup ++ [0 [dup ++] codireco] rest cons + 0 0 . ++ [0 [dup ++] codireco] rest cons + 0 1 . [0 [dup ++] codireco] rest cons + 0 1 [0 [dup ++] codireco] . rest cons + 0 1 [[dup ++] codireco] . cons + 0 [1 [dup ++] codireco] . + +But first we have to change the ``spiral_next`` function to work on a +quoted pair of integers, and leave a copy of the pair on the stack. +From: + +:: + + y x spiral_next + --------------------- + y' x' + +to: + +:: + + [x y] [spiral_next] infra + ------------------------------- + [x' y'] + +.. code:: ipython3 + + J('[0 0] [spiral_next] infra') + + +.. parsed-literal:: + + [0 1] + + +So our generator is: + +:: + + [[x y] [dup [spiral_next] infra] codireco] + +Or rather: + +:: + + [[0 0] [dup [spiral_next] infra] codireco] + +There is a function ``make_generator`` that will build the generator for +us out of the value and stepper function: + +:: + + [0 0] [dup [spiral_next] infra] make_generator + ---------------------------------------------------- + [[0 0] [dup [spiral_next] infra] codireco] + +Here it is in action: + +.. code:: ipython3 + + J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop') + + +.. parsed-literal:: + + [0 0] [0 1] [-1 1] [-1 0] + + +Four ``x`` combinators, four pairs of coordinates. + +Conclusion +---------- + +So that's an example of Joy code. It's a straightforward translation of +the original. It's a little long for a single definition, you might +break it up like so: + +:: + + _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] && + + _spn_T ::= [ !-] [[++]] [[--]] ifte dip + _spn_E ::= [pop !-] [--] [++] ifte + + spiral_next ::= _spn_P [_spn_E] [_spn_T] branch + +This way it's easy to see that the function is a branch with two +quasi-symmetrical paths. + +We then used this function to make a simple generator of coordinate +pairs, where the next pair in the series can be generated at any time by +using the ``x`` combinator on the generator (which is just a quoted +expression containing a copy of the current pair and the "stepper +function" to generate the next pair from that.) + +.. code:: ipython3 + + define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&') + define('_spn_T [!-] [[++]] [[--]] ifte dip') + define('_spn_E [pop !-] [--] [++] ifte') + define('spiral_next _spn_P [_spn_E] [_spn_T] branch') + +.. code:: ipython3 + + V('23 18 spiral_next') + + +.. parsed-literal:: + + . 23 18 spiral_next + 23 . 18 spiral_next + 23 18 . spiral_next + 23 18 . _spn_P [_spn_E] [_spn_T] branch + 23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch + 23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch + 23 18 . 0 [_spn_E] [_spn_T] branch + 23 18 0 . [_spn_E] [_spn_T] branch + 23 18 0 [_spn_E] . [_spn_T] branch + 23 18 0 [_spn_E] [_spn_T] . branch + 23 18 . _spn_E + 23 18 . [pop !-] [--] [++] ifte + 23 18 [pop !-] . [--] [++] ifte + 23 18 [pop !-] [--] . [++] ifte + 23 18 [pop !-] [--] [++] . ifte + 23 18 [pop !-] [--] [++] . [nullary not] dipd branch + 23 18 [pop !-] [--] [++] [nullary not] . dipd branch + 23 18 [pop !-] . nullary not [--] [++] branch + 23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch + 23 18 [pop !-] [stack] . dip infra first not [--] [++] branch + 23 18 . stack [pop !-] infra first not [--] [++] branch + 23 18 [18 23] . [pop !-] infra first not [--] [++] branch + 23 18 [18 23] [pop !-] . infra first not [--] [++] branch + 23 18 . pop !- [18 23] swaack first not [--] [++] branch + 23 . !- [18 23] swaack first not [--] [++] branch + 23 . 0 >= [18 23] swaack first not [--] [++] branch + 23 0 . >= [18 23] swaack first not [--] [++] branch + True . [18 23] swaack first not [--] [++] branch + True [18 23] . swaack first not [--] [++] branch + 23 18 [True] . first not [--] [++] branch + 23 18 True . not [--] [++] branch + 23 18 False . [--] [++] branch + 23 18 False [--] . [++] branch + 23 18 False [--] [++] . branch + 23 18 . -- + 23 17 . + diff --git a/docs/sphinx_docs/notebooks/Treestep.rst b/docs/sphinx_docs/notebooks/Treestep.rst index 7f273d8..6b9081f 100644 --- a/docs/sphinx_docs/notebooks/Treestep.rst +++ b/docs/sphinx_docs/notebooks/Treestep.rst @@ -148,11 +148,11 @@ Working backwards: Define ``treestep`` ------------------- -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V, define, DefinitionWrapper -.. code:: python +.. code:: ipython2 DefinitionWrapper.add_definitions(''' @@ -173,7 +173,7 @@ all nodes in a tree with this function: sumtree == [pop 0] [] [sum +] treestep -.. code:: python +.. code:: ipython2 define('sumtree == [pop 0] [] [sum +] treestep') @@ -185,7 +185,7 @@ Running this function on an empty tree value gives zero: ------------------------------------ 0 -.. code:: python +.. code:: ipython2 J('[] sumtree') # Empty tree. @@ -205,7 +205,7 @@ Running it on a non-empty node: n m + n+m -.. code:: python +.. code:: ipython2 J('[23] sumtree') # No child trees. @@ -215,7 +215,7 @@ Running it on a non-empty node: 23 -.. code:: python +.. code:: ipython2 J('[23 []] sumtree') # Child tree, empty. @@ -225,7 +225,7 @@ Running it on a non-empty node: 23 -.. code:: python +.. code:: ipython2 J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees. @@ -235,7 +235,7 @@ Running it on a non-empty node: 32 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc... @@ -245,7 +245,7 @@ Running it on a non-empty node: 49 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling". @@ -255,7 +255,7 @@ Running it on a non-empty node: 49 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node. @@ -265,7 +265,7 @@ Running it on a non-empty node: [23 [23 [23] [23]] [23] [23 []]] -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep') @@ -275,7 +275,7 @@ Running it on a non-empty node: [1 [1 [1] [1]] [1] [1 []]] -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree') @@ -285,7 +285,7 @@ Running it on a non-empty node: 6 -.. code:: python +.. code:: ipython2 J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function. @@ -295,7 +295,7 @@ Running it on a non-empty node: 6 -.. code:: python +.. code:: ipython2 J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function. @@ -339,7 +339,7 @@ Traversal This doesn’t quite work: -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep') @@ -369,7 +369,7 @@ So: [] [first] [flatten cons] treestep -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep') @@ -401,7 +401,7 @@ So: [] [i roll< swons concat] [first] treestep -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep') @@ -429,7 +429,7 @@ Plugging in our BTree structure: [key value] N [left right] [K] C -.. code:: python +.. code:: ipython2 J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind') @@ -444,7 +444,7 @@ Plugging in our BTree structure: Iteration through the nodes -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind') @@ -456,7 +456,7 @@ Iteration through the nodes Sum the nodes’ keys. -.. code:: python +.. code:: ipython2 J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind') @@ -468,7 +468,7 @@ Sum the nodes’ keys. Rebuild the tree using ``map`` (imitating ``treestep``.) -.. code:: python +.. code:: ipython2 J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind') @@ -574,7 +574,7 @@ Putting it together To me, that seems simpler than the ``genrec`` version. -.. code:: python +.. code:: ipython2 DefinitionWrapper.add_definitions(''' @@ -587,7 +587,7 @@ To me, that seems simpler than the ``genrec`` version. ''', D) -.. code:: python +.. code:: ipython2 J('''\ @@ -603,7 +603,7 @@ To me, that seems simpler than the ``genrec`` version. 15 -.. code:: python +.. code:: ipython2 J('''\ diff --git a/docs/sphinx_docs/notebooks/TypeChecking.rst b/docs/sphinx_docs/notebooks/TypeChecking.rst index 4e70a1a..cd85c67 100644 --- a/docs/sphinx_docs/notebooks/TypeChecking.rst +++ b/docs/sphinx_docs/notebooks/TypeChecking.rst @@ -1,7 +1,7 @@ Type Checking ============= -.. code:: python +.. code:: ipython2 import logging, sys @@ -11,7 +11,7 @@ Type Checking level=logging.INFO, ) -.. code:: python +.. code:: ipython2 from joy.utils.types import ( doc_from_stack_effect, @@ -22,7 +22,7 @@ Type Checking JoyTypeError, ) -.. code:: python +.. code:: ipython2 D = FUNCTIONS.copy() del D['product'] @@ -31,7 +31,7 @@ Type Checking An Example ---------- -.. code:: python +.. code:: ipython2 fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0] @@ -46,7 +46,7 @@ An Example 40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘ -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(fi, fo) @@ -56,13 +56,13 @@ An Example ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) -.. code:: python +.. code:: ipython2 from joy.parser import text_to_expression from joy.utils.stack import stack_to_string -.. code:: python +.. code:: ipython2 e = text_to_expression('0 1 2 [3 4]') # reverse order print stack_to_string(e) @@ -73,7 +73,7 @@ An Example [3 4] 2 1 0 -.. code:: python +.. code:: ipython2 u = unify(e, fi)[0] u @@ -87,7 +87,7 @@ An Example -.. code:: python +.. code:: ipython2 g = reify(u, (fi, fo)) print doc_from_stack_effect(*g) @@ -101,11 +101,11 @@ An Example Unification Works “in Reverse” ------------------------------ -.. code:: python +.. code:: ipython2 e = text_to_expression('[2 3]') -.. code:: python +.. code:: ipython2 u = unify(e, fo)[0] # output side, not input side u @@ -119,7 +119,7 @@ Unification Works “in Reverse” -.. code:: python +.. code:: ipython2 g = reify(u, (fi, fo)) print doc_from_stack_effect(*g) @@ -133,7 +133,7 @@ Unification Works “in Reverse” Failing a Check --------------- -.. code:: python +.. code:: ipython2 fi, fo = infer(dup, mul)[0] @@ -146,7 +146,7 @@ Failing a Check 31 (i1 -- i2) ∘ -.. code:: python +.. code:: ipython2 e = text_to_expression('"two"') print stack_to_string(e) @@ -157,7 +157,7 @@ Failing a Check 'two' -.. code:: python +.. code:: ipython2 try: unify(e, fi) diff --git a/docs/sphinx_docs/notebooks/Types.rst b/docs/sphinx_docs/notebooks/Types.rst index 8ca737d..4c91600 100644 --- a/docs/sphinx_docs/notebooks/Types.rst +++ b/docs/sphinx_docs/notebooks/Types.rst @@ -184,7 +184,7 @@ Compiling ``pop∘swap∘roll<`` The simplest way to “compile” this function would be something like: -.. code:: python +.. code:: ipython2 def poswrd(s, e, d): return rolldown(*swap(*pop(s, e, d))) @@ -200,7 +200,7 @@ Looking ahead for a moment, from the stack effect comment: We should be able to directly write out a Python function like: -.. code:: python +.. code:: ipython2 def poswrd(stack): (_, (a, (b, (c, stack)))) = stack @@ -393,7 +393,7 @@ And there you have it, the stack effect for From this stack effect comment it should be possible to construct the following Python code: -.. code:: python +.. code:: ipython2 def F(stack): (_, (d, (c, ((a, (b, S0)), stack)))) = stack @@ -408,7 +408,7 @@ Representing Stack Effect Comments in Python I’m going to use pairs of tuples of type descriptors, which will be integers or tuples of type descriptors: -.. code:: python +.. code:: ipython2 roll_dn = (1, 2, 3), (2, 3, 1) @@ -419,7 +419,7 @@ integers or tuples of type descriptors: ``compose()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def compose(f, g): @@ -465,7 +465,7 @@ integers or tuples of type descriptors: ``unify()`` ~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -483,7 +483,7 @@ integers or tuples of type descriptors: ``update()`` ~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def update(s, term): if not isinstance(term, tuple): @@ -493,7 +493,7 @@ integers or tuples of type descriptors: ``relabel()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def relabel(left, right): return left, _1000(right) @@ -517,7 +517,7 @@ integers or tuples of type descriptors: ``delabel()`` ~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 def delabel(f): s = {u: i for i, u in enumerate(sorted(_unique(f)))} @@ -551,7 +551,7 @@ At last we put it all together in a function ``C()`` that accepts two stack effect comments and returns their composition (or raises and exception if they can’t be composed due to type conflicts.) -.. code:: python +.. code:: ipython2 def C(f, g): f, g = relabel(f, g) @@ -560,7 +560,7 @@ exception if they can’t be composed due to type conflicts.) Let’s try it out. -.. code:: python +.. code:: ipython2 C(pop, swap) @@ -573,7 +573,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 C(C(pop, swap), roll_dn) @@ -586,7 +586,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 C(swap, roll_dn) @@ -599,7 +599,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 C(pop, C(swap, roll_dn)) @@ -612,7 +612,7 @@ Let’s try it out. -.. code:: python +.. code:: ipython2 poswrd = reduce(C, (pop, swap, roll_dn)) poswrd @@ -633,13 +633,13 @@ Here’s that trick to represent functions like ``rest`` and ``cons`` that manipulate stacks. We use a cons-list of tuples and give the tails their own numbers. Then everything above already works. -.. code:: python +.. code:: ipython2 rest = ((1, 2),), (2,) cons = (1, 2), ((1, 2),) -.. code:: python +.. code:: ipython2 C(poswrd, rest) @@ -671,7 +671,7 @@ The translation table, if you will, would be: 0: 0, } -.. code:: python +.. code:: ipython2 F = reduce(C, (pop, swap, roll_dn, rest, rest, cons, cons)) @@ -699,11 +699,11 @@ Dealing with ``cons`` and ``uncons`` However, if we try to compose e.g. ``cons`` and ``uncons`` it won’t work: -.. code:: python +.. code:: ipython2 uncons = ((1, 2),), (1, 2) -.. code:: python +.. code:: ipython2 try: C(cons, uncons) @@ -723,7 +723,7 @@ The problem is that the ``unify()`` function as written doesn’t handle the case when both terms are tuples. We just have to add a clause to deal with this recursively: -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -753,7 +753,7 @@ deal with this recursively: return s -.. code:: python +.. code:: ipython2 C(cons, uncons) @@ -771,7 +771,7 @@ Part III: Compiling Yin Functions Now consider the Python function we would like to derive: -.. code:: python +.. code:: ipython2 def F_python(stack): (_, (d, (c, ((a, (b, S0)), stack)))) = stack @@ -779,7 +779,7 @@ Now consider the Python function we would like to derive: And compare it to the input stack effect comment tuple we just computed: -.. code:: python +.. code:: ipython2 F[0] @@ -816,7 +816,7 @@ Eh? And the return tuple -.. code:: python +.. code:: ipython2 F[1] @@ -848,7 +848,7 @@ Python Identifiers We want to substitute Python identifiers for the integers. I’m going to repurpose ``joy.parser.Symbol`` class for this: -.. code:: python +.. code:: ipython2 from collections import defaultdict from joy.parser import Symbol @@ -874,7 +874,7 @@ effect comment tuples to reasonable text format. There are some details in how this code works that related to stuff later in the notebook, so you should skip it for now and read it later if you’re interested. -.. code:: python +.. code:: ipython2 def doc_from_stack_effect(inputs, outputs): return '(%s--%s)' % ( @@ -914,7 +914,7 @@ Now we can write a compiler function to emit Python source code. (The underscore suffix distiguishes it from the built-in ``compile()`` function.) -.. code:: python +.. code:: ipython2 def compile_(name, f, doc=None): if doc is None: @@ -932,7 +932,7 @@ function.) Here it is in action: -.. code:: python +.. code:: ipython2 source = compile_('F', F) @@ -949,7 +949,7 @@ Here it is in action: Compare: -.. code:: python +.. code:: ipython2 def F_python(stack): (_, (d, (c, ((a, (b, S0)), stack)))) = stack @@ -957,7 +957,7 @@ Compare: Next steps: -.. code:: python +.. code:: ipython2 L = {} @@ -976,16 +976,16 @@ Next steps: Let’s try it out: -.. code:: python +.. code:: ipython2 from notebook_preamble import D, J, V from joy.library import SimpleFunctionWrapper -.. code:: python +.. code:: ipython2 D['F'] = SimpleFunctionWrapper(L['F']) -.. code:: python +.. code:: ipython2 J('[4 5 ...] 2 3 1 F') @@ -1012,7 +1012,7 @@ Compiling Library Functions We can use ``compile_()`` to generate many primitives in the library from their stack effect comments: -.. code:: python +.. code:: ipython2 def defs(): @@ -1036,7 +1036,7 @@ from their stack effect comments: return locals() -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(defs().items()): print @@ -1205,7 +1205,7 @@ Python class hierarchy of Joy types and use the ``issubclass()`` method to establish domain ordering, as well as other handy behaviour that will make it fairly easy to reuse most of the code above. -.. code:: python +.. code:: ipython2 class AnyJoyType(object): @@ -1251,14 +1251,14 @@ make it fairly easy to reuse most of the code above. Mess with it a little: -.. code:: python +.. code:: ipython2 from itertools import permutations “Any” types can be specialized to numbers and stacks, but not vice versa: -.. code:: python +.. code:: ipython2 for a, b in permutations((A[0], N[0], S[0]), 2): print a, '>=', b, '->', a >= b @@ -1278,7 +1278,7 @@ Our crude `Numerical Tower `__ of *numbers* > *floats* > *integers* works as well (but we’re not going to use it yet): -.. code:: python +.. code:: ipython2 for a, b in permutations((A[0], N[0], FloatJoyType(0), IntJoyType(0)), 2): print a, '>=', b, '->', a >= b @@ -1303,13 +1303,13 @@ Tower `__ of *numbers* > Typing ``sqr`` ~~~~~~~~~~~~~~ -.. code:: python +.. code:: ipython2 dup = (A[1],), (A[1], A[1]) mul = (N[1], N[2]), (N[3],) -.. code:: python +.. code:: ipython2 dup @@ -1322,7 +1322,7 @@ Typing ``sqr`` -.. code:: python +.. code:: ipython2 mul @@ -1340,7 +1340,7 @@ Modifying the Inferencer Re-labeling still works fine: -.. code:: python +.. code:: ipython2 foo = relabel(dup, mul) @@ -1361,7 +1361,7 @@ Re-labeling still works fine: The ``delabel()`` function needs an overhaul. It now has to keep track of how many labels of each domain it has “seen”. -.. code:: python +.. code:: ipython2 from collections import Counter @@ -1383,7 +1383,7 @@ of how many labels of each domain it has “seen”. return tuple(delabel(inner, seen, c) for inner in f) -.. code:: python +.. code:: ipython2 delabel(foo) @@ -1399,7 +1399,7 @@ of how many labels of each domain it has “seen”. ``unify()`` version 3 ^^^^^^^^^^^^^^^^^^^^^ -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -1449,7 +1449,7 @@ of how many labels of each domain it has “seen”. Rewrite the stack effect comments: -.. code:: python +.. code:: ipython2 def defs(): @@ -1503,11 +1503,11 @@ Rewrite the stack effect comments: return locals() -.. code:: python +.. code:: ipython2 DEFS = defs() -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(DEFS.items()): print name, '=', doc_from_stack_effect(*stack_effect_comment) @@ -1543,14 +1543,14 @@ Rewrite the stack effect comments: uncons = ([a1 .1.] -- a1 [.1.]) -.. code:: python +.. code:: ipython2 globals().update(DEFS) Compose ``dup`` and ``mul`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code:: python +.. code:: ipython2 C(dup, mul) @@ -1565,7 +1565,7 @@ Compose ``dup`` and ``mul`` Revisit the ``F`` function, works fine. -.. code:: python +.. code:: ipython2 F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons)) F @@ -1579,7 +1579,7 @@ Revisit the ``F`` function, works fine. -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*F) @@ -1592,12 +1592,12 @@ Revisit the ``F`` function, works fine. Some otherwise inefficient functions are no longer to be feared. We can also get the effect of combinators in some limited cases. -.. code:: python +.. code:: ipython2 def neato(*funcs): print doc_from_stack_effect(*reduce(C, funcs)) -.. code:: python +.. code:: ipython2 # e.g. [swap] dip neato(rollup, swap, rolldown) @@ -1608,7 +1608,7 @@ also get the effect of combinators in some limited cases. (a1 a2 a3 -- a2 a1 a3) -.. code:: python +.. code:: ipython2 # e.g. [popop] dipd neato(popdd, rolldown, pop) @@ -1619,7 +1619,7 @@ also get the effect of combinators in some limited cases. (a1 a2 a3 a4 -- a3 a4) -.. code:: python +.. code:: ipython2 # Reverse the order of the top three items. neato(rollup, swap) @@ -1636,7 +1636,7 @@ also get the effect of combinators in some limited cases. Because the type labels represent themselves as valid Python identifiers the ``compile_()`` function doesn’t need to generate them anymore: -.. code:: python +.. code:: ipython2 def compile_(name, f, doc=None): inputs, outputs = f @@ -1652,7 +1652,7 @@ the ``compile_()`` function doesn’t need to generate them anymore: %s = stack return %s''' % (name, doc, i, o) -.. code:: python +.. code:: ipython2 print compile_('F', F) @@ -1668,7 +1668,7 @@ the ``compile_()`` function doesn’t need to generate them anymore: But it cannot magically create new functions that involve e.g. math and such. Note that this is *not* a ``sqr`` function implementation: -.. code:: python +.. code:: ipython2 print compile_('sqr', C(dup, mul)) @@ -1696,7 +1696,7 @@ The functions that *can* be compiled are the ones that have only ``AnyJoyType`` and ``StackJoyType`` labels in their stack effect comments. We can write a function to check that: -.. code:: python +.. code:: ipython2 from itertools import imap @@ -1704,7 +1704,7 @@ comments. We can write a function to check that: def compilable(f): return isinstance(f, tuple) and all(imap(compilable, f)) or stacky(f) -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(defs().items()): if compilable(stack_effect_comment): @@ -1828,7 +1828,7 @@ the “truthiness” of ``StackJoyType`` to false to let e.g. ``joy.utils.stack.concat`` work with our stack effect comment cons-list tuples.) -.. code:: python +.. code:: ipython2 def compose(f, g): (f_in, f_out), (g_in, g_out) = f, g @@ -1840,7 +1840,7 @@ tuples.) I don’t want to rewrite all the defs myself, so I’ll write a little conversion function instead. This is programmer’s laziness. -.. code:: python +.. code:: ipython2 def sequence_to_stack(seq, stack=StackJoyType(23)): for item in seq: stack = item, stack @@ -1854,7 +1854,7 @@ conversion function instead. This is programmer’s laziness. NEW_DEFS['swaack'] = (S[1], S[0]), (S[0], S[1]) globals().update(NEW_DEFS) -.. code:: python +.. code:: ipython2 C(stack, uncons) @@ -1867,7 +1867,7 @@ conversion function instead. This is programmer’s laziness. -.. code:: python +.. code:: ipython2 reduce(C, (stack, uncons, uncons)) @@ -1887,7 +1887,7 @@ The display function should be changed too. Clunky junk, but it will suffice for now. -.. code:: python +.. code:: ipython2 def doc_from_stack_effect(inputs, outputs): switch = [False] # Do we need to display the '...' for the rest of the main stack? @@ -1935,7 +1935,7 @@ Clunky junk, but it will suffice for now. a.append(end) return '[%s]' % ' '.join(a) -.. code:: python +.. code:: ipython2 for name, stack_effect_comment in sorted(NEW_DEFS.items()): print name, '=', doc_from_stack_effect(*stack_effect_comment) @@ -1973,7 +1973,7 @@ Clunky junk, but it will suffice for now. uncons = ([a1 .1.] -- a1 [.1.]) -.. code:: python +.. code:: ipython2 print ; print doc_from_stack_effect(*stack) print ; print doc_from_stack_effect(*C(stack, uncons)) @@ -1993,7 +1993,7 @@ Clunky junk, but it will suffice for now. (... a1 -- ... a1 [a1 ...]) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*C(ccons, stack)) @@ -2003,7 +2003,7 @@ Clunky junk, but it will suffice for now. (... a2 a1 [.1.] -- ... [a2 a1 .1.] [[a2 a1 .1.] ...]) -.. code:: python +.. code:: ipython2 Q = C(ccons, stack) @@ -2024,7 +2024,7 @@ Clunky junk, but it will suffice for now. This makes the ``compile_()`` function pretty simple as the stack effect comments are now already in the form needed for the Python code: -.. code:: python +.. code:: ipython2 def compile_(name, f, doc=None): i, o = f @@ -2035,7 +2035,7 @@ comments are now already in the form needed for the Python code: %s = stack return %s''' % (name, doc, i, o) -.. code:: python +.. code:: ipython2 print compile_('Q', Q) @@ -2053,12 +2053,12 @@ comments are now already in the form needed for the Python code: -.. code:: python +.. code:: ipython2 unstack = (S[1], S[0]), S[1] enstacken = S[0], (S[0], S[1]) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*unstack) @@ -2068,7 +2068,7 @@ comments are now already in the form needed for the Python code: ([.1.] --) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*enstacken) @@ -2078,7 +2078,7 @@ comments are now already in the form needed for the Python code: (-- [.0.]) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*C(cons, unstack)) @@ -2088,7 +2088,7 @@ comments are now already in the form needed for the Python code: (a1 [.1.] -- a1) -.. code:: python +.. code:: ipython2 print doc_from_stack_effect(*C(cons, enstacken)) @@ -2098,7 +2098,7 @@ comments are now already in the form needed for the Python code: (a1 [.1.] -- [[a1 .1.] .2.]) -.. code:: python +.. code:: ipython2 C(cons, unstack) @@ -2117,7 +2117,7 @@ Part VI: Multiple Stack Effects … -.. code:: python +.. code:: ipython2 class IntJoyType(NumberJoyType): prefix = 'i' @@ -2125,7 +2125,7 @@ Part VI: Multiple Stack Effects F = map(FloatJoyType, _R) I = map(IntJoyType, _R) -.. code:: python +.. code:: ipython2 muls = [ ((I[2], (I[1], S[0])), (I[3], S[0])), @@ -2134,7 +2134,7 @@ Part VI: Multiple Stack Effects ((F[2], (F[1], S[0])), (F[3], S[0])), ] -.. code:: python +.. code:: ipython2 for f in muls: print doc_from_stack_effect(*f) @@ -2148,7 +2148,7 @@ Part VI: Multiple Stack Effects (f1 f2 -- f3) -.. code:: python +.. code:: ipython2 for f in muls: try: @@ -2164,7 +2164,7 @@ Part VI: Multiple Stack Effects (a1 -- a1 a1) (f1 f2 -- f3) (f1 -- f2) -.. code:: python +.. code:: ipython2 from itertools import product @@ -2180,7 +2180,7 @@ Part VI: Multiple Stack Effects def MC(F, G): return sorted(set(meta_compose(F, G))) -.. code:: python +.. code:: ipython2 for f in MC([dup], [mul]): print doc_from_stack_effect(*f) @@ -2191,7 +2191,7 @@ Part VI: Multiple Stack Effects (n1 -- n2) -.. code:: python +.. code:: ipython2 for f in MC([dup], muls): print doc_from_stack_effect(*f) @@ -2264,7 +2264,7 @@ Giving us two unifiers: {c: a, d: b, .1.: .0.} {c: a, d: e, .1.: A* b .0.} -.. code:: python +.. code:: ipython2 class KleeneStar(object): @@ -2314,7 +2314,7 @@ Giving us two unifiers: Can now return multiple results… -.. code:: python +.. code:: ipython2 def unify(u, v, s=None): if s is None: @@ -2386,7 +2386,7 @@ Can now return multiple results… def stacky(thing): return thing.__class__ in {AnyJoyType, StackJoyType} -.. code:: python +.. code:: ipython2 a = (As[1], S[1]) a @@ -2400,7 +2400,7 @@ Can now return multiple results… -.. code:: python +.. code:: ipython2 b = (A[1], S[2]) b @@ -2414,7 +2414,7 @@ Can now return multiple results… -.. code:: python +.. code:: ipython2 for result in unify(b, a): print result, '->', update(result, a), update(result, b) @@ -2426,7 +2426,7 @@ Can now return multiple results… {a1: a10001, s2: (a1*, s1)} -> (a1*, s1) (a10001, (a1*, s1)) -.. code:: python +.. code:: ipython2 for result in unify(a, b): print result, '->', update(result, a), update(result, b) @@ -2446,7 +2446,7 @@ Can now return multiple results… (a1*, s1) [a1*] (a2, (a1*, s1)) [a2 a1*] -.. code:: python +.. code:: ipython2 sum_ = ((Ns[1], S[1]), S[0]), (N[0], S[0]) @@ -2458,7 +2458,7 @@ Can now return multiple results… ([n1* .1.] -- n0) -.. code:: python +.. code:: ipython2 f = (N[1], (N[2], (N[3], S[1]))), S[0] @@ -2470,7 +2470,7 @@ Can now return multiple results… (-- [n1 n2 n3 .1.]) -.. code:: python +.. code:: ipython2 for result in unify(sum_[0], f): print result, '->', update(result, sum_[1]) @@ -2489,7 +2489,7 @@ Can now return multiple results… This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 def compose(f, g): (f_in, f_out), (g_in, g_out) = f, g @@ -2501,7 +2501,7 @@ This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 def meta_compose(F, G): for f, g in product(F, G): @@ -2517,7 +2517,7 @@ This function has to be modified to yield multiple results. for fg in compose(f, g): yield delabel(fg) -.. code:: python +.. code:: ipython2 for f in MC([dup], muls): print doc_from_stack_effect(*f) @@ -2529,7 +2529,7 @@ This function has to be modified to yield multiple results. (i1 -- i2) -.. code:: python +.. code:: ipython2 @@ -2542,7 +2542,7 @@ This function has to be modified to yield multiple results. ([n1* .1.] -- [n1* .1.] n1) -.. code:: python +.. code:: ipython2 @@ -2556,7 +2556,7 @@ This function has to be modified to yield multiple results. (n1 [n1* .1.] -- n2) -.. code:: python +.. code:: ipython2 sum_ = (((N[1], (Ns[1], S[1])), S[0]), (N[0], S[0])) print doc_from_stack_effect(*cons), @@ -2571,7 +2571,7 @@ This function has to be modified to yield multiple results. (a1 [.1.] -- [a1 .1.]) ([n1 n1* .1.] -- n0) (n1 [n1* .1.] -- n2) -.. code:: python +.. code:: ipython2 a = (A[4], (As[1], (A[3], S[1]))) a @@ -2585,7 +2585,7 @@ This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 b = (A[1], (A[2], S[2])) b @@ -2599,7 +2599,7 @@ This function has to be modified to yield multiple results. -.. code:: python +.. code:: ipython2 for result in unify(b, a): print result @@ -2611,7 +2611,7 @@ This function has to be modified to yield multiple results. {a1: a4, s2: (a1*, (a3, s1)), a2: a10003} -.. code:: python +.. code:: ipython2 for result in unify(a, b): print result @@ -2681,7 +2681,7 @@ We need a type variable for Joy functions that can go in our expressions and be used by the hybrid inferencer/interpreter. They have to store a name and a list of stack effects. -.. code:: python +.. code:: ipython2 class FunctionJoyType(AnyJoyType): @@ -2703,14 +2703,14 @@ Specialized for Simple Functions and Combinators For non-combinator functions the stack effects list contains stack effect comments (represented by pairs of cons-lists as described above.) -.. code:: python +.. code:: ipython2 class SymbolJoyType(FunctionJoyType): prefix = 'F' For combinators the list contains Python functions. -.. code:: python +.. code:: ipython2 class CombinatorJoyType(FunctionJoyType): @@ -2731,7 +2731,7 @@ For combinators the list contains Python functions. For simple combinators that have only one effect (like ``dip``) you only need one function and it can be the combinator itself. -.. code:: python +.. code:: ipython2 import joy.library @@ -2741,7 +2741,7 @@ For combinators that can have more than one effect (like ``branch``) you have to write functions that each implement the action of one of the effects. -.. code:: python +.. code:: ipython2 def branch_true(stack, expression, dictionary): (then, (else_, (flag, stack))) = stack @@ -2771,7 +2771,7 @@ updated along with the stack effects after doing unification or we risk losing useful information. This was a straightforward, if awkward, modification to the call structure of ``meta_compose()`` et. al. -.. code:: python +.. code:: ipython2 ID = S[0], S[0] # Identity function. @@ -2833,7 +2833,7 @@ cruft to convert the definitions in ``DEFS`` to the new ``SymbolJoyType`` objects, and some combinators. Here is an example of output from the current code : -.. code:: python +.. code:: ipython2 1/0 # (Don't try to run this cell! It's not going to work. This is "read only" code heh..) @@ -2956,7 +2956,7 @@ module. But if you’re interested in all that you should just use Prolog! Anyhow, type *checking* is a few easy steps away. -.. code:: python +.. code:: ipython2 def _ge(self, other): return (issubclass(other.__class__, self.__class__) diff --git a/docs/sphinx_docs/notebooks/Zipper.rst b/docs/sphinx_docs/notebooks/Zipper.rst index c44343a..dc4f996 100644 --- a/docs/sphinx_docs/notebooks/Zipper.rst +++ b/docs/sphinx_docs/notebooks/Zipper.rst @@ -10,7 +10,7 @@ Huet `__ out of sequences. -.. code:: python +.. code:: ipython2 J('[1 [2 [3 4 25 6] 7] 8]') @@ -54,14 +54,14 @@ show the trace so you can see how it works. If we were going to use these a lot it would make sense to write Python versions for efficiency, but see below. -.. code:: python +.. code:: ipython2 define('z-down == [] swap uncons swap') define('z-up == swons swap shunt') define('z-right == [swons] cons dip uncons swap') define('z-left == swons [uncons swap] dip swap') -.. code:: python +.. code:: ipython2 V('[1 [2 [3 4 25 6] 7] 8] z-down') @@ -77,7 +77,7 @@ but see below. [] [[2 [3 4 25 6] 7] 8] 1 . -.. code:: python +.. code:: ipython2 V('[] [[2 [3 4 25 6] 7] 8] 1 z-right') @@ -101,7 +101,7 @@ but see below. [1] [8] [2 [3 4 25 6] 7] . -.. code:: python +.. code:: ipython2 J('[1] [8] [2 [3 4 25 6] 7] z-down') @@ -111,7 +111,7 @@ but see below. [1] [8] [] [[3 4 25 6] 7] 2 -.. code:: python +.. code:: ipython2 J('[1] [8] [] [[3 4 25 6] 7] 2 z-right') @@ -121,7 +121,7 @@ but see below. [1] [8] [2] [7] [3 4 25 6] -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [3 4 25 6] z-down') @@ -131,7 +131,7 @@ but see below. [1] [8] [2] [7] [] [4 25 6] 3 -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [] [4 25 6] 3 z-right') @@ -141,7 +141,7 @@ but see below. [1] [8] [2] [7] [3] [25 6] 4 -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [3] [25 6] 4 z-right') @@ -151,7 +151,7 @@ but see below. [1] [8] [2] [7] [4 3] [6] 25 -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [4 3] [6] 25 sqr') @@ -161,7 +161,7 @@ but see below. [1] [8] [2] [7] [4 3] [6] 625 -.. code:: python +.. code:: ipython2 V('[1] [8] [2] [7] [4 3] [6] 625 z-up') @@ -184,7 +184,7 @@ but see below. [1] [8] [2] [7] [3 4 625 6] . -.. code:: python +.. code:: ipython2 J('[1] [8] [2] [7] [3 4 625 6] z-up') @@ -194,7 +194,7 @@ but see below. [1] [8] [2 [3 4 625 6] 7] -.. code:: python +.. code:: ipython2 J('[1] [8] [2 [3 4 625 6] 7] z-up') @@ -210,7 +210,7 @@ but see below. In Joy we have the ``dip`` and ``infra`` combinators which can “target” or “address” any particular item in a Joy tree structure. -.. code:: python +.. code:: ipython2 V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra') @@ -270,13 +270,13 @@ been embedded in a nested series of quoted programs, e.g.: The ``Z`` function isn’t hard to make. -.. code:: python +.. code:: ipython2 define('Z == [[] cons cons] step i') Here it is in action in a simplified scenario. -.. code:: python +.. code:: ipython2 V('1 [2 3 4] Z') @@ -314,7 +314,7 @@ Here it is in action in a simplified scenario. And here it is doing the main thing. -.. code:: python +.. code:: ipython2 J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z') diff --git a/docs/sphinx_docs/notebooks/index.rst b/docs/sphinx_docs/notebooks/index.rst index c14aafa..dbb23a5 100644 --- a/docs/sphinx_docs/notebooks/index.rst +++ b/docs/sphinx_docs/notebooks/index.rst @@ -16,6 +16,7 @@ These essays are adapted from Jupyter notebooks. I hope to have those hosted so Treestep Generator_Programs Newton-Raphson + Square_Spiral Zipper Types TypeChecking