OSDN Git Service

More docs.
authorSimon Forman <sforman@hushmail.com>
Wed, 6 Jun 2018 00:39:18 +0000 (17:39 -0700)
committerSimon Forman <sforman@hushmail.com>
Wed, 6 Jun 2018 00:39:18 +0000 (17:39 -0700)
.hgignore
docs/4. Replacing Functions in the Dictionary.ipynb
docs/Generator Programs.ipynb
docs/Hylo-, Ana-, Cata-, and Para-morphisms - Recursion Combinators.ipynb
docs/Quadratic.ipynb
docs/Treestep.ipynb
docs/Zipper.ipynb

index 2bf58da..0276843 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -3,4 +3,5 @@ build
 .hypothesis
 .pytest_cache
 .vscode
+docs/.ipynb_checkpoints
 
index 598d697..16cfeb7 100644 (file)
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython2",
-   "version": "2.7.13"
+   "version": "2.7.12"
   }
  },
  "nbformat": 4,
index d202481..0ed86be 100644 (file)
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Consider the `x` combinator `x == dup i`:\n",
+    "Consider the `x` combinator:\n",
+    "\n",
+    "    x == dup i\n",
+    "\n",
+    "We can apply it to a quoted program consisting of some value `a` and a function `B`:\n",
     "\n",
     "    [a B] x\n",
-    "    [a B] a B\n",
+    "    [a B] a B"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Let `B` function `swap` the `a` with the quote and run some function `C` on it to generate a new value `b`:\n",
     "\n",
-    "Let `B` `swap` the `a` with the quote and run some function `[C]` on it.\n",
+    "    B == swap [C] dip\n",
     "\n",
     "    [a B] a B\n",
     "    [a B] a swap [C] dip\n",
     "    a [a B]      [C] dip\n",
     "    a C [a B]\n",
+    "    b [a B]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Now discard the quoted `a` with `rest` then `cons` `b`:\n",
     "\n",
-    "Now discard the quoted `a` with `rest` and `cons` the result of `C` on `a` whatever that is:\n",
-    "\n",
-    "    aC [a B] rest cons\n",
-    "    aC [B] cons\n",
-    "    [aC B]\n",
-    "\n",
-    "Altogether, this is the definition of `B`:\n",
-    "\n",
-    "    B == swap [C] dip rest cons\n",
+    "    b [a B] rest cons\n",
+    "    b [B]        cons\n",
+    "    [b B]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Putting it together, this is the definition of `B`:\n",
     "\n",
-    "We can create a quoted program that generates the Natural numbers (integers 0, 1, 2, ...) by using `0` for `a` and `[dup ++]` for `[C]`:\n",
+    "    B == swap [C] dip rest cons"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "We can create a quoted program that generates the Natural numbers (0, 1, 2, ...) by using `0` for `a` and `[dup ++]` for `[C]`:\n",
     "\n",
     "    [0 swap [dup ++] dip rest cons]\n",
     "\n",
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "# Generating Generators\n",
-    "We want to go from:\n",
-    "\n",
-    "    a [C] G\n",
-    "\n",
-    "to:\n",
-    "\n",
-    "    [a swap [C] direco]\n",
+    "# Making Generators\n",
+    "We want to define a function that accepts `a` and `[C]` and builds our quoted program:\n",
     "\n",
+    "             a [C] G\n",
+    "    -------------------------\n",
+    "       [a swap [C] direco]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "Working in reverse:\n",
     "\n",
     "    [a swap   [C] direco] cons\n",
     "Reading from the bottom up:\n",
     "\n",
     "    G == [direco] cons [swap] swap concat cons\n",
