Switch to Joy kernel.
This commit is contained in:
parent
fcd4c613e4
commit
384d391175
|
|
@ -1,21 +1,20 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from notebook_preamble import D, DefinitionWrapper, J, V, define"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Recursion Combinators\n",
|
||||
"\n",
|
||||
"This article describes the `genrec` combinator, how to use it, and several generic specializations.\n",
|
||||
"This article describes the `genrec` combinator and how to use it, then several generic specializations.\n",
|
||||
"\n",
|
||||
"## General Recursive Function\n",
|
||||
"\n",
|
||||
"In Joy recursive functions are defined by four quoted programs and the `genrec` combinator.\n",
|
||||
"\n",
|
||||
" F == [if] [then] [rec1] [rec2] genrec\n",
|
||||
"\n",
|
||||
"This can be thought of as transforming into an \"if..then..else\" expression using the `ifte` combinator and containing a quoted copy of itself in the \"else\" branch:\n",
|
||||
"\n",
|
||||
" [if] [then] [rec1] [rec2] genrec\n",
|
||||
" ---------------------------------------------------------------------\n",
|
||||
|
|
@ -33,130 +32,123 @@
|
|||
"the combinator are again pushed onto the stack bundled up in a quoted\n",
|
||||
"form. Then the rec2-part is executed, where it will find the bundled\n",
|
||||
"form. Typically it will then execute the bundled form, either with i or\n",
|
||||
"with app2, or some other combinator.\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"with app2, or some other combinator.\"\n",
|
||||
"\n",
|
||||
"## Designing Recursive Functions\n",
|
||||
"The way to design one of these is to fix your base case and \n",
|
||||
"test and then treat `R1` and `R2` as an else-part \"sandwiching\"\n",
|
||||
"a quotation of the whole function.\n",
|
||||
"\n",
|
||||
"Fix your base case and test functions and then treat `R1` and `R2` as an else-part \"sandwiching\" a quotation of the whole function.\n",
|
||||
"\n",
|
||||
"For example, given a (general recursive) function `F`:\n",
|
||||
"\n",
|
||||
" F == [I] [T] [R1] [R2] genrec\n",
|
||||
" == [I] [T] [R1 [F] R2] ifte\n",
|
||||
" F == [P] [T] [R1] [R2] genrec\n",
|
||||
" == [P] [T] [R1 [F] R2] ifte\n",
|
||||
"\n",
|
||||
"If the `[I]` predicate is false you must derive `R1` and `R2` from:\n",
|
||||
"Derive `R1` and `R2` from:\n",
|
||||
"\n",
|
||||
" ... R1 [F] R2\n",
|
||||
"\n",
|
||||
"Set the stack arguments in front and figure out what `R1` and `R2`\n",
|
||||
"have to do to apply the quoted `[F]` in the proper way."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Primitive Recursive Functions\n",
|
||||
"Primitive recursive functions are those where `R2 == i`.\n",
|
||||
"Set the stack arguments in front and figure out what `R1` and `R2` have to do to apply the quoted `[F]` in the proper way.\n",
|
||||
"\n",
|
||||
" P == [I] [T] [R] primrec\n",
|
||||
" == [I] [T] [R [P] i] ifte\n",
|
||||
" == [I] [T] [R P] ifte"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## [Hylomorphism](https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29)\n",
|
||||
"A [hylomorphism](https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29) is a recursive function `H :: A -> C` that converts a value of type `A` into a value of type `C` by means of:\n",
|
||||
"\n",
|
||||
"- A generator `G :: A -> (B, A)`\n",
|
||||
"- A combiner `F :: (B, C) -> C`\n",
|
||||
"- A predicate `P :: A -> Bool` to detect the base case\n",
|
||||
"- A base case value `c :: C`\n",
|
||||
"A [hylomorphism](https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29) is a recursive function `H` that converts a value of type `A` into a value of type `C` by means of:\n",
|
||||
"\n",
|
||||
"- A generator `G` from `A` to `(B, A)`\n",
|
||||
"- A combiner `Q` from `(B, C)` to `C`\n",
|
||||
"- A predicate `P` from `A` to `Bool` to detect the base case\n",
|
||||
"- A base case value `c` of type `C`, and\n",
|
||||
"- Recursive calls (zero or more); it has a \"call stack in the form of a cons list\".\n",
|
||||
"\n",
|
||||
"It may be helpful to see this function implemented in imperative Python code."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hylomorphism(c, F, P, G):\n",
|
||||
" '''Return a hylomorphism function H.'''\n",
|
||||
"It may be helpful to see this function implemented in pseudocode (Python).\n",
|
||||
"\n",
|
||||
" def H(a):\n",
|
||||
" if P(a):\n",
|
||||
" result = c\n",
|
||||
" else:\n",
|
||||
" def hylomorphism(c, Q, P, G):\n",
|
||||
" '''Return a hylomorphism function H.'''\n",
|
||||
"\n",
|
||||
" def H(a):\n",
|
||||
" if P(a):\n",
|
||||
" return c\n",
|
||||
" b, aa = G(a)\n",
|
||||
" result = F(b, H(aa)) # b is stored in the stack frame during recursive call to H().\n",
|
||||
" return result\n",
|
||||
" return Q(b, H(aa))\n",
|
||||
"\n",
|
||||
" return H\n",
|
||||
"\n",
|
||||
" return H"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Cf. [\"Bananas, Lenses, & Barbed Wire\"](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125)\n",
|
||||
"\n",
|
||||
"Note that during evaluation of `H()` the intermediate `b` values are stored in the Python call stack. This is what is meant by \"call stack in the form of a cons list\"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Note that during evaluation of `H()` the intermediate `b` values are stored in the Python call stack. This is what is meant by \"call stack in the form of a cons list\".\n",
|
||||
"\n",
|
||||
"## Hylomorphism in Joy\n",
|
||||
"\n",
|
||||
" a H\n",
|
||||
" ---------\n",
|
||||
" c\n",
|
||||
"\n",
|
||||
"We can define a combinator `hylomorphism` that will make a hylomorphism combinator `H` from constituent parts.\n",
|
||||
"\n",
|
||||
" H == [P] c [G] [F] hylomorphism\n",
|
||||
" H == [P] c [G] [Q] hylomorphism\n",
|
||||
"\n",
|
||||
"The function `H` is recursive, so we start with `ifte` and set the else-part to\n",
|
||||
"some function `J` that will contain a quoted copy of `H`. (The then-part just\n",
|
||||
"discards the leftover `a` and replaces it with the base case value `c`.)\n",
|
||||
"some function `J` that will contain a quoted copy of `H`.\n",
|
||||
"The then-part just discards the leftover `a` and replaces it with the base case value `c`:\n",
|
||||
"\n",
|
||||
" H == [P] [pop c] [J] ifte\n",
|
||||
"\n",
|
||||
"The else-part `J` gets just the argument `a` on the stack.\n",
|
||||
"\n",
|
||||
" a J\n",
|
||||
" a G The first thing to do is use the generator G\n",
|
||||
" aa b which produces b and a new aa\n",
|
||||
" aa b [H] dip we recur with H on the new aa\n",
|
||||
" aa H b F and run F on the result.\n",
|
||||
"\n",
|
||||
"This gives us a definition for `J`.\n",
|
||||
"The first thing to do is use the generator `G` which produces values `b` and a new `aa`:\n",
|
||||
"\n",
|
||||
" J == G [H] dip F\n",
|
||||
" a G\n",
|
||||
" ----------\n",
|
||||
" aa b\n",
|
||||
"\n",
|
||||
"Plug it in and convert to genrec.\n",
|
||||
"So:\n",
|
||||
"\n",
|
||||
" H == [P] [pop c] [G [H] dip F] ifte\n",
|
||||
" H == [P] [pop c] [G] [dip F] genrec\n",
|
||||
" J == G J′\n",
|
||||
"\n",
|
||||
"Then we recur with `H` on `aa`:\n",
|
||||
"\n",
|
||||
" aa b [H] dip\n",
|
||||
" ------------------\n",
|
||||
" aa H b\n",
|
||||
" ------------------\n",
|
||||
" cc b\n",
|
||||
"\n",
|
||||
"So:\n",
|
||||
"\n",
|
||||
" J′ == [H] dip J″\n",
|
||||
"\n",
|
||||
"And run `Q` on the result:\n",
|
||||
"\n",
|
||||
" cc b Q\n",
|
||||
" ------------\n",
|
||||
" c\n",
|
||||
"So:\n",
|
||||
"\n",
|
||||
" J″ == Q\n",
|
||||
"\n",
|
||||
"Summing up:\n",
|
||||
"\n",
|
||||
" J == G J′\n",
|
||||
" J′ == [H] dip J″\n",
|
||||
" J″ == Q\n",
|
||||
"\n",
|
||||
"This gives us a definition for `J`:\n",
|
||||
"\n",
|
||||
" J == G [H] dip Q\n",
|
||||
"\n",
|
||||
"Plug it in and convert to genrec:\n",
|
||||
"\n",
|
||||
" H == [P] [pop c] [ J ] ifte\n",
|
||||
" [P] [pop c] [G [H] dip Q] ifte\n",
|
||||
" [P] [pop c] [G] [dip Q] genrec\n",
|
||||
"\n",
|
||||
"This is the form of a hylomorphism in Joy, which nicely illustrates that\n",
|
||||
"it is a simple specialization of the general recursion combinator.\n",
|
||||
"\n",
|
||||
" H == [P] c [G] [F] hylomorphism == [P] [pop c] [G] [dip F] genrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
" [P] c [G] [Q] hylomorphism\n",
|
||||
" [P] [pop c] [G] [dip Q] genrec\n",
|
||||
"\n",
|
||||
"## Derivation of `hylomorphism` combinator\n",
|
||||
"\n",
|
||||
"Now we just need to derive a definition that builds the `genrec` arguments\n",
|
||||
|
|
@ -172,8 +164,6 @@
|
|||
"- Use `unit` to dequote `c`.\n",
|
||||
"- Use `dipd` to untangle `[unit [pop] swoncat]` from the givens.\n",
|
||||
"\n",
|
||||
"So:\n",
|
||||
"\n",
|
||||
" H == [P] [pop c] [G] [dip F] genrec\n",
|
||||
" [P] [c] [pop] swoncat [G] [F] [dip] swoncat genrec\n",
|
||||
" [P] c unit [pop] swoncat [G] [F] [dip] swoncat genrec\n",
|
||||
|
|
@ -187,11 +177,17 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')"
|
||||
"[hylomorphism [unit [pop] swoncat] dipd [dip] swoncat genrec] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -211,11 +207,17 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')"
|
||||
"[triangular_number [1 <=] 0 [-- dup] [+] hylomorphism] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -227,36 +229,45 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"10\n"
|
||||
"10"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 triangular_number')"
|
||||
"5 triangular_number"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[0 0 1 3 6 10 15]\n"
|
||||
"[0 0 1 3 6 10 15 21]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[0 1 2 3 4 5 6] [triangular_number] map')"
|
||||
"clear\n",
|
||||
"\n",
|
||||
"[0 1 2 3 4 5 6 7] [triangular_number] map"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Neat!"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -407,6 +418,7 @@
|
|||
"metadata": {},
|
||||
"source": [
|
||||
"### `range` et. al.\n",
|
||||
"\n",
|
||||
"An example of an anamorphism is the `range` function which generates the list of integers from 0 to *n* - 1 given *n*.\n",
|
||||
"\n",
|
||||
"Each of the above variations can be used to make four slightly different `range` functions."
|
||||
|
|
@ -423,16 +435,37 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('range == [0 <=] [] [-- dup] [swons] hylomorphism')"
|
||||
"clear "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"[range [0 <=] [] [-- dup] [swons] hylomorphism] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
|
|
@ -441,12 +474,12 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[4 3 2 1 0]\n"
|
||||
"[4 3 2 1 0]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 range')"
|
||||
"5 range"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -454,17 +487,38 @@
|
|||
"metadata": {},
|
||||
"source": [
|
||||
"#### `range` with `H2`\n",
|
||||
" H2 == c swap [P] [pop] [G [F] dip] primrec\n",
|
||||
" == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec"
|
||||
" H2 == c swap [P] [pop] [G [F] dip] tailrec\n",
|
||||
" == [] swap [0 <=] [pop] [-- dup [swons] dip] tailrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"clear "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')"
|
||||
"[range_reverse [] swap [0 <=] [pop] [-- dup [swons] dip] tailrec] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -478,12 +532,12 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[0 1 2 3 4]\n"
|
||||
"[0 1 2 3 4]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 range_reverse')"
|
||||
"5 range_reverse"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -499,14 +553,35 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')"
|
||||
"clear "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"[ranger [0 <=] [pop []] [[--] dupdip] [dip swons] genrec] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
|
|
@ -515,12 +590,12 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[5 4 3 2 1]\n"
|
||||
"[5 4 3 2 1]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 ranger')"
|
||||
"5 ranger"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -534,16 +609,37 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')"
|
||||
"clear "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"[ranger_reverse [] swap [0 <=] [pop] [[swons] dupdip --] tailrec] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
|
|
@ -552,19 +648,12 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[1 2 3 4 5]\n"
|
||||
"[1 2 3 4 5]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 ranger_reverse')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Hopefully this illustrates the workings of the variations. For more insight you can run the cells using the `V()` function instead of the `J()` function to get a trace of the Joy evaluation."
|
||||
"5 ranger_reverse"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -572,54 +661,77 @@
|
|||
"metadata": {},
|
||||
"source": [
|
||||
"## Catamorphism\n",
|
||||
"A catamorphism can be defined as a hylomorphism that uses `[uncons swap]` for `[G]`\n",
|
||||
"and `[[] =]` (or just `[not]`) for the predicate `[P]`. A catamorphic function tears down a list term-by-term and makes some new value.\n",
|
||||
"A catamorphic function tears down a list term-by-term and makes some new value.\n",
|
||||
"It can be defined as a hylomorphism that uses `[uncons swap]` for `[G]`\n",
|
||||
"and `[[] =]` (or just `[not]`) for the predicate `[P]`.\n",
|
||||
"\n",
|
||||
" C == [not] c [uncons swap] [F] hylomorphism\n",
|
||||
"\n",
|
||||
" C == [not] c [uncons swap] [F] hylomorphism"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('swuncons == uncons swap') # Awkward name."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"An example of a catamorphism is the sum function.\n",
|
||||
"\n",
|
||||
" sum == [not] 0 [swuncons] [+] hylomorphism"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"define('sum == [not] 0 [swuncons] [+] hylomorphism')"
|
||||
" sum == [not] 0 [uncons swap] [+] hylomorphism"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"clear "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"[sum [not] 0 [uncons swap] [+] hylomorphism] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"15\n"
|
||||
"15"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[5 4 3 2 1] sum')"
|
||||
"[5 4 3 2 1] sum"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"clear "
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -632,64 +744,76 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"==== Help on step ====\n",
|
||||
"\n",
|
||||
"Run a quoted program on each item in a sequence.\n",
|
||||
"::\n",
|
||||
"\n",
|
||||
" ... [] [Q] . step\n",
|
||||
" -----------------------\n",
|
||||
" ... .\n",
|
||||
" ... [] [Q] . step\n",
|
||||
" -----------------------\n",
|
||||
" ... .\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" ... [a] [Q] . step\n",
|
||||
" ------------------------\n",
|
||||
" ... a . Q\n",
|
||||
" ... a . Q\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" ... [a b c] [Q] . step\n",
|
||||
" ----------------------------------------\n",
|
||||
" ... a . Q [b c] [Q] step\n",
|
||||
" ... [a b c] [Q] . step\n",
|
||||
" ----------------------------------------\n",
|
||||
" ... a . Q [b c] [Q] step\n",
|
||||
"\n",
|
||||
"The step combinator executes the quotation on each member of the list\n",
|
||||
"on top of the stack.\n",
|
||||
"\n",
|
||||
"---- end (step)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[step] help')"
|
||||
"[step] help"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('sum == 0 swap [+] step')"
|
||||
"[sum 0 swap [+] step] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"15\n"
|
||||
"15"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[5 4 3 2 1] sum')"
|
||||
"[5 4 3 2 1] sum"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -712,16 +836,37 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')"
|
||||
"clear"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"[factorial 1 swap [1 <=] [pop] [[*] dupdip --] tailrec] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
|
|
@ -730,12 +875,12 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"120\n"
|
||||
"120"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('5 factorial')"
|
||||
"5 factorial"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -748,54 +893,65 @@
|
|||
" [1 2 3] tails\n",
|
||||
" --------------------\n",
|
||||
" [[] [3] [2 3]]\n",
|
||||
" "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We can build as we go, and we want `F` to run after `G`, so we use pattern `H2`:\n",
|
||||
" \n",
|
||||
"\n",
|
||||
"We can build as we go, and we want `Q` to run after `G`, so we use pattern `H2`:\n",
|
||||
"\n",
|
||||
" H2 == c swap [P] [pop] [G [Q] dip] tailrec\n",
|
||||
"\n",
|
||||
" H2 == c swap [P] [pop] [G [F] dip] primrec"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We would use:\n",
|
||||
"\n",
|
||||
" c == []\n",
|
||||
" F == swons\n",
|
||||
" Q == swons\n",
|
||||
" G == rest dup\n",
|
||||
" P == not"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')"
|
||||
"clear"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": []
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"[tails [] swap [not] [pop] [rest dup [swons] dip] tailrec] inscribe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[] [3] [2 3]]\n"
|
||||
"[[] [3] [2 3]]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"J('[1 2 3] tails')"
|
||||
"[1 2 3] tails"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -837,21 +993,14 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"display_name": "Joypy",
|
||||
"language": "",
|
||||
"name": "thun"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.15"
|
||||
"file_extension": ".joy",
|
||||
"mimetype": "text/plain",
|
||||
"name": "Joy"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
Loading…
Reference in New Issue