More docs.
This commit is contained in:
parent
e67a6f7b6e
commit
9a04534b05
|
|
@ -3,4 +3,5 @@ build
|
|||
.hypothesis
|
||||
.pytest_cache
|
||||
.vscode
|
||||
docs/.ipynb_checkpoints
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.13"
|
||||
"version": "2.7.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
|
|
@ -22,29 +22,56 @@
|
|||
"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",
|
||||
" 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",
|
||||
" 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",
|
||||
"\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",
|
||||
|
|
@ -154,15 +181,18 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Generating Generators\n",
|
||||
"We want to go from:\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",
|
||||
"to:\n",
|
||||
"\n",
|
||||
" [a swap [C] direco]\n",
|
||||
"\n",
|
||||
" -------------------------\n",
|
||||
" [a swap [C] direco]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Working in reverse:\n",
|
||||
"\n",
|
||||
" [a swap [C] direco] cons\n",
|
||||
|
|
@ -174,11 +204,7 @@
|
|||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -190,6 +216,13 @@
|
|||
"define('G == [direco] cons [swap] swoncat cons')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's try it out:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
|
|
@ -199,22 +232,12 @@
|
|||
"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"
|
||||
"[0 swap [dup ++] direco]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"V('0 [dup ++] G')"
|
||||
"J('0 [dup ++] G')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -226,33 +249,12 @@
|
|||
"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"
|
||||
"0 1 2\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"V('0 [dup ++] G x')"
|
||||
"J('0 [dup ++] G x x x pop')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -271,22 +273,20 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"1 2 4 8 16 32 64 128 256 [512 swap [dup 1 <<] direco]\n"
|
||||
"1 2 4 8 16 32 64 128 256\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('1 [dup 1 <<] G x x x x x x x x x')"
|
||||
"J('1 [dup 1 <<] G x x x x x x x x x pop')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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:"
|
||||
"### `[x] times`\n",
|
||||
"If we have one of these quoted programs we can drive it using `times` with the `x` combinator."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -298,95 +298,12 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"23 24 25 26 27\n"
|
||||
"23 24 25 26 27 [28 swap [dup ++] direco]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('23 [dup ++] G 5 [x] times pop')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We can use `dip` to untangle `[dup ++] G` from the arguments."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"23 24 25 26 27\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('23 5 [[dup ++] G] dip [x] times 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')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"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"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('450 9 [dup ++] times')"
|
||||
"J('23 [dup ++] G 5 [x] times')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -408,7 +325,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
|
|
@ -417,7 +334,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -451,7 +368,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -466,23 +383,6 @@
|
|||
"J('14811 [PE1.1] G')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": {},
|
||||
|
|
@ -492,7 +392,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
|
|
@ -519,7 +419,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
|
|
@ -528,7 +428,24 @@
|
|||
},
|
||||
{
|
||||
"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": [
|
||||
{
|
||||
|
|
@ -543,6 +460,13 @@
|
|||
"J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": {},
|
||||
|
|
@ -553,7 +477,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -577,7 +501,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 19,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
|
|
@ -586,17 +510,17 @@
|
|||
"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
|
||||
},
|
||||
|
|
@ -610,7 +534,7 @@
|
|||
}
|
||||
],
|
||||
"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')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -622,7 +546,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
|
|
@ -633,36 +557,12 @@
|
|||
"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,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"233168\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('0 0 [0 swap [PE1.1.check PE1.1] direco] 466 [x [PE1.2] dip] times popop')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Or using `G` we can write:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -685,68 +585,119 @@
|
|||
"Consider:\n",
|
||||
"\n",
|
||||
" [b a F] x\n",
|
||||
" [b a F] b a F\n",
|
||||
"\n",
|
||||
" [b a F] b a F"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"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",
|
||||
" [b a F] b+a"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"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": [
|
||||
|
|
@ -755,7 +706,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -775,14 +726,15 @@
|
|||
"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": [
|
||||
|
|
@ -798,7 +750,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
|
|
@ -814,7 +766,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
|
|
@ -823,7 +775,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -876,7 +828,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 35,
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -900,7 +852,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 36,
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -917,7 +869,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
|
|
@ -926,7 +878,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 38,
|
||||
"execution_count": 33,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -950,7 +902,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 39,
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -972,6 +924,78 @@
|
|||
"# 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": {
|
||||
|
|
@ -990,7 +1014,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.13"
|
||||
"version": "2.7.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
|
|
@ -1694,7 +1694,7 @@
|
|||
"- 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",
|
||||
|
|
@ -1812,7 +1812,7 @@
|
|||
"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",
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.13"
|
||||
"version": "2.7.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
|
|
@ -15,31 +15,20 @@
|
|||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -48,19 +37,26 @@
|
|||
"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] ..."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -120,9 +116,9 @@
|
|||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -132,28 +128,12 @@
|
|||
"## 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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
" [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",
|
||||
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^"
|
||||
]
|
||||
},
|
||||
|
|
@ -161,20 +141,36 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
" TS1 == [dip] cons [uncons] swoncat"
|
||||
"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": [
|
||||
" 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",
|
||||
" [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": [
|
||||
"### (alternate) Extract the givens to parameterize the program.\n",
|
||||
"Working backwards:\n",
|
||||
"\n",
|
||||
" [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": "markdown",
|
||||
"metadata": {},
|
||||
|
|
@ -184,7 +180,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
|
|
@ -193,15 +189,15 @@
|
|||
},
|
||||
{
|
||||
"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)"
|
||||
|
|
@ -214,7 +210,16 @@
|
|||
"## 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": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('sumtree == [pop 0] [] [sum +] treestep')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -223,36 +228,14 @@
|
|||
"source": [
|
||||
"Running this function on an empty tree value gives zero:\n",
|
||||
"\n",
|
||||
" [] 0 [N] [C] treestep\n",
|
||||
" ---------------------------\n",
|
||||
" [] [pop 0] [] [sum +] treestep\n",
|
||||
" ------------------------------------\n",
|
||||
" 0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Running it on a non-empty node:\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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
{
|
||||
|
|
@ -267,9 +250,22 @@
|
|||
"J('[] sumtree') # Empty tree."
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
},
|
||||
|
|
@ -288,7 +284,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
|
|
@ -307,7 +303,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -324,7 +320,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -341,7 +337,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -353,12 +349,12 @@
|
|||
}
|
||||
],
|
||||
"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": [
|
||||
{
|
||||
|
|
@ -375,7 +371,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -392,7 +388,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -409,7 +405,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
|
|
@ -423,16 +419,35 @@
|
|||
}
|
||||
],
|
||||
"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]"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -455,8 +470,8 @@
|
|||
"metadata": {},
|
||||
"source": [
|
||||
"### Traversal\n",
|
||||
" [key value] uncons pop [left right] [K] map i\n",
|
||||
" key [value] pop [left right] [K] map i\n",
|
||||
" [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"
|
||||
|
|
@ -471,19 +486,19 @@
|
|||
},
|
||||
{
|
||||
"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')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -503,12 +518,12 @@
|
|||
"\n",
|
||||
"So:\n",
|
||||
"\n",
|
||||
" [] [flatten cons] [first] treestep"
|
||||
" [] [first] [flatten cons] treestep"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 16,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
|
|
@ -536,7 +551,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### In-order traversal with `treestep`.\n",
|
||||
"### In-order traversal\n",
|
||||
"\n",
|
||||
"From here:\n",
|
||||
"\n",
|
||||
|
|
@ -554,7 +569,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -573,10 +588,8 @@
|
|||
"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",
|
||||
|
|
@ -587,77 +600,311 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"23 'N' [[44] [18]] [[not] [pop 'z'] [uncons ['N'] dip] ['C'] genrec] 'C'\n"
|
||||
"['key' 'value'] 'N' [['left'] ['right']] [[not] ['B'] [uncons ['N'] dip] ['C'] genrec] 'C'\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[23 [44] [18] ] \"z\" [\"N\"] [\"C\"] treegrind')"
|
||||
"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": null,
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[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('[[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": 20,
|
||||
"metadata": {},
|
||||
"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": 21,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[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] [] []]] []]] []]] [] [[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": []
|
||||
"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": 35,
|
||||
"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": 24,
|
||||
"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"
|
||||
"15\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] 23 [\"N\"] [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": 36,
|
||||
"execution_count": 25,
|
||||
"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"
|
||||
"'nope'\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] 23 [first ] [step] treegrind')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 39,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0 [3 [2 [] []] [9 [5 [4 [] []] [8 [6 [] [7 [] []]] []]] []]]\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",
|
||||
"''')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -493,7 +493,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.13"
|
||||
"version": "2.7.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
Loading…
Reference in New Issue