-    "    G == [direco] cons [swap] swoncat cons\n",
-    "\n",
-    "We can try it out:\n",
-    "\n",
-    "    0 [dup ++] G"
+    "    G == [direco] cons [swap] swoncat cons"
    ]
   },
   {
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 7,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "                           . 0 [dup ++] G\n",
-      "                         0 . [dup ++] G\n",
-      "                0 [dup ++] . G\n",
-      "                0 [dup ++] . [direco] cons [swap] swoncat cons\n",
-      "       0 [dup ++] [direco] . cons [swap] swoncat cons\n",
-      "       0 [[dup ++] direco] . [swap] swoncat cons\n",
-      "0 [[dup ++] direco] [swap] . swoncat cons\n",
-      "0 [[dup ++] direco] [swap] . swap concat cons\n",
-      "0 [swap] [[dup ++] direco] . concat cons\n",
-      "  0 [swap [dup ++] direco] . cons\n",
-      "  [0 swap [dup ++] direco] . \n"
-     ]
-    }
-   ],
-   "source": [
-    "V('0 [dup ++] G')"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 8,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "                                    . 0 [dup ++] G x\n",
-      "                                  0 . [dup ++] G x\n",
-      "                         0 [dup ++] . G x\n",
-      "                         0 [dup ++] . [direco] cons [swap] swoncat cons x\n",
-      "                0 [dup ++] [direco] . cons [swap] swoncat cons x\n",
-      "                0 [[dup ++] direco] . [swap] swoncat cons x\n",
-      "         0 [[dup ++] direco] [swap] . swoncat cons x\n",
-      "         0 [[dup ++] direco] [swap] . swap concat cons x\n",
-      "         0 [swap] [[dup ++] direco] . concat cons x\n",
-      "           0 [swap [dup ++] direco] . cons x\n",
-      "           [0 swap [dup ++] direco] . x\n",
-      "           [0 swap [dup ++] direco] . 0 swap [dup ++] direco\n",
-      "         [0 swap [dup ++] direco] 0 . swap [dup ++] direco\n",
-      "         0 [0 swap [dup ++] direco] . [dup ++] direco\n",
-      "0 [0 swap [dup ++] direco] [dup ++] . direco\n",
-      "0 [0 swap [dup ++] direco] [dup ++] . dip rest cons\n",
-      "                                  0 . dup ++ [0 swap [dup ++] direco] rest cons\n",
-      "                                0 0 . ++ [0 swap [dup ++] direco] rest cons\n",
-      "                                0 1 . [0 swap [dup ++] direco] rest cons\n",
-      "       0 1 [0 swap [dup ++] direco] . rest cons\n",
-      "         0 1 [swap [dup ++] direco] . cons\n",
-      "         0 [1 swap [dup ++] direco] . \n"
-     ]
-    }
-   ],
-   "source": [
-    "V('0 [dup ++] G x')"
-   ]
-  },
-  {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "### Powers of 2"
+    "Let's try it out:"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 7,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "1 2 4 8 16 32 64 128 256 [512 swap [dup 1 <<] direco]\n"
+      "[0 swap [dup ++] direco]\n"
      ]
     }
    ],
    "source": [
-    "J('1 [dup 1 <<] G x x x x x x x x x')"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "# `n [x] times`\n",
-    "If we have one of these quoted programs we can drive it using `times` with the `x` combinator.\n",
-    "\n",
-    "Let's define a word `n_range` that takes a starting integer and a count and leaves that many consecutive integers on the stack.  For example:"
+    "J('0 [dup ++] G')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "23 24 25 26 27\n"
+      "0 1 2\n"
      ]
     }
    ],
    "source": [
-    "J('23 [dup ++] G 5 [x] times pop')"
+    "J('0 [dup ++] G x x x pop')"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "We can use `dip` to untangle `[dup ++] G` from the arguments."
+    "### Powers of 2"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 9,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "23 24 25 26 27\n"
+      "1 2 4 8 16 32 64 128 256\n"
      ]
     }
    ],
    "source": [
-    "J('23 5 [[dup ++] G] dip [x] times pop')"
+    "J('1 [dup 1 <<] G x x x x x x x x x pop')"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Now that the givens (arguments) are on the left we have the definition we're looking for:"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 12,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "define('n_range == [[dup ++] G] dip [x] times pop')"
+    "### `[x] times`\n",
+    "If we have one of these quoted programs we can drive it using `times` with the `x` combinator."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "450 451 452 453 454 455 456 457 458 459\n"
-     ]
-    }
-   ],
-   "source": [
-    "J('450 10 n_range')"
-   ]
-  },
-  {
-   "cell_type": "markdown",
+   "execution_count": 10,
    "metadata": {},
-   "source": [
-    "This is better just using the `times` combinator though..."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 14,
-   "metadata": {
-    "scrolled": true
-   },
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "450 451 452 453 454 455 456 457 458 459\n"
+      "23 24 25 26 27 [28 swap [dup ++] direco]\n"
      ]
     }
    ],
    "source": [
-    "J('450 9 [dup ++] times')"
+    "J('23 [dup ++] G 5 [x] times')"
    ]
   },
   {
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 11,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 13,
    "metadata": {},
    "outputs": [
     {
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 18,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "3 [3702 swap [PE1.1] direco]\n"
-     ]
-    }
-   ],
-   "source": [
-    "J('[14811 swap [PE1.1] direco] x')"
-   ]
-  },
-  {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
+   "execution_count": 14,
    "metadata": {
     "scrolled": true
    },
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[14811 swap [PE1.1.check PE1.1] direco]\n"
+     ]
+    }
+   ],
+   "source": [
+    "J('14811 [PE1.1.check PE1.1] G')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
    "metadata": {},
    "outputs": [
     {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
+    "(It would be more efficient to reset the int every seven cycles but that's a little beyond the scope of this article.  This solution does extra work, but not much, and we're not using it \"in production\" as they say.)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "### Run 466 times\n",
     "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."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 18,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 23,
+   "execution_count": 19,
    "metadata": {
     "scrolled": false
    },
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "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] dip rest cons]\n"
+      "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]\n"
      ]
     }
    ],
    "source": [
-    "J('[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times')"
+    "J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 24,
+   "execution_count": 20,
    "metadata": {
     "scrolled": true
    },
     }
    ],
    "source": [
-    "J('[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times pop enstacken sum')"
+    "J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')"
    ]
   },
   {
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 21,
    "metadata": {},
    "outputs": [],
    "source": [
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Now we can add `PE1.2` to the quoted program given to `times`."
+    "Now we can add `PE1.2` to the quoted program given to `G`."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 22,
    "metadata": {},
    "outputs": [
     {
     }
    ],
    "source": [
-    "J('0 0 [0 swap [PE1.1.check PE1.1] direco] 466 [x [PE1.2] dip] times popop')"
+    "J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop')"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Or using `G` we can write:"
+    "# A generator for the Fibonacci Sequence.\n",
+    "Consider:\n",
+    "\n",
+    "    [b a F] x\n",
+    "    [b a F] b a F"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 27,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "233168\n"
-     ]
-    }
-   ],
    "source": [
-    "J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop')"
+    "The obvious first thing to do is just add `b` and `a`:\n",
+    "\n",
+    "    [b a F] b a +\n",
+    "    [b a F] b+a"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "# A generator for the Fibonacci Sequence.\n",
-    "Consider:\n",
-    "\n",
-    "    [b a F] x\n",
-    "    [b a F] b a F\n",
-    "\n",
-    "The obvious first thing to do is just add `b` and `a`:\n",
-    "\n",
-    "    [b a F] b a +\n",
-    "    [b a F] b+a\n",
-    "\n",
     "From here we want to arrive at:\n",
     "\n",
-    "    b [b+a b F]\n",
-    "\n",
+    "    b [b+a b F]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "Let's start with `swons`:\n",
     "\n",
     "    [b a F] b+a swons\n",
-    "    [b+a b a F]\n",
-    "\n",
+    "    [b+a b a F]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "Considering this quote as a stack:\n",
     "\n",
-    "    F a b b+a\n",
-    "\n",
+    "    F a b b+a"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "We want to get it to:\n",
     "\n",
-    "    F b b+a b\n",
-    "\n",
+    "    F b b+a b"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "So:\n",
     "\n",
     "    F a b b+a popdd over\n",
-    "    F b b+a b\n",
-    "\n",
+    "    F b b+a b"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "And therefore:\n",
     "\n",
     "    [b+a b a F] [popdd over] infra\n",
-    "    [b b+a b F]\n",
+    "    [b b+a b F]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "But we can just use `cons` to carry `b+a` into the quote:\n",
     "\n",
-    "And lastly:\n",
+    "    [b a F] b+a [popdd over] cons infra\n",
+    "    [b a F] [b+a popdd over]      infra\n",
+    "    [b b+a b F]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Lastly:\n",
     "\n",
     "    [b b+a b F] uncons\n",
-    "    b [b+a b F]\n",
-    "\n",
-    "Done.\n",
-    "\n",
+    "    b [b+a b F]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
     "Putting it all together:\n",
     "\n",
-    "    F == + swons [popdd over] infra uncons\n",
-    "\n",
-    "And:\n",
-    "\n",
+    "    F == + [popdd over] cons infra uncons\n",
     "    fib_gen == [1 1 F]"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 23,
    "metadata": {},
    "outputs": [],
    "source": [
-    "define('fib == + swons [popdd over] infra uncons')"
+    "define('fib == + [popdd over] cons infra uncons')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 24,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 25,
    "metadata": {},
    "outputs": [
     {
    "metadata": {},
    "source": [
     "### Project Euler Problem Two\n",
-    "    By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.\n",
+    "    By considering the terms in the Fibonacci sequence whose values do not exceed four million,\n",
+    "    find the sum of the even-valued terms.\n",
     "\n",
     "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."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 31,
+   "execution_count": 26,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 32,
+   "execution_count": 27,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 28,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 29,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 30,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 36,
+   "execution_count": 31,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 37,
+   "execution_count": 32,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 38,
+   "execution_count": 33,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 39,
+   "execution_count": 34,
    "metadata": {},
    "outputs": [
     {
     "# How to compile these?\n",
     "You would probably start with a special version of `G`, and perhaps modifications to the default `x`?"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# An Interesting Variation"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "define('codireco == cons dip rest cons')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "                                 . [0 [dup ++] codireco] x\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] . \n"
+     ]
+    }
+   ],
+   "source": [
+    "V('[0 [dup ++] codireco] x')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 37,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "define('G == [codireco] cons cons')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 38,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "230 231 232 233 234\n"
+     ]
+    }
+   ],
+   "source": [
+    "J('230 [dup ++] G 5 [x] times pop')"
+   ]
   }
  ],
  "metadata": {
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython2",
-   "version": "2.7.13"
+   "version": "2.7.12"
   }
  },
  "nbformat": 4,
