diff --git a/docs/Ordered_Binary_Trees.html b/docs/Ordered_Binary_Trees.html index 221b317..e5a218f 100644 --- a/docs/Ordered_Binary_Trees.html +++ b/docs/Ordered_Binary_Trees.html @@ -11775,7 +11775,7 @@ div#notebook {
Although any expression in Joy can be considered to describe a tree with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about ordered binary trees and how to make and use them.
+Although any expression in Joy can be considered to describe a tree with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about ordered binary trees and how to make and use them.
The basic structure, in a crude type notation, is:
Tree :: [] | [key value Tree Tree]
@@ -11886,6 +11886,24 @@ key [value [] []] cons
cmp combinator¶Instead of mucking about with nested ifte combinators let's just go whole hog and define cmp which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:
cmp combinator¶Instead of mucking about with nested ifte combinators let's use cmp which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
@@ -12518,47 +12536,6 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
from joy.library import FunctionWrapper
-from joy.utils.stack import pushback
-from notebook_preamble import D
-
-
-@FunctionWrapper
-def cmp_(stack, expression, dictionary):
- '''
- cmp takes two values and three quoted programs on the stack and runs
- one of the three depending on the results of comparing the two values:
-
- a b [G] [E] [L] cmp
- ------------------------- a > b
- G
-
- a b [G] [E] [L] cmp
- ------------------------- a = b
- E
-
- a b [G] [E] [L] cmp
- ------------------------- a < b
- L
- '''
- L, (E, (G, (b, (a, stack)))) = stack
- expression = pushback(G if a > b else L if a < b else E, expression)
- return stack, expression, dictionary
-
-
-D['cmp'] = cmp_
-J("1 0 ['G'] ['E'] ['L'] cmp")
@@ -12589,7 +12566,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
J("1 1 ['G'] ['E'] ['L'] cmp")
@@ -12620,7 +12597,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
J("0 1 ['G'] ['E'] ['L'] cmp")
@@ -12706,7 +12683,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
define('P == over [popop popop first] nullary')
@@ -12755,7 +12732,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec')
@@ -12768,7 +12745,7 @@ Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Still works.
@@ -12938,7 +12915,7 @@ key left-keys right-keys
define('Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec')
@@ -12959,7 +12936,7 @@ key left-keys right-keys
J('[] [foo] Tree-iter') # It doesn't matter what F is as it won't be used.
@@ -12990,7 +12967,7 @@ key left-keys right-keys
J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [first] Tree-iter")
@@ -13021,7 +12998,7 @@ key left-keys right-keys
J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [second] Tree-iter")
@@ -13061,7 +13038,7 @@ key left-keys right-keys
J('[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step')
@@ -13092,7 +13069,7 @@ key left-keys right-keys
define('to_set == [] swap [0 swap Tree-add] step')
@@ -13105,7 +13082,7 @@ key left-keys right-keys
J('[3 9 5 2 8 6 7 8 4] to_set')
@@ -13145,7 +13122,7 @@ key left-keys right-keys
define('unique == [to_set [first] Tree-iter] cons run')
@@ -13158,7 +13135,7 @@ key left-keys right-keys
J('[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique') # Filter duplicate items.
@@ -13302,7 +13279,7 @@ Tree-iter-order == [not] [pop] [dup third] [proc_left proc_current proc_right] g
#define('Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec')
@@ -13328,7 +13305,7 @@ Tree-iter-order == [not] [pop] [dup third] [proc_left proc_current proc_right] g
J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order')
@@ -13361,7 +13338,7 @@ Tree-iter-order == [not] [pop] [dup third] [proc_left proc_current proc_right] g
Parameterizing the [F] function is left as an exercise for the reader (for now.)
Parameterizing the [F] function is left as an exercise for the reader.
# I don't want to deal with name conflicts with the above so I'm inlining everything here.
@@ -13555,7 +13532,7 @@ Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec
J('["gary" 23 [] []] "mike" [popd " not in tree" +] Tree-get')
@@ -13586,7 +13563,7 @@ Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec
J('["gary" 23 [] []] "gary" [popop "err"] Tree-get')
@@ -13617,7 +13594,7 @@ Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec
J('''
@@ -13654,7 +13631,7 @@ Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec
J('''
@@ -13847,59 +13824,6 @@ T< == [dipdd] cons infra
from joy.library import FunctionWrapper, S_ifte
-
-
-@FunctionWrapper
-def cond(stack, expression, dictionary):
- '''
- like a case statement; works by rewriting into a chain of ifte.
-
- [..[[Bi] Ti]..[D]] -> ...
-
-
- [[[B0] T0] [[B1] T1] [D]] cond
- -----------------------------------------
- [B0] [T0] [[B1] [T1] [D] ifte] ifte
-
- '''
- conditions, stack = stack
- if conditions:
- expression = _cond(conditions, expression)
- try:
- # Attempt to preload the args to first ifte.
- (P, (T, (E, expression))) = expression
- except ValueError:
- # If, for any reason, the argument to cond should happen to contain
- # only the default clause then this optimization will fail.
- pass
- else:
- stack = (E, (T, (P, stack)))
- return stack, expression, dictionary
-
-
-def _cond(conditions, expression):
- (clause, rest) = conditions
- if not rest: # clause is [D]
- return clause
- P, T = clause
- return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
-
-
-
-D['cond'] = cond
-Minor rearrangement:
+Minor rearrangement, move dup into W:
W == dup [fourth] [fourth] while uncons uncons pop over
E′ == roll> popop rest [W] dip cons dipd swap
@@ -14218,9 +14142,9 @@ E == [
Refactoring¶
W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop
+W == dup W.rightmost W.unpack over
E.clear_stuff == roll> popop rest
E.delete == cons dipd
-W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [
[[pop third not] pop fourth]
@@ -14241,7 +14165,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
DefinitionWrapper.add_definitions('''
@@ -14258,7 +14182,8 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
T< == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp
-Tree-Delete == [pop not] [pop] [R0] [R1] genrec''', D)
+Tree-Delete == [pop not] [pop] [R0] [R1] genrec
+''', D)
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' Tree-Delete ")
@@ -14299,7 +14224,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' Tree-Delete ")
@@ -14330,7 +14255,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' Tree-Delete ")
@@ -14361,7 +14286,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' Tree-Delete ")
@@ -14392,7 +14317,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
J('[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step')
@@ -14423,7 +14348,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete ")
@@ -14454,7 +14379,7 @@ BTree-Delete == [pop not] swap [R0] [R1] genrec
J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete ")
diff --git a/docs/Ordered_Binary_Trees.ipynb b/docs/Ordered_Binary_Trees.ipynb
index f426b94..c9dfffe 100644
--- a/docs/Ordered_Binary_Trees.ipynb
+++ b/docs/Ordered_Binary_Trees.ipynb
@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Treating Trees I\n",
+ "# Treating Trees I: Ordered Binary Trees\n",
"\n",
"Although any expression in Joy can be considered to describe a [tree](https://en.wikipedia.org/wiki/Tree_structure) with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about [ordered binary trees](https://en.wikipedia.org/wiki/Binary_search_tree) and how to make and use them.\n",
"\n",
@@ -92,7 +92,15 @@
"cell_type": "code",
"execution_count": 3,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "['k' 'v' [] []]\n"
+ ]
+ }
+ ],
"source": [
"J('\"v\" \"k\" Tree-new')"
]
@@ -521,7 +529,7 @@
"metadata": {},
"source": [
"## Interlude: `cmp` combinator\n",
- "Instead of mucking about with nested `ifte` combinators let's just go whole hog and define `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:\n",
+ "Instead of mucking about with nested `ifte` combinators let's use `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:\n",
"\n",
" a b [G] [E] [L] cmp\n",
" ------------------------- a > b\n",
@@ -540,43 +548,6 @@
"cell_type": "code",
"execution_count": 20,
"metadata": {},
- "outputs": [],
- "source": [
- "from joy.library import FunctionWrapper\n",
- "from joy.utils.stack import pushback\n",
- "from notebook_preamble import D\n",
- "\n",
- "\n",
- "@FunctionWrapper\n",
- "def cmp_(stack, expression, dictionary):\n",
- " '''\n",
- " cmp takes two values and three quoted programs on the stack and runs\n",
- " one of the three depending on the results of comparing the two values:\n",
- "\n",
- " a b [G] [E] [L] cmp\n",
- " ------------------------- a > b\n",
- " G\n",
- "\n",
- " a b [G] [E] [L] cmp\n",
- " ------------------------- a = b\n",
- " E\n",
- "\n",
- " a b [G] [E] [L] cmp\n",
- " ------------------------- a < b\n",
- " L\n",
- " '''\n",
- " L, (E, (G, (b, (a, stack)))) = stack\n",
- " expression = pushback(G if a > b else L if a < b else E, expression)\n",
- " return stack, expression, dictionary\n",
- "\n",
- "\n",
- "D['cmp'] = cmp_"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
"outputs": [
{
"name": "stdout",
@@ -592,7 +563,7 @@
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 21,
"metadata": {},
"outputs": [
{
@@ -609,7 +580,7 @@
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 22,
"metadata": {},
"outputs": [
{
@@ -674,7 +645,7 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
@@ -713,7 +684,7 @@
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
@@ -722,7 +693,7 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 25,
"metadata": {
"scrolled": false
},
@@ -865,7 +836,7 @@
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
@@ -881,7 +852,7 @@
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": 27,
"metadata": {},
"outputs": [
{
@@ -898,7 +869,7 @@
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 28,
"metadata": {},
"outputs": [
{
@@ -915,7 +886,7 @@
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 29,
"metadata": {},
"outputs": [
{
@@ -940,7 +911,7 @@
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 30,
"metadata": {},
"outputs": [
{
@@ -957,7 +928,7 @@
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
@@ -966,7 +937,7 @@
},
{
"cell_type": "code",
- "execution_count": 33,
+ "execution_count": 32,
"metadata": {},
"outputs": [
{
@@ -990,7 +961,7 @@
},
{
"cell_type": "code",
- "execution_count": 34,
+ "execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
@@ -999,7 +970,7 @@
},
{
"cell_type": "code",
- "execution_count": 35,
+ "execution_count": 34,
"metadata": {
"scrolled": true
},
@@ -1117,7 +1088,7 @@
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
@@ -1141,7 +1112,7 @@
},
{
"cell_type": "code",
- "execution_count": 37,
+ "execution_count": 36,
"metadata": {},
"outputs": [
{
@@ -1160,7 +1131,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Parameterizing the `[F]` function is left as an exercise for the reader (for now.)"
+ "Parameterizing the `[F]` function is left as an exercise for the reader."
]
},
{
@@ -1310,7 +1281,7 @@
},
{
"cell_type": "code",
- "execution_count": 38,
+ "execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
@@ -1333,7 +1304,7 @@
},
{
"cell_type": "code",
- "execution_count": 39,
+ "execution_count": 38,
"metadata": {},
"outputs": [
{
@@ -1350,7 +1321,7 @@
},
{
"cell_type": "code",
- "execution_count": 40,
+ "execution_count": 39,
"metadata": {},
"outputs": [
{
@@ -1367,7 +1338,7 @@
},
{
"cell_type": "code",
- "execution_count": 41,
+ "execution_count": 40,
"metadata": {},
"outputs": [
{
@@ -1390,7 +1361,7 @@
},
{
"cell_type": "code",
- "execution_count": 52,
+ "execution_count": 41,
"metadata": {},
"outputs": [
{
@@ -1552,55 +1523,6 @@
"We have to handle three cases, so let's use `cond`."
]
},
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [],
- "source": [
- "from joy.library import FunctionWrapper, S_ifte\n",
- "\n",
- "\n",
- "@FunctionWrapper\n",
- "def cond(stack, expression, dictionary):\n",
- " '''\n",
- " like a case statement; works by rewriting into a chain of ifte.\n",
- "\n",
- " [..[[Bi] Ti]..[D]] -> ...\n",
- "\n",
- "\n",
- " [[[B0] T0] [[B1] T1] [D]] cond\n",
- " -----------------------------------------\n",
- " [B0] [T0] [[B1] [T1] [D] ifte] ifte\n",
- "\n",
- " '''\n",
- " conditions, stack = stack\n",
- " if conditions:\n",
- " expression = _cond(conditions, expression)\n",
- " try:\n",
- " # Attempt to preload the args to first ifte.\n",
- " (P, (T, (E, expression))) = expression\n",
- " except ValueError:\n",
- " # If, for any reason, the argument to cond should happen to contain\n",
- " # only the default clause then this optimization will fail.\n",
- " pass\n",
- " else:\n",
- " stack = (E, (T, (P, stack)))\n",
- " return stack, expression, dictionary\n",
- "\n",
- "\n",
- "def _cond(conditions, expression):\n",
- " (clause, rest) = conditions\n",
- " if not rest: # clause is [D]\n",
- " return clause\n",
- " P, T = clause\n",
- " return (P, (T, (_cond(rest, ()), (S_ifte, expression))))\n",
- "\n",
- "\n",
- "\n",
- "D['cond'] = cond"
- ]
- },
{
"cell_type": "markdown",
"metadata": {},
@@ -1860,7 +1782,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Minor rearrangement:\n",
+ "Minor rearrangement, move `dup` into `W`:\n",
"\n",
" W == dup [fourth] [fourth] while uncons uncons pop over\n",
" E′ == roll> popop rest [W] dip cons dipd swap\n",
@@ -1879,9 +1801,9 @@
"\n",
" W.rightmost == [fourth] [fourth] while\n",
" W.unpack == uncons uncons pop\n",
+ " W == dup W.rightmost W.unpack over\n",
" E.clear_stuff == roll> popop rest\n",
" E.delete == cons dipd\n",
- " W == dup W.rightmost W.unpack over\n",
" E.0 == E.clear_stuff [W] dip E.delete swap\n",
" E == [\n",
" [[pop third not] pop fourth]\n",
@@ -1899,7 +1821,7 @@
},
{
"cell_type": "code",
- "execution_count": 43,
+ "execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
@@ -1917,12 +1839,13 @@
"T< == [dipdd] cons infra\n",
"R0 == over first swap dup\n",
"R1 == cons roll> [T>] [E] [T<] cmp\n",
- "Tree-Delete == [pop not] [pop] [R0] [R1] genrec''', D)"
+ "Tree-Delete == [pop not] [pop] [R0] [R1] genrec\n",
+ "''', D)"
]
},
{
"cell_type": "code",
- "execution_count": 44,
+ "execution_count": 43,
"metadata": {},
"outputs": [
{
@@ -1939,7 +1862,7 @@
},
{
"cell_type": "code",
- "execution_count": 45,
+ "execution_count": 44,
"metadata": {},
"outputs": [
{
@@ -1956,7 +1879,7 @@
},
{
"cell_type": "code",
- "execution_count": 46,
+ "execution_count": 45,
"metadata": {},
"outputs": [
{
@@ -1973,7 +1896,7 @@
},
{
"cell_type": "code",
- "execution_count": 47,
+ "execution_count": 46,
"metadata": {},
"outputs": [
{
@@ -1990,7 +1913,7 @@
},
{
"cell_type": "code",
- "execution_count": 48,
+ "execution_count": 47,
"metadata": {},
"outputs": [
{
@@ -2007,7 +1930,7 @@
},
{
"cell_type": "code",
- "execution_count": 49,
+ "execution_count": 48,
"metadata": {},
"outputs": [
{
@@ -2024,7 +1947,7 @@
},
{
"cell_type": "code",
- "execution_count": 50,
+ "execution_count": 49,
"metadata": {
"scrolled": true
},
@@ -2099,11 +2022,6 @@
" Tree-delete == [pop not] [pop] [_Tree_delete_R0] [_Tree_delete_R1] genrec\n",
"\n"
]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": []
}
],
"metadata": {
diff --git a/docs/Ordered_Binary_Trees.md b/docs/Ordered_Binary_Trees.md
index 368c76e..adecfb7 100644
--- a/docs/Ordered_Binary_Trees.md
+++ b/docs/Ordered_Binary_Trees.md
@@ -1,5 +1,5 @@
-# Treating Trees I
+# Treating Trees I: Ordered Binary Trees
Although any expression in Joy can be considered to describe a [tree](https://en.wikipedia.org/wiki/Tree_structure) with the quotes as compound nodes and the non-quote values as leaf nodes, in this page I want to talk about [ordered binary trees](https://en.wikipedia.org/wiki/Binary_search_tree) and how to make and use them.
@@ -64,6 +64,9 @@ define('Tree-new == swap [[] []] cons cons')
J('"v" "k" Tree-new')
```
+ ['k' 'v' [] []]
+
+
(As an implementation detail, the `[[] []]` literal used in the definition of `Tree-new` will be reused to supply the *constant* tail for *all* new nodes produced by it. This is one of those cases where you get amortized storage "for free" by using [persistent datastructures](https://en.wikipedia.org/wiki/Persistent_data_structure). Because the tail, which is `((), ((), ()))` in Python, is immutable and embedded in the definition body for `Tree-new`, all new nodes can reuse it as their own tail without fear that some other code somewhere will change it.)
### Adding to a non-empty node.
@@ -302,7 +305,7 @@ J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step')
## Interlude: `cmp` combinator
-Instead of mucking about with nested `ifte` combinators let's just go whole hog and define `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:
+Instead of mucking about with nested `ifte` combinators let's use `cmp` which takes two values and three quoted programs on the stack and runs one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
@@ -317,39 +320,6 @@ Instead of mucking about with nested `ifte` combinators let's just go whole hog
L
-```python
-from joy.library import FunctionWrapper
-from joy.utils.stack import pushback
-from notebook_preamble import D
-
-
-@FunctionWrapper
-def cmp_(stack, expression, dictionary):
- '''
- cmp takes two values and three quoted programs on the stack and runs
- one of the three depending on the results of comparing the two values:
-
- a b [G] [E] [L] cmp
- ------------------------- a > b
- G
-
- a b [G] [E] [L] cmp
- ------------------------- a = b
- E
-
- a b [G] [E] [L] cmp
- ------------------------- a < b
- L
- '''
- L, (E, (G, (b, (a, stack)))) = stack
- expression = pushback(G if a > b else L if a < b else E, expression)
- return stack, expression, dictionary
-
-
-D['cmp'] = cmp_
-```
-
-
```python
J("1 0 ['G'] ['E'] ['L'] cmp")
```
@@ -681,7 +651,7 @@ J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order')
2 3 4 5 6 7 8 9
-Parameterizing the `[F]` function is left as an exercise for the reader (for now.)
+Parameterizing the `[F]` function is left as an exercise for the reader.
## Getting values by key
Let's derive a function that accepts a tree and a key and returns the value associated with that key.
@@ -937,51 +907,6 @@ We have found the node in the tree where `key` equals `node_key`. We need to re
We have to handle three cases, so let's use `cond`.
-
-```python
-from joy.library import FunctionWrapper, S_ifte
-
-
-@FunctionWrapper
-def cond(stack, expression, dictionary):
- '''
- like a case statement; works by rewriting into a chain of ifte.
-
- [..[[Bi] Ti]..[D]] -> ...
-
-
- [[[B0] T0] [[B1] T1] [D]] cond
- -----------------------------------------
- [B0] [T0] [[B1] [T1] [D] ifte] ifte
-
- '''
- conditions, stack = stack
- if conditions:
- expression = _cond(conditions, expression)
- try:
- # Attempt to preload the args to first ifte.
- (P, (T, (E, expression))) = expression
- except ValueError:
- # If, for any reason, the argument to cond should happen to contain
- # only the default clause then this optimization will fail.
- pass
- else:
- stack = (E, (T, (P, stack)))
- return stack, expression, dictionary
-
-
-def _cond(conditions, expression):
- (clause, rest) = conditions
- if not rest: # clause is [D]
- return clause
- P, T = clause
- return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
-
-
-
-D['cond'] = cond
-```
-
#### One or more child nodes are `[]`
The first two cases are symmetrical: if we only have one non-empty child node return it. If both child nodes are empty return an empty node.
@@ -1127,7 +1052,7 @@ Substituting:
[[E′] cons infra]
] cond
-Minor rearrangement:
+Minor rearrangement, move `dup` into `W`:
W == dup [fourth] [fourth] while uncons uncons pop over
E′ == roll> popop rest [W] dip cons dipd swap
@@ -1141,9 +1066,9 @@ Minor rearrangement:
W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop
+ W == dup W.rightmost W.unpack over
E.clear_stuff == roll> popop rest
E.delete == cons dipd
- W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [
[[pop third not] pop fourth]
@@ -1174,7 +1099,8 @@ T> == [dipd] cons infra
T< == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp
-Tree-Delete == [pop not] [pop] [R0] [R1] genrec''', D)
+Tree-Delete == [pop not] [pop] [R0] [R1] genrec
+''', D)
```
diff --git a/docs/Ordered_Binary_Trees.rst b/docs/Ordered_Binary_Trees.rst
index 883d431..612fd66 100644
--- a/docs/Ordered_Binary_Trees.rst
+++ b/docs/Ordered_Binary_Trees.rst
@@ -1,6 +1,6 @@
-Treating Trees I
-================
+Treating Trees I: Ordered Binary Trees
+======================================
Although any expression in Joy can be considered to describe a
`tree `__ with the quotes
@@ -96,6 +96,12 @@ Definition:
J('"v" "k" Tree-new')
+
+.. parsed-literal::
+
+ ['k' 'v' [] []]
+
+
(As an implementation detail, the ``[[] []]`` literal used in the
definition of ``Tree-new`` will be reused to supply the *constant* tail
for *all* new nodes produced by it. This is one of those cases where you
@@ -420,10 +426,10 @@ Examples
Interlude: ``cmp`` combinator
-----------------------------
-Instead of mucking about with nested ``ifte`` combinators let's just go
-whole hog and define ``cmp`` which takes two values and three quoted
-programs on the stack and runs one of the three depending on the results
-of comparing the two values:
+Instead of mucking about with nested ``ifte`` combinators let's use
+``cmp`` which takes two values and three quoted programs on the stack
+and runs one of the three depending on the results of comparing the two
+values:
::
@@ -439,38 +445,6 @@ of comparing the two values:
------------------------- a < b
L
-.. code:: ipython2
-
- from joy.library import FunctionWrapper
- from joy.utils.stack import pushback
- from notebook_preamble import D
-
-
- @FunctionWrapper
- def cmp_(stack, expression, dictionary):
- '''
- cmp takes two values and three quoted programs on the stack and runs
- one of the three depending on the results of comparing the two values:
-
- a b [G] [E] [L] cmp
- ------------------------- a > b
- G
-
- a b [G] [E] [L] cmp
- ------------------------- a = b
- E
-
- a b [G] [E] [L] cmp
- ------------------------- a < b
- L
- '''
- L, (E, (G, (b, (a, stack)))) = stack
- expression = pushback(G if a > b else L if a < b else E, expression)
- return stack, expression, dictionary
-
-
- D['cmp'] = cmp_
-
.. code:: ipython2
J("1 0 ['G'] ['E'] ['L'] cmp")
@@ -930,7 +904,7 @@ Now we can sort sequences.
Parameterizing the ``[F]`` function is left as an exercise for the
-reader (for now.)
+reader.
Getting values by key
---------------------
@@ -1291,50 +1265,6 @@ need to replace the current node with something
We have to handle three cases, so let's use ``cond``.
-.. code:: ipython2
-
- from joy.library import FunctionWrapper, S_ifte
-
-
- @FunctionWrapper
- def cond(stack, expression, dictionary):
- '''
- like a case statement; works by rewriting into a chain of ifte.
-
- [..[[Bi] Ti]..[D]] -> ...
-
-
- [[[B0] T0] [[B1] T1] [D]] cond
- -----------------------------------------
- [B0] [T0] [[B1] [T1] [D] ifte] ifte
-
- '''
- conditions, stack = stack
- if conditions:
- expression = _cond(conditions, expression)
- try:
- # Attempt to preload the args to first ifte.
- (P, (T, (E, expression))) = expression
- except ValueError:
- # If, for any reason, the argument to cond should happen to contain
- # only the default clause then this optimization will fail.
- pass
- else:
- stack = (E, (T, (P, stack)))
- return stack, expression, dictionary
-
-
- def _cond(conditions, expression):
- (clause, rest) = conditions
- if not rest: # clause is [D]
- return clause
- P, T = clause
- return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
-
-
-
- D['cond'] = cond
-
One or more child nodes are ``[]``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1534,7 +1464,7 @@ Substituting:
[[E′] cons infra]
] cond
-Minor rearrangement:
+Minor rearrangement, move ``dup`` into ``W``:
::
@@ -1553,9 +1483,9 @@ Refactoring
W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop
+ W == dup W.rightmost W.unpack over
E.clear_stuff == roll> popop rest
E.delete == cons dipd
- W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [
[[pop third not] pop fourth]
@@ -1587,7 +1517,8 @@ program.
T< == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp
- Tree-Delete == [pop not] [pop] [R0] [R1] genrec''', D)
+ Tree-Delete == [pop not] [pop] [R0] [R1] genrec
+ ''', D)
.. code:: ipython2