index 2d58dd0..fde17ad 100644 (file)
     "- A base case value `c :: B`\n",
     "\n",
     "\n",
-    "### Hylo- Ana-, Cata-\n",
+    "### Hylo-, Ana-, Cata-\n",
     "\n",
     "    w/ G :: A -> (A, B)\n",
     "\n",
    "metadata": {},
    "source": [
     "### 4\n",
-    "And, last but not least, if you can combine as you go, starting with c, and the combiner needs to work on the current item this is the form:\n",
+    "And, last but not least, if you can combine as you go, starting with c, and the combiner needs to work on the current item, this is the form:\n",
     "\n",
     "    W == c swap [P] [pop] [[F] dupdip G] primrec\n",
     "\n",
index 9ba1208..89029f1 100644 (file)
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython2",
-   "version": "2.7.13"
+   "version": "2.7.12"
   }
  },
  "nbformat": 4,
index 93c3b79..6eb1c5e 100644 (file)
    "metadata": {},
    "source": [
     "## `treestep`\n",
-    "In the spirit of `step` we are going to define a combinator `treestep` which expects a tree and three additional items: a base-case value `z`, and two quoted programs `[N]` and `[C]`.\n",
+    "In the spirit of `step` we are going to define a combinator `treestep` which expects a tree and three additional items: a base-case function `[B]`, and two quoted programs `[N]` and `[C]`.\n",
     "\n",
-    "    tree z [N] [C] treestep"
+    "    tree [B] [N] [C] treestep"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "The base-case value `z` is of some type `Z`, the `[N]` function is executed per-node and should accept the node value (whatever it is) and return a value of type `A` (which can be `Z`), and the `[C]` function should expect an `A` and a list of `Z` and return a value of type `Z`:\n",
+    "If the current tree node is empty then just execute `B`:\n",
     "\n",
-    "    z :: Z\n",
-    "    N :: node -> A\n",
-    "    C :: A [Z*] -> Z"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "If the current tree node is empty then just leave `z` on the stack in lieu:\n",
-    "\n",
-    "       [] z [N] [C] treestep\n",
+    "       [] [B] [N] [C] treestep\n",
     "    ---------------------------\n",
-    "          z"
+    "       []  B"
    ]
   },
   {
    "source": [
     "Otherwise, evaluate `N` on the node value, `map` the whole function (abbreviated here as `K`) over the child trees recursively, and then combine the result with `C`.\n",
     "\n",
-    "       [node tree*] z [N] [C] treestep\n",
-    "    --------------------------------------- w/ K == z [N] [C] treestep\n",
-    "           node N [tree*] [K] map C"
+    "       [node tree*] [B] [N] [C] treestep\n",
+    "    --------------------------------------- w/ K == [B] [N] [C] treestep\n",
+    "           node N [tree*] [K] map C\n",
+    "\n",
+    "(Later on we'll experiment with making `map` part of `C` so you can use other combinators.)"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Derive the recursive form.\n",
-    "We can begin to derive it by finding the `ifte` stage that `genrec` will produce.  The predicate and base-case functions are trivial, so we just have to derive `J`.\n",
+    "## Derive the recursive function.\n",
+    "We can begin to derive it by finding the `ifte` stage that `genrec` will produce.\n",
     "\n",
-    "    K == [not] [pop z] [J] ifte"
+    "    K == [not] [B] [R0]   [R1] genrec\n",
+    "      == [not] [B] [R0 [K] R1] ifte\n",
+    "\n",
+    "So we just have to derive `J`:\n",
+    "\n",
+    "    J == R0 [K] R1"
    ]
   },
   {
@@ -80,7 +76,7 @@
    "source": [
     "So `J` will have some form like:\n",
     "\n",
-    "    J == .. [N] .. [K] .. [C] .."
+    "    J == ... [N] ... [K] ... [C] ..."
    ]
   },
   {
    "source": [
     "Plug it in and convert to `genrec`:\n",
     "\n",
-    "    K == [not] [pop z] [J                       ] ifte\n",
-    "    K == [not] [pop z] [uncons [N] dip [K] map C] ifte\n",
-    "    K == [not] [pop z] [uncons [N] dip]   [map C] genrec"
+    "    K == [not] [B] [J                       ] ifte\n",
+    "      == [not] [B] [uncons [N] dip [K] map C] ifte\n",
+    "      == [not] [B] [uncons [N] dip]   [map C] genrec"
    ]
   },
   {
     "## Extract the givens to parameterize the program.\n",
     "Working backwards:\n",
     "\n",
-    "    [not] [pop z]                   [uncons [N] dip] [map C] genrec\n",
-    "    [not] [z]         [pop] swoncat [uncons [N] dip] [map C] genrec\n",
-    "    [not]  z     unit [pop] swoncat [uncons [N] dip] [map C] genrec\n",
-    "    z [not] swap unit [pop] swoncat [uncons [N] dip] [map C] genrec\n",
-    "      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "    TS0 == [not] swap unit [pop] swoncat"
+    "    [not] [B]          [uncons [N] dip]                  [map C] genrec\n",
+    "    [B] [not] swap     [uncons [N] dip]                  [map C] genrec\n",
+    "    [B]                [uncons [N] dip] [[not] swap] dip [map C] genrec\n",
+    "                                        ^^^^^^^^^^^^^^^^\n",
+    "    [B] [[N] dip]      [uncons] swoncat [[not] swap] dip [map C] genrec\n",
+    "    [B] [N] [dip] cons [uncons] swoncat [[not] swap] dip [map C] genrec\n",
+    "            ^^^^^^^^^^^^^^^^^^^^^^^^^^^"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "    z TS0 [uncons [N] dip]                            [map C] genrec\n",
-    "    z     [uncons [N] dip]                  [TS0] dip [map C] genrec\n",
-    "    z       [[N] dip]      [uncons] swoncat [TS0] dip [map C] genrec\n",
-    "    z       [N] [dip] cons [uncons] swoncat [TS0] dip [map C] genrec\n",
-    "                ^^^^^^^^^^^^^^^^^^^^^^^^^^^"
+    "Extract a couple of auxiliary definitions:\n",
+    "\n",
+    "    TS.0 == [[not] swap] dip\n",
+    "    TS.1 == [dip] cons [uncons] swoncat"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "    TS1 == [dip] cons [uncons] swoncat"
+    "    [B] [N] TS.1 TS.0 [map C]                         genrec\n",
+    "    [B] [N]           [map C]         [TS.1 TS.0] dip genrec\n",
+    "    [B] [N] [C]         [map] swoncat [TS.1 TS.0] dip genrec\n",
+    "\n",
+    "The givens are all to the left so we have our definition."
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "    z [N] TS1 [TS0] dip [map C]                             genrec\n",
-    "    z [N]               [map C]         [TS1 [TS0] dip] dip genrec\n",
-    "    z [N]             [C] [map] swoncat [TS1 [TS0] dip] dip genrec\n",
+    "### (alternate) Extract the givens to parameterize the program.\n",
+    "Working backwards:\n",
     "\n",
-    "The givens are all to the left so we have our definition."
+    "    [not] [B]           [uncons [N] dip]            [map C] genrec\n",
+    "    [not] [B] [N]       [dip] cons [uncons] swoncat [map C] genrec\n",
+    "    [B] [N] [not] roll> [dip] cons [uncons] swoncat [map C] genrec\n",
+    "            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
    ]
   },
   {
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 1,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [],
    "source": [
     "DefinitionWrapper.add_definitions('''\n",
     "\n",
-    "    _treestep_0 == [not] swap unit [pop] swoncat\n",
+    "    _treestep_0 == [[not] swap] dip\n",
     "    _treestep_1 == [dip] cons [uncons] swoncat\n",
-    "    treegrind == [_treestep_1 [_treestep_0] dip] dip genrec\n",
+    "    treegrind == [_treestep_1 _treestep_0] dip genrec\n",
     "    treestep == [map] swoncat treegrind\n",
     "\n",
     "''', D)"
     "## Examples\n",
     "Consider trees, the nodes of which are integers.  We can find the sum of all nodes in a tree with this function:\n",
     "\n",
-    "    sumtree == 0 [] [sum +] treestep"
+    "    sumtree == [pop 0] [] [sum +] treestep"
    ]
   },
   {
-   "cell_type": "markdown",
+   "cell_type": "code",
+   "execution_count": 3,
    "metadata": {},
+   "outputs": [],
    "source": [
-    "Running this function on an empty tree value gives zero:\n",
-    "\n",
-    "       [] 0 [N] [C] treestep\n",
-    "    ---------------------------\n",
-    "          0"
+    "define('sumtree == [pop 0] [] [sum +] treestep')"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Running it on a non-empty node:\n",
+    "Running this function on an empty tree value gives zero:\n",
     "\n",
-    "    [n tree*]  0 [] [sum +] treestep\n",
-    "    n [tree*] [0 [] [sum +] treestep] map sum +\n",
-    "    n [ ... ]                             sum +\n",
-    "    n m                                       +\n",
-    "    n+m\n"
+    "       [] [pop 0] [] [sum +] treestep\n",
+    "    ------------------------------------\n",
+    "               0"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "define('sumtree == 0 [] [sum +] treestep')"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
    ]
   },
   {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Running it on a non-empty node:\n",
+    "\n",
+    "    [n tree*]  [pop 0] [] [sum +] treestep\n",
+    "    n [tree*] [[pop 0] [] [sum +] treestep] map sum +\n",
+    "    n [ ... ]                                   sum +\n",
+    "    n m                                             +\n",
+    "    n+m\n"
+   ]
+  },
+  {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 5,
    "metadata": {
     "scrolled": true
    },
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 6,
    "metadata": {
     "scrolled": true
    },
   },
   {
    "cell_type": "code",
-   "execution_count": 23,
+   "execution_count": 7,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 24,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 9,
    "metadata": {},
    "outputs": [
     {
     }
    ],
    "source": [
-    "J('[23 [2 [8] [9]] [3] [4 []]] 0 [] [cons sum] treestep')  # Alternate \"spelling\"."
+    "J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep')  # Alternate \"spelling\"."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 10,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 11,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 13,
    "metadata": {
     "scrolled": false
    },
     }
    ],
    "source": [
-    "J('[23 [2 [8] [9]] [3] [4 []]] 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."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "3\n"
+     ]
+    }
+   ],
+   "source": [
+    "J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep')  # Combine replace and sum into one function."
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Redefining our BTree in terms of this form.\n",
+    "## Redefining the Ordered Binary Tree in terms of `treestep`.\n",
     "\n",
-    "    BTree = [] | [[key value] left right]"
+    "    Tree = [] | [[key value] left right]"
    ]
   },
   {
    "metadata": {},
    "source": [
     "### Traversal\n",
-    "    [key value] uncons pop [left right] [K] map i\n",
-    "    key [value]        pop [left right] [K] map i\n",
-    "    key                    [left right] [K] map i\n",
-    "    key                    [lkey rkey ]         i\n",
-    "    key                     lkey rkey"
+    "    [key value] first [left right] [K] map i\n",
+    "    key [value]       [left right] [K] map i\n",
+    "    key               [left right] [K] map i\n",
+    "    key               [lkey rkey ]         i\n",
+    "    key                lkey rkey"
    ]
   },
   {
   },
   {
    "cell_type": "code",
-   "execution_count": 14,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "3 23 23\n"
+      "3 'B' 'B'\n"
      ]
     }
    ],
    "source": [
-    "J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]]   23 [uncons pop] [i] treestep')"
+    "J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] [\"B\"] [first] [i] treestep')"
    ]
   },
   {
     "\n",
     "So:\n",
     "\n",
-    "    [] [flatten cons] [first] treestep"
+    "    [] [first] [flatten cons] treestep"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 16,
    "metadata": {
     "scrolled": true
    },
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "### In-order traversal with `treestep`.\n",
+    "### In-order traversal\n",
     "\n",
     "From here:\n",
     "\n",
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 17,
    "metadata": {},
    "outputs": [
     {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## with `treegrind`?\n",
-    "What kind of functions can we write for this with our `treegrind`?\n",
-    "\n",
-    "The pattern for processing a non-empty node is:\n",
+    "## With `treegrind`?\n",
+    "The `treegrind` function doesn't include the `map` combinator, so the `[C]` function must arrange to use some combinator on the quoted recursive copy `[K]`.  With this function, the pattern for processing a non-empty node is:\n",
     "\n",
     "    node N [tree*] [K] C\n",
     "\n",
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 18,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "['key' 'value'] 'N' [['left'] ['right']] [[not] ['B'] [uncons ['N'] dip] ['C'] genrec] 'C'\n"
+     ]
+    }
+   ],
+   "source": [
+    "J('[[\"key\" \"value\"] [\"left\"] [\"right\"] ] [\"B\"] [\"N\"] [\"C\"] treegrind')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## `treegrind` with `step`"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Iteration through the nodes"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "23 'N' [[44] [18]] [[not] [pop 'z'] [uncons ['N'] dip] ['C'] genrec] 'C'\n"
+      "[3 0] 'N' [2 0] 'N' [9 0] 'N' [5 0] 'N' [4 0] 'N' [8 0] 'N' [6 0] 'N' [7 0] 'N'\n"
      ]
     }
    ],
    "source": [
-    "J('[23 [44] [18] ] \"z\" [\"N\"] [\"C\"] treegrind')"
+    "J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [pop] [\"N\"] [step] treegrind')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Sum the nodes' keys."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 20,
    "metadata": {},
-   "outputs": [],
-   "source": []
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "44\n"
+     ]
+    }
+   ],
+   "source": [
+    "J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [pop] [first +] [step] treegrind')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Rebuild the tree using `map` (imitating `treestep`.)"
+   ]
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 21,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "[3 0] 'N' [2 0] 'N' 23 23 [9 0] 'N' [5 0] 'N' [4 0] 'N' 23 23 [8 0] 'N' [6 0] 'N' 23 [7 0] 'N' 23 23 23 23\n"
+      "[[103 0] [[102 0] [] []] [[109 0] [[105 0] [[104 0] [] []] [[108 0] [[106 0] [] [[107 0] [] []]] []]] []]]\n"
      ]
     }
    ],
    "source": [
-    "J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   23 [\"N\"] [step] treegrind')"
+    "J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [[100 +] infra] [map cons] treegrind')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Do we have the flexibility to reimplement `Tree-get`?\n",
+    "I think we do:\n",
+    "\n",
+    "    [B] [N] [C] treegrind"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "We'll start by saying that the base-case (the key is not in the tree) is user defined, and the per-node function is just the query key literal:\n",
+    "\n",
+    "    [B] [query_key] [C] treegrind"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "This means we just have to define `C` from:\n",
+    "\n",
+    "    [key value] query_key [left right] [K] C\n",
+    " "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Let's try `cmp`:\n",
+    "\n",
+    "    C == P [T>] [E] [T<] cmp\n",
+    "\n",
+    "    [key value] query_key [left right] [K] P [T>] [E] [T<] cmp"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### The predicate `P`\n",
+    "Seems pretty easy (we must preserve the value in case the keys are equal):\n",
+    "\n",
+    "    [key value] query_key [left right] [K] P\n",
+    "    [key value] query_key [left right] [K] roll<\n",
+    "    [key value] [left right] [K] query_key       [roll< uncons swap] dip\n",
+    "\n",
+    "    [key value] [left right] [K] roll< uncons swap query_key\n",
+    "    [left right] [K] [key value]       uncons swap query_key\n",
+    "    [left right] [K] key [value]              swap query_key\n",
+    "    [left right] [K] [value] key                   query_key\n",
+    "\n",
+    "    P == roll< [roll< uncons swap] dip\n",
+    "\n",
+    "(Possibly with a swap at the end?  Or just swap `T<` and `T>`.)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "So now:\n",
+    "\n",
+    "    [left right] [K] [value] key query_key [T>] [E] [T<] cmp\n",
+    "\n",
+    "Becomes one of these three:\n",
+    "\n",
+    "    [left right] [K] [value] T>\n",
+    "    [left right] [K] [value] E\n",
+    "    [left right] [K] [value] T<\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### `E`\n",
+    "Easy.\n",
+    "\n",
+    "    E == roll> popop first"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### `T<` and `T>`\n",
+    "\n",
+    "    T< == pop [first] dip i\n",
+    "    T> == pop [second] dip i"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Putting it together\n",
+    "\n",
+    "\n",
+    "    T> == pop [first] dip i\n",
+    "    T< == pop [second] dip i\n",
+    "    E == roll> popop first\n",
+    "    P == roll< [roll< uncons swap] dip\n",
+    "    \n",
+    "    Tree-get == [P [T>] [E] [T<] cmp] treegrind\n",
+    "\n",
+    "To me, that seems simpler than the `genrec` version."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "DefinitionWrapper.add_definitions('''\n",
+    "\n",
+    "    T> == pop [first] dip i\n",
+    "    T< == pop [second] dip i\n",
+    "    E == roll> popop first\n",
+    "    P == roll< [roll< uncons swap] dip\n",
+    "\n",
+    "    Tree-get == [P [T>] [E] [T<] cmp] treegrind\n",
+    "\n",
+    "''', D)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from joy.library import FunctionWrapper\n",
+    "from joy.utils.stack import pushback\n",
+    "\n",
+    "\n",
+    "@FunctionWrapper\n",
+    "def cmp_(stack, expression, dictionary):\n",
+    "    '''\n",
+    "    cmp takes two values and three quoted programs on the stack and runs\n",
+    "    one of the three depending on the results of comparing the two values:\n",
+    "\n",
+    "           a b [G] [E] [L] cmp\n",
+    "        ------------------------- a > b\n",
+    "                G\n",
+    "\n",
+    "           a b [G] [E] [L] cmp\n",
+    "        ------------------------- a = b\n",
+    "                    E\n",
+    "\n",
+    "           a b [G] [E] [L] cmp\n",
+    "        ------------------------- a < b\n",
+    "                        L\n",
+    "    '''\n",
+    "    L, (E, (G, (b, (a, stack)))) = stack\n",
+    "    expression = pushback(G if a > b else L if a < b else E, expression)\n",
+    "    return stack, expression, dictionary\n",
+    "\n",
+    "\n",
+    "D['cmp'] = cmp_"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 36,
+   "execution_count": 24,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "0 3 2 23 23 9 5 4 23 23 8 6 23 7 23 23 23 23\n"
+      "15\n"
      ]
     }
    ],
    "source": [
-    "J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   23 [first ] [step] treegrind')"
+    "J('''\\\n",
+    "\n",
+    "[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]\n",
+    "\n",
+    "[] [5] Tree-get\n",
+    "\n",
+    "''')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 39,
+   "execution_count": 25,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "0 [3 [2 [] []] [9 [5 [4 [] []] [8 [6 [] [7 [] []]] []]] []]]\n"
+      "'nope'\n"
      ]
     }
    ],
    "source": [
-    "J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]]   [] [first ] [map cons] treegrind')"
+    "J('''\\\n",
+    "\n",
+    "[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]\n",
+    "\n",
+    "[pop \"nope\"] [25] Tree-get\n",
+    "\n",
+    "''')"
    ]
   },
   {
index 67ca6d0..ceec382 100644 (file)
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython2",
-   "version": "2.7.13"
+   "version": "2.7.12"
   }
  },
  "nbformat": 4,