Convert syntax highlighter spec.
This commit is contained in:
parent
31c26cd235
commit
3f40e30c6f
|
|
@ -76,7 +76,7 @@ E.g.:
|
||||||
Implementation
|
Implementation
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from functools import partial as curry
|
from functools import partial as curry
|
||||||
from itertools import product
|
from itertools import product
|
||||||
|
|
@ -86,7 +86,7 @@ Implementation
|
||||||
|
|
||||||
The empty set and the set of just the empty string.
|
The empty set and the set of just the empty string.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
phi = frozenset() # ϕ
|
phi = frozenset() # ϕ
|
||||||
y = frozenset({''}) # λ
|
y = frozenset({''}) # λ
|
||||||
|
|
@ -101,7 +101,7 @@ alphabet with two symbols (if you had to.)
|
||||||
I chose the names ``O`` and ``l`` (uppercase “o” and lowercase “L”) to
|
I chose the names ``O`` and ``l`` (uppercase “o” and lowercase “L”) to
|
||||||
look like ``0`` and ``1`` (zero and one) respectively.
|
look like ``0`` and ``1`` (zero and one) respectively.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
syms = O, l = frozenset({'0'}), frozenset({'1'})
|
syms = O, l = frozenset({'0'}), frozenset({'1'})
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ expression* is one of:
|
||||||
|
|
||||||
Where ``R`` and ``S`` stand for *regular expressions*.
|
Where ``R`` and ``S`` stand for *regular expressions*.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split() # Tags are just strings.
|
AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split() # Tags are just strings.
|
||||||
|
|
||||||
|
|
@ -133,7 +133,7 @@ only, these datastructures are immutable.
|
||||||
String Representation of RE Datastructures
|
String Representation of RE Datastructures
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def stringy(re):
|
def stringy(re):
|
||||||
'''
|
'''
|
||||||
|
|
@ -175,11 +175,11 @@ Match anything. Often spelled “.”
|
||||||
|
|
||||||
I = (0|1)*
|
I = (0|1)*
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
I = (KSTAR, (OR, O, l))
|
I = (KSTAR, (OR, O, l))
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print stringy(I)
|
print stringy(I)
|
||||||
|
|
||||||
|
|
@ -201,14 +201,14 @@ The example expression from Brzozowski:
|
||||||
|
|
||||||
Note that it contains one of everything.
|
Note that it contains one of everything.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I))))
|
a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I))))
|
||||||
b = (CONS, I, (CONS, O, l))
|
b = (CONS, I, (CONS, O, l))
|
||||||
c = (CONS, l, (KSTAR, l))
|
c = (CONS, l, (KSTAR, l))
|
||||||
it = (AND, a, (NOT, (OR, b, c)))
|
it = (AND, a, (NOT, (OR, b, c)))
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print stringy(it)
|
print stringy(it)
|
||||||
|
|
||||||
|
|
@ -223,7 +223,7 @@ Note that it contains one of everything.
|
||||||
|
|
||||||
Let’s get that auxiliary predicate function ``δ`` out of the way.
|
Let’s get that auxiliary predicate function ``δ`` out of the way.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def nully(R):
|
def nully(R):
|
||||||
'''
|
'''
|
||||||
|
|
@ -263,7 +263,7 @@ This is the straightforward version with no “compaction”. It works fine,
|
||||||
but does waaaay too much work because the expressions grow each
|
but does waaaay too much work because the expressions grow each
|
||||||
derivation.
|
derivation.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def D(symbol):
|
def D(symbol):
|
||||||
|
|
||||||
|
|
@ -308,7 +308,7 @@ derivation.
|
||||||
Compaction Rules
|
Compaction Rules
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def _compaction_rule(relation, one, zero, a, b):
|
def _compaction_rule(relation, one, zero, a, b):
|
||||||
return (
|
return (
|
||||||
|
|
@ -320,7 +320,7 @@ Compaction Rules
|
||||||
|
|
||||||
An elegant symmetry.
|
An elegant symmetry.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
# R ∧ I = I ∧ R = R
|
# R ∧ I = I ∧ R = R
|
||||||
# R ∧ ϕ = ϕ ∧ R = ϕ
|
# R ∧ ϕ = ϕ ∧ R = ϕ
|
||||||
|
|
@ -341,7 +341,7 @@ We can save re-processing by remembering results we have already
|
||||||
computed. RE datastructures are immutable and the ``derv()`` functions
|
computed. RE datastructures are immutable and the ``derv()`` functions
|
||||||
are *pure* so this is fine.
|
are *pure* so this is fine.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
class Memo(object):
|
class Memo(object):
|
||||||
|
|
||||||
|
|
@ -365,7 +365,7 @@ With “Compaction”
|
||||||
This version uses the rules above to perform compaction. It keeps the
|
This version uses the rules above to perform compaction. It keeps the
|
||||||
expressions from growing too large.
|
expressions from growing too large.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def D_compaction(symbol):
|
def D_compaction(symbol):
|
||||||
|
|
||||||
|
|
@ -414,7 +414,7 @@ Let’s try it out…
|
||||||
|
|
||||||
(FIXME: redo.)
|
(FIXME: redo.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
o, z = D_compaction('0'), D_compaction('1')
|
o, z = D_compaction('0'), D_compaction('1')
|
||||||
REs = set()
|
REs = set()
|
||||||
|
|
@ -605,20 +605,20 @@ You can see the one-way nature of the ``g`` state and the ``hij`` “trap”
|
||||||
in the way that the ``.111.`` on the left-hand side of the ``&``
|
in the way that the ``.111.`` on the left-hand side of the ``&``
|
||||||
disappears once it has been matched.
|
disappears once it has been matched.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from string import ascii_lowercase
|
from string import ascii_lowercase
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
d0, d1 = D_compaction('0'), D_compaction('1')
|
d0, d1 = D_compaction('0'), D_compaction('1')
|
||||||
|
|
||||||
``explore()``
|
``explore()``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def explore(re):
|
def explore(re):
|
||||||
|
|
||||||
|
|
@ -645,7 +645,7 @@ disappears once it has been matched.
|
||||||
|
|
||||||
return table, accepting
|
return table, accepting
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
table, accepting = explore(it)
|
table, accepting = explore(it)
|
||||||
table
|
table
|
||||||
|
|
@ -678,7 +678,7 @@ disappears once it has been matched.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
accepting
|
accepting
|
||||||
|
|
||||||
|
|
@ -697,7 +697,7 @@ Generate Diagram
|
||||||
Once we have the FSM table and the set of accepting states we can
|
Once we have the FSM table and the set of accepting states we can
|
||||||
generate the diagram above.
|
generate the diagram above.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
_template = '''\
|
_template = '''\
|
||||||
digraph finite_state_machine {
|
digraph finite_state_machine {
|
||||||
|
|
@ -722,7 +722,7 @@ generate the diagram above.
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print make_graph(table, accepting)
|
print make_graph(table, accepting)
|
||||||
|
|
||||||
|
|
@ -776,7 +776,7 @@ Trampoline Function
|
||||||
Python has no GOTO statement but we can fake it with a “trampoline”
|
Python has no GOTO statement but we can fake it with a “trampoline”
|
||||||
function.
|
function.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def trampoline(input_, jump_from, accepting):
|
def trampoline(input_, jump_from, accepting):
|
||||||
I = iter(input_)
|
I = iter(input_)
|
||||||
|
|
@ -793,7 +793,7 @@ Stream Functions
|
||||||
Little helpers to process the iterator of our data (a “stream” of “1”
|
Little helpers to process the iterator of our data (a “stream” of “1”
|
||||||
and “0” characters, not bits.)
|
and “0” characters, not bits.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
getch = lambda I: int(next(I))
|
getch = lambda I: int(next(I))
|
||||||
|
|
||||||
|
|
@ -816,7 +816,7 @@ code. (You have to imagine that these are GOTO statements in C or
|
||||||
branches in assembly and that the state names are branch destination
|
branches in assembly and that the state names are branch destination
|
||||||
labels.)
|
labels.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
a = lambda I: c if getch(I) else b
|
a = lambda I: c if getch(I) else b
|
||||||
b = lambda I: _0(I) or d
|
b = lambda I: _0(I) or d
|
||||||
|
|
@ -833,12 +833,12 @@ Note that the implementations of ``h`` and ``g`` are identical ergo
|
||||||
``h = g`` and we could eliminate one in the code but ``h`` is an
|
``h = g`` and we could eliminate one in the code but ``h`` is an
|
||||||
accepting state and ``g`` isn’t.
|
accepting state and ``g`` isn’t.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def acceptable(input_):
|
def acceptable(input_):
|
||||||
return trampoline(input_, a, {h, i})
|
return trampoline(input_, a, {h, i})
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for n in range(2**5):
|
for n in range(2**5):
|
||||||
s = bin(n)[2:]
|
s = bin(n)[2:]
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ As an example of developing a program in Joy let's take the first problem from t
|
||||||
|
|
||||||
Find the sum of all the multiples of 3 or 5 below 1000.
|
Find the sum of all the multiples of 3 or 5 below 1000.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import J, V, define
|
from notebook_preamble import J, V, define
|
||||||
|
|
||||||
|
|
@ -22,11 +22,11 @@ Sum a range filtered by a predicate
|
||||||
Let's create a predicate that returns ``True`` if a number is a multiple
|
Let's create a predicate that returns ``True`` if a number is a multiple
|
||||||
of 3 or 5 and ``False`` otherwise.
|
of 3 or 5 and ``False`` otherwise.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('P == [3 % not] dupdip 5 % not or')
|
define('P == [3 % not] dupdip 5 % not or')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('80 P')
|
V('80 P')
|
||||||
|
|
||||||
|
|
@ -108,11 +108,11 @@ the counter to the running sum. This function will do that:
|
||||||
|
|
||||||
PE1.1 == + [+] dupdip
|
PE1.1 == + [+] dupdip
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1.1 == + [+] dupdip')
|
define('PE1.1 == + [+] dupdip')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('0 0 3 PE1.1')
|
V('0 0 3 PE1.1')
|
||||||
|
|
||||||
|
|
@ -131,7 +131,7 @@ the counter to the running sum. This function will do that:
|
||||||
3 3 .
|
3 3 .
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('0 0 [3 2 1 3 1 2 3] [PE1.1] step')
|
V('0 0 [3 2 1 3 1 2 3] [PE1.1] step')
|
||||||
|
|
||||||
|
|
@ -219,7 +219,7 @@ total to 60.
|
||||||
How many multiples to sum?
|
How many multiples to sum?
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
1000 / 15
|
1000 / 15
|
||||||
|
|
||||||
|
|
@ -232,7 +232,7 @@ How many multiples to sum?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
66 * 15
|
66 * 15
|
||||||
|
|
||||||
|
|
@ -245,7 +245,7 @@ How many multiples to sum?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
1000 - 990
|
1000 - 990
|
||||||
|
|
||||||
|
|
@ -260,7 +260,7 @@ How many multiples to sum?
|
||||||
|
|
||||||
We only want the terms *less than* 1000.
|
We only want the terms *less than* 1000.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
999 - 990
|
999 - 990
|
||||||
|
|
||||||
|
|
@ -276,11 +276,11 @@ We only want the terms *less than* 1000.
|
||||||
That means we want to run the full list of numbers sixty-six times to
|
That means we want to run the full list of numbers sixty-six times to
|
||||||
get to 990 and then the first four numbers 3 2 1 3 to get to 999.
|
get to 990 and then the first four numbers 3 2 1 3 to get to 999.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1 == 0 0 66 [[3 2 1 3 1 2 3] [PE1.1] step] times [3 2 1 3] [PE1.1] step pop')
|
define('PE1 == 0 0 66 [[3 2 1 3 1 2 3] [PE1.1] step] times [3 2 1 3] [PE1.1] step pop')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('PE1')
|
J('PE1')
|
||||||
|
|
||||||
|
|
@ -305,7 +305,7 @@ integer terms from the list.
|
||||||
3 2 1 3 1 2 3
|
3 2 1 3 1 2 3
|
||||||
0b 11 10 01 11 01 10 11 == 14811
|
0b 11 10 01 11 01 10 11 == 14811
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
0b11100111011011
|
0b11100111011011
|
||||||
|
|
||||||
|
|
@ -318,11 +318,11 @@ integer terms from the list.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1.2 == [3 & PE1.1] dupdip 2 >>')
|
define('PE1.2 == [3 & PE1.1] dupdip 2 >>')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('0 0 14811 PE1.2')
|
V('0 0 14811 PE1.2')
|
||||||
|
|
||||||
|
|
@ -349,7 +349,7 @@ integer terms from the list.
|
||||||
3 3 3702 .
|
3 3 3702 .
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('3 3 3702 PE1.2')
|
V('3 3 3702 PE1.2')
|
||||||
|
|
||||||
|
|
@ -376,7 +376,7 @@ integer terms from the list.
|
||||||
8 5 925 .
|
8 5 925 .
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('0 0 14811 7 [PE1.2] times pop')
|
V('0 0 14811 7 [PE1.2] times pop')
|
||||||
|
|
||||||
|
|
@ -518,11 +518,11 @@ integer terms from the list.
|
||||||
|
|
||||||
And so we have at last:
|
And so we have at last:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1 == 0 0 66 [14811 7 [PE1.2] times pop] times 14811 4 [PE1.2] times popop')
|
define('PE1 == 0 0 66 [14811 7 [PE1.2] times pop] times 14811 4 [PE1.2] times popop')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('PE1')
|
J('PE1')
|
||||||
|
|
||||||
|
|
@ -542,17 +542,17 @@ Let's refactor
|
||||||
14811 n [PE1.2] times pop
|
14811 n [PE1.2] times pop
|
||||||
n 14811 swap [PE1.2] times pop
|
n 14811 swap [PE1.2] times pop
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1.3 == 14811 swap [PE1.2] times pop')
|
define('PE1.3 == 14811 swap [PE1.2] times pop')
|
||||||
|
|
||||||
Now we can simplify the definition above:
|
Now we can simplify the definition above:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1 == 0 0 66 [7 PE1.3] times 4 PE1.3 pop')
|
define('PE1 == 0 0 66 [7 PE1.3] times 4 PE1.3 pop')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('PE1')
|
J('PE1')
|
||||||
|
|
||||||
|
|
@ -581,11 +581,11 @@ then four more. In the *Generator Programs* notebook we derive a
|
||||||
generator that can be repeatedly driven by the ``x`` combinator to
|
generator that can be repeatedly driven by the ``x`` combinator to
|
||||||
produce a stream of the seven numbers repeating over and over again.
|
produce a stream of the seven numbers repeating over and over again.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1.terms == [0 swap [dup [pop 14811] [] branch [3 &] dupdip 2 >>] dip rest cons]')
|
define('PE1.terms == [0 swap [dup [pop 14811] [] branch [3 &] dupdip 2 >>] dip rest cons]')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('PE1.terms 21 [x] times')
|
J('PE1.terms 21 [x] times')
|
||||||
|
|
||||||
|
|
@ -598,7 +598,7 @@ produce a stream of the seven numbers repeating over and over again.
|
||||||
We know from above that we need sixty-six times seven then four more
|
We know from above that we need sixty-six times seven then four more
|
||||||
terms to reach up to but not over one thousand.
|
terms to reach up to but not over one thousand.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('7 66 * 4 +')
|
J('7 66 * 4 +')
|
||||||
|
|
||||||
|
|
@ -611,7 +611,7 @@ terms to reach up to but not over one thousand.
|
||||||
Here they are...
|
Here they are...
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('PE1.terms 466 [x] times pop')
|
J('PE1.terms 466 [x] times pop')
|
||||||
|
|
||||||
|
|
@ -624,7 +624,7 @@ Here they are...
|
||||||
...and they do sum to 999.
|
...and they do sum to 999.
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[PE1.terms 466 [x] times pop] run sum')
|
J('[PE1.terms 466 [x] times pop] run sum')
|
||||||
|
|
||||||
|
|
@ -638,7 +638,7 @@ Now we can use ``PE1.1`` to accumulate the terms as we go, and then
|
||||||
``pop`` the generator and the counter from the stack when we're done,
|
``pop`` the generator and the counter from the stack when we're done,
|
||||||
leaving just the sum.
|
leaving just the sum.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('0 0 PE1.terms 466 [x [PE1.1] dip] times popop')
|
J('0 0 PE1.terms 466 [x [PE1.1] dip] times popop')
|
||||||
|
|
||||||
|
|
@ -654,7 +654,7 @@ A little further analysis renders iteration unnecessary.
|
||||||
Consider finding the sum of the positive integers less than or equal to
|
Consider finding the sum of the positive integers less than or equal to
|
||||||
ten.
|
ten.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[10 9 8 7 6 5 4 3 2 1] sum')
|
J('[10 9 8 7 6 5 4 3 2 1] sum')
|
||||||
|
|
||||||
|
|
@ -686,11 +686,11 @@ positive integers is:
|
||||||
(The formula also works for odd values of N, I'll leave that to you if
|
(The formula also works for odd values of N, I'll leave that to you if
|
||||||
you want to work it out or you can take my word for it.)
|
you want to work it out or you can take my word for it.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('F == dup ++ * 2 floordiv')
|
define('F == dup ++ * 2 floordiv')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('10 F')
|
V('10 F')
|
||||||
|
|
||||||
|
|
@ -727,7 +727,7 @@ And ending with:
|
||||||
|
|
||||||
If we reverse one of these two blocks and sum pairs...
|
If we reverse one of these two blocks and sum pairs...
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip')
|
J('[3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip')
|
||||||
|
|
||||||
|
|
@ -737,7 +737,7 @@ If we reverse one of these two blocks and sum pairs...
|
||||||
[[978 15] [980 12] [981 10] [984 9] [985 6] [987 5] [990 3]]
|
[[978 15] [980 12] [981 10] [984 9] [985 6] [987 5] [990 3]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip [sum] map')
|
J('[3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip [sum] map')
|
||||||
|
|
||||||
|
|
@ -750,7 +750,7 @@ If we reverse one of these two blocks and sum pairs...
|
||||||
(Interesting that the sequence of seven numbers appears again in the
|
(Interesting that the sequence of seven numbers appears again in the
|
||||||
rightmost digit of each term.)
|
rightmost digit of each term.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[ 3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip [sum] map sum')
|
J('[ 3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip [sum] map sum')
|
||||||
|
|
||||||
|
|
@ -771,7 +771,7 @@ additional unpaired terms between 990 and 1000:
|
||||||
So we can give the "sum of all the multiples of 3 or 5 below 1000" like
|
So we can give the "sum of all the multiples of 3 or 5 below 1000" like
|
||||||
so:
|
so:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('6945 33 * [993 995 996 999] cons sum')
|
J('6945 33 * [993 995 996 999] cons sum')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ Using ``x`` to Generate Values
|
||||||
|
|
||||||
Cf. jp-reprod.html
|
Cf. jp-reprod.html
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import J, V, define
|
from notebook_preamble import J, V, define
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ We can make a generator for the Natural numbers (0, 1, 2, …) by using
|
||||||
|
|
||||||
Let’s try it:
|
Let’s try it:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[0 swap [dup ++] dip rest cons] x')
|
V('[0 swap [dup ++] dip rest cons] x')
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ Let’s try it:
|
||||||
After one application of ``x`` the quoted program contains ``1`` and
|
After one application of ``x`` the quoted program contains ``1`` and
|
||||||
``0`` is below it on the stack.
|
``0`` is below it on the stack.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[0 swap [dup ++] dip rest cons] x x x x x pop')
|
J('[0 swap [dup ++] dip rest cons] x x x x x pop')
|
||||||
|
|
||||||
|
|
@ -94,11 +94,11 @@ After one application of ``x`` the quoted program contains ``1`` and
|
||||||
``direco``
|
``direco``
|
||||||
----------
|
----------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('direco == dip rest cons')
|
define('direco == dip rest cons')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[0 swap [dup ++] direco] x')
|
V('[0 swap [dup ++] direco] x')
|
||||||
|
|
||||||
|
|
@ -149,13 +149,13 @@ Reading from the bottom up:
|
||||||
G == [direco] cons [swap] swap concat cons
|
G == [direco] cons [swap] swap concat cons
|
||||||
G == [direco] cons [swap] swoncat cons
|
G == [direco] cons [swap] swoncat cons
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('G == [direco] cons [swap] swoncat cons')
|
define('G == [direco] cons [swap] swoncat cons')
|
||||||
|
|
||||||
Let’s try it out:
|
Let’s try it out:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('0 [dup ++] G')
|
J('0 [dup ++] G')
|
||||||
|
|
||||||
|
|
@ -165,7 +165,7 @@ Let’s try it out:
|
||||||
[0 swap [dup ++] direco]
|
[0 swap [dup ++] direco]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('0 [dup ++] G x x x pop')
|
J('0 [dup ++] G x x x pop')
|
||||||
|
|
||||||
|
|
@ -178,7 +178,7 @@ Let’s try it out:
|
||||||
Powers of 2
|
Powers of 2
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('1 [dup 1 <<] G x x x x x x x x x pop')
|
J('1 [dup 1 <<] G x x x x x x x x x pop')
|
||||||
|
|
||||||
|
|
@ -194,7 +194,7 @@ Powers of 2
|
||||||
If we have one of these quoted programs we can drive it using ``times``
|
If we have one of these quoted programs we can drive it using ``times``
|
||||||
with the ``x`` combinator.
|
with the ``x`` combinator.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('23 [dup ++] G 5 [x] times')
|
J('23 [dup ++] G 5 [x] times')
|
||||||
|
|
||||||
|
|
@ -226,11 +226,11 @@ int:
|
||||||
And pick them off by masking with 3 (binary 11) and then shifting the
|
And pick them off by masking with 3 (binary 11) and then shifting the
|
||||||
int right two bits.
|
int right two bits.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1.1 == dup [3 &] dip 2 >>')
|
define('PE1.1 == dup [3 &] dip 2 >>')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('14811 PE1.1')
|
V('14811 PE1.1')
|
||||||
|
|
||||||
|
|
@ -252,7 +252,7 @@ int right two bits.
|
||||||
|
|
||||||
If we plug ``14811`` and ``[PE1.1]`` into our generator form…
|
If we plug ``14811`` and ``[PE1.1]`` into our generator form…
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('14811 [PE1.1] G')
|
J('14811 [PE1.1] G')
|
||||||
|
|
||||||
|
|
@ -264,7 +264,7 @@ If we plug ``14811`` and ``[PE1.1]`` into our generator form…
|
||||||
|
|
||||||
…we get a generator that works for seven cycles before it reaches zero:
|
…we get a generator that works for seven cycles before it reaches zero:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[14811 swap [PE1.1] direco] 7 [x] times')
|
J('[14811 swap [PE1.1] direco] 7 [x] times')
|
||||||
|
|
||||||
|
|
@ -280,11 +280,11 @@ Reset at Zero
|
||||||
We need a function that checks if the int has reached zero and resets it
|
We need a function that checks if the int has reached zero and resets it
|
||||||
if so.
|
if so.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1.1.check == dup [pop 14811] [] branch')
|
define('PE1.1.check == dup [pop 14811] [] branch')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('14811 [PE1.1.check PE1.1] G')
|
J('14811 [PE1.1.check PE1.1] G')
|
||||||
|
|
||||||
|
|
@ -294,7 +294,7 @@ if so.
|
||||||
[14811 swap [PE1.1.check PE1.1] direco]
|
[14811 swap [PE1.1.check PE1.1] direco]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
|
J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
|
||||||
|
|
||||||
|
|
@ -316,7 +316,7 @@ In the PE1 problem we are asked to sum all the multiples of three and
|
||||||
five less than 1000. It’s worked out that we need to use all seven
|
five less than 1000. It’s worked out that we need to use all seven
|
||||||
numbers sixty-six times and then four more.
|
numbers sixty-six times and then four more.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('7 66 * 4 +')
|
J('7 66 * 4 +')
|
||||||
|
|
||||||
|
|
@ -328,7 +328,7 @@ numbers sixty-six times and then four more.
|
||||||
|
|
||||||
If we drive our generator 466 times and sum the stack we get 999.
|
If we drive our generator 466 times and sum the stack we get 999.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')
|
J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')
|
||||||
|
|
||||||
|
|
@ -338,7 +338,7 @@ If we drive our generator 466 times and sum the stack we get 999.
|
||||||
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco]
|
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')
|
J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')
|
||||||
|
|
||||||
|
|
@ -351,13 +351,13 @@ If we drive our generator 466 times and sum the stack we get 999.
|
||||||
Project Euler Problem One
|
Project Euler Problem One
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE1.2 == + dup [+] dip')
|
define('PE1.2 == + dup [+] dip')
|
||||||
|
|
||||||
Now we can add ``PE1.2`` to the quoted program given to ``G``.
|
Now we can add ``PE1.2`` to the quoted program given to ``G``.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop')
|
J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop')
|
||||||
|
|
||||||
|
|
@ -445,15 +445,15 @@ Putting it all together:
|
||||||
F == + [popdd over] cons infra uncons
|
F == + [popdd over] cons infra uncons
|
||||||
fib_gen == [1 1 F]
|
fib_gen == [1 1 F]
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('fib == + [popdd over] cons infra uncons')
|
define('fib == + [popdd over] cons infra uncons')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('fib_gen == [1 1 fib]')
|
define('fib_gen == [1 1 fib]')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('fib_gen 10 [x] times')
|
J('fib_gen 10 [x] times')
|
||||||
|
|
||||||
|
|
@ -473,14 +473,14 @@ Now that we have a generator for the Fibonacci sequence, we need a
|
||||||
function that adds a term in the sequence to a sum if it is even, and
|
function that adds a term in the sequence to a sum if it is even, and
|
||||||
``pop``\ s it otherwise.
|
``pop``\ s it otherwise.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE2.1 == dup 2 % [+] [pop] branch')
|
define('PE2.1 == dup 2 % [+] [pop] branch')
|
||||||
|
|
||||||
And a predicate function that detects when the terms in the series
|
And a predicate function that detects when the terms in the series
|
||||||
“exceed four million”.
|
“exceed four million”.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('>4M == 4000000 >')
|
define('>4M == 4000000 >')
|
||||||
|
|
||||||
|
|
@ -488,11 +488,11 @@ Now it’s straightforward to define ``PE2`` as a recursive function that
|
||||||
generates terms in the Fibonacci sequence until they exceed four million
|
generates terms in the Fibonacci sequence until they exceed four million
|
||||||
and sums the even ones.
|
and sums the even ones.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec')
|
define('PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('PE2')
|
J('PE2')
|
||||||
|
|
||||||
|
|
@ -535,7 +535,7 @@ So the Fibonacci sequence considered in terms of just parity would be:
|
||||||
|
|
||||||
Every third term is even.
|
Every third term is even.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1 0 fib] x x x') # To start the sequence with 1 1 2 3 instead of 1 2 3.
|
J('[1 0 fib] x x x') # To start the sequence with 1 1 2 3 instead of 1 2 3.
|
||||||
|
|
||||||
|
|
@ -547,7 +547,7 @@ Every third term is even.
|
||||||
|
|
||||||
Drive the generator three times and ``popop`` the two odd terms.
|
Drive the generator three times and ``popop`` the two odd terms.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1 0 fib] x x x [popop] dipd')
|
J('[1 0 fib] x x x [popop] dipd')
|
||||||
|
|
||||||
|
|
@ -557,11 +557,11 @@ Drive the generator three times and ``popop`` the two odd terms.
|
||||||
2 [3 2 fib]
|
2 [3 2 fib]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('PE2.2 == x x x [popop] dipd')
|
define('PE2.2 == x x x [popop] dipd')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1 0 fib] 10 [PE2.2] times')
|
J('[1 0 fib] 10 [PE2.2] times')
|
||||||
|
|
||||||
|
|
@ -574,7 +574,7 @@ Drive the generator three times and ``popop`` the two odd terms.
|
||||||
Replace ``x`` with our new driver function ``PE2.2`` and start our
|
Replace ``x`` with our new driver function ``PE2.2`` and start our
|
||||||
``fib`` generator at ``1 0``.
|
``fib`` generator at ``1 0``.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec')
|
J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec')
|
||||||
|
|
||||||
|
|
@ -593,11 +593,11 @@ modifications to the default ``x``?
|
||||||
An Interesting Variation
|
An Interesting Variation
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('codireco == cons dip rest cons')
|
define('codireco == cons dip rest cons')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[0 [dup ++] codireco] x')
|
V('[0 [dup ++] codireco] x')
|
||||||
|
|
||||||
|
|
@ -620,11 +620,11 @@ An Interesting Variation
|
||||||
0 [1 [dup ++] codireco] .
|
0 [1 [dup ++] codireco] .
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('G == [codireco] cons cons')
|
define('G == [codireco] cons cons')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('230 [dup ++] G 5 [x] times pop')
|
J('230 [dup ++] G 5 [x] times pop')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ TBD (look in the :module: joy.parser module.)
|
||||||
Examples
|
Examples
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
joy.parser.text_to_expression('1 2 3 4 5') # A simple sequence.
|
joy.parser.text_to_expression('1 2 3 4 5') # A simple sequence.
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ Examples
|
||||||
(1, (2, (3, (4, (5, ())))))
|
(1, (2, (3, (4, (5, ())))))
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
joy.parser.text_to_expression('[1 2 3] 4 5') # Three items, the first is a list with three items
|
joy.parser.text_to_expression('[1 2 3] 4 5') # Three items, the first is a list with three items
|
||||||
|
|
||||||
|
|
@ -170,7 +170,7 @@ Examples
|
||||||
((1, (2, (3, ()))), (4, (5, ())))
|
((1, (2, (3, ()))), (4, (5, ())))
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
joy.parser.text_to_expression('1 23 ["four" [-5.0] cons] 8888') # A mixed bag. cons is
|
joy.parser.text_to_expression('1 23 ["four" [-5.0] cons] 8888') # A mixed bag. cons is
|
||||||
# a Symbol, no lookup at
|
# a Symbol, no lookup at
|
||||||
|
|
@ -184,7 +184,7 @@ Examples
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
joy.parser.text_to_expression('[][][][][]') # Five empty lists.
|
joy.parser.text_to_expression('[][][][][]') # Five empty lists.
|
||||||
|
|
||||||
|
|
@ -197,7 +197,7 @@ Examples
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
joy.parser.text_to_expression('[[[[[]]]]]') # Five nested lists.
|
joy.parser.text_to_expression('[[[[[]]]]]') # Five nested lists.
|
||||||
|
|
||||||
|
|
@ -221,7 +221,7 @@ provide control-flow and higher-order operations.
|
||||||
|
|
||||||
Many of the functions are defined in Python, like ``dip``:
|
Many of the functions are defined in Python, like ``dip``:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print inspect.getsource(joy.library.dip)
|
print inspect.getsource(joy.library.dip)
|
||||||
|
|
||||||
|
|
@ -239,7 +239,7 @@ When the interpreter executes a definition function that function just
|
||||||
pushes its body expression onto the pending expression (the
|
pushes its body expression onto the pending expression (the
|
||||||
continuation) and returns control to the interpreter.
|
continuation) and returns control to the interpreter.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print joy.library.definitions
|
print joy.library.definitions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ implementation under the hood. (Where does the “type” come from? It has
|
||||||
a contingent existence predicated on the disciplined use of these
|
a contingent existence predicated on the disciplined use of these
|
||||||
functions on otherwise undistinguished Joy datastructures.)
|
functions on otherwise undistinguished Joy datastructures.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import D, J, V, define, DefinitionWrapper
|
from notebook_preamble import D, J, V, define, DefinitionWrapper
|
||||||
|
|
||||||
|
|
@ -87,11 +87,11 @@ Definition:
|
||||||
|
|
||||||
Tree-new == swap [[] []] cons cons
|
Tree-new == swap [[] []] cons cons
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('Tree-new == swap [[] []] cons cons')
|
define('Tree-new == swap [[] []] cons cons')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('"v" "k" Tree-new')
|
J('"v" "k" Tree-new')
|
||||||
|
|
||||||
|
|
@ -163,11 +163,11 @@ comparison operator:
|
||||||
P < == pop roll> pop first <
|
P < == pop roll> pop first <
|
||||||
P == pop roll> pop first
|
P == pop roll> pop first
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('P == pop roll> pop first')
|
define('P == pop roll> pop first')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["old_key" 23 [] []] 17 "new_key" ["..."] P')
|
J('["old_key" 23 [] []] 17 "new_key" ["..."] P')
|
||||||
|
|
||||||
|
|
@ -242,11 +242,11 @@ And so ``T`` is just:
|
||||||
|
|
||||||
T == cons cons [dipdd] cons infra
|
T == cons cons [dipdd] cons infra
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('T == cons cons [dipdd] cons infra')
|
define('T == cons cons [dipdd] cons infra')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] T')
|
J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] T')
|
||||||
|
|
||||||
|
|
@ -266,7 +266,7 @@ This is very very similar to the above:
|
||||||
[key_n value_n left right] value key [Tree-add] E
|
[key_n value_n left right] value key [Tree-add] E
|
||||||
[key_n value_n left right] value key [Tree-add] [P <] [Te] [Ee] ifte
|
[key_n value_n left right] value key [Tree-add] [P <] [Te] [Ee] ifte
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('E == [P <] [Te] [Ee] ifte')
|
define('E == [P <] [Te] [Ee] ifte')
|
||||||
|
|
||||||
|
|
@ -278,11 +278,11 @@ instead of the right, so the only difference is that it must use
|
||||||
|
|
||||||
Te == cons cons [dipd] cons infra
|
Te == cons cons [dipd] cons infra
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('Te == cons cons [dipd] cons infra')
|
define('Te == cons cons [dipd] cons infra')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] Te')
|
J('["old_k" "old_value" "left" "right"] "new_value" "new_key" ["Tree-add"] Te')
|
||||||
|
|
||||||
|
|
@ -320,11 +320,11 @@ Example:
|
||||||
key new_value [ left right] cons cons
|
key new_value [ left right] cons cons
|
||||||
[key new_value left right]
|
[key new_value left right]
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('Ee == pop swap roll< rest rest cons cons')
|
define('Ee == pop swap roll< rest rest cons cons')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["k" "old_value" "left" "right"] "new_value" "k" ["Tree-add"] Ee')
|
J('["k" "old_value" "left" "right"] "new_value" "k" ["Tree-add"] Ee')
|
||||||
|
|
||||||
|
|
@ -355,14 +355,14 @@ Putting it all together:
|
||||||
|
|
||||||
Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
|
Tree-add == [popop not] [[pop] dipd Tree-new] [] [R] genrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [[P >] [T] [E] ifte] genrec')
|
define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [[P >] [T] [E] ifte] genrec')
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] 23 "b" Tree-add') # Initial
|
J('[] 23 "b" Tree-add') # Initial
|
||||||
|
|
||||||
|
|
@ -372,7 +372,7 @@ Examples
|
||||||
['b' 23 [] []]
|
['b' 23 [] []]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["b" 23 [] []] 88 "c" Tree-add') # Greater than
|
J('["b" 23 [] []] 88 "c" Tree-add') # Greater than
|
||||||
|
|
||||||
|
|
@ -382,7 +382,7 @@ Examples
|
||||||
['b' 23 [] ['c' 88 [] []]]
|
['b' 23 [] ['c' 88 [] []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["b" 23 [] []] 88 "a" Tree-add') # Less than
|
J('["b" 23 [] []] 88 "a" Tree-add') # Less than
|
||||||
|
|
||||||
|
|
@ -392,7 +392,7 @@ Examples
|
||||||
['b' 23 ['a' 88 [] []] []]
|
['b' 23 ['a' 88 [] []] []]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["b" 23 [] []] 88 "b" Tree-add') # Equal to
|
J('["b" 23 [] []] 88 "b" Tree-add') # Equal to
|
||||||
|
|
||||||
|
|
@ -402,7 +402,7 @@ Examples
|
||||||
['b' 88 [] []]
|
['b' 88 [] []]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Series.
|
J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Series.
|
||||||
|
|
||||||
|
|
@ -412,7 +412,7 @@ Examples
|
||||||
['b' 23 ['a' 88 [] []] ['c' 44 [] []]]
|
['b' 23 ['a' 88 [] []] ['c' 44 [] []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step')
|
J('[] [[23 "b"] [88 "a"] [44 "c"]] [i Tree-add] step')
|
||||||
|
|
||||||
|
|
@ -444,7 +444,7 @@ values:
|
||||||
------------------------- a < b
|
------------------------- a < b
|
||||||
L
|
L
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("1 0 ['G'] ['E'] ['L'] cmp")
|
J("1 0 ['G'] ['E'] ['L'] cmp")
|
||||||
|
|
||||||
|
|
@ -454,7 +454,7 @@ values:
|
||||||
'G'
|
'G'
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("1 1 ['G'] ['E'] ['L'] cmp")
|
J("1 1 ['G'] ['E'] ['L'] cmp")
|
||||||
|
|
||||||
|
|
@ -464,7 +464,7 @@ values:
|
||||||
'E'
|
'E'
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("0 1 ['G'] ['E'] ['L'] cmp")
|
J("0 1 ['G'] ['E'] ['L'] cmp")
|
||||||
|
|
||||||
|
|
@ -514,7 +514,7 @@ Or just:
|
||||||
|
|
||||||
P == over [popop popop first] nullary
|
P == over [popop popop first] nullary
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('P == over [popop popop first] nullary')
|
define('P == over [popop popop first] nullary')
|
||||||
|
|
||||||
|
|
@ -541,11 +541,11 @@ to understand:
|
||||||
|
|
||||||
Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec
|
Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec')
|
define('Tree-add == [popop not] [[pop] dipd Tree-new] [] [P [T] [Ee] [Te] cmp] genrec')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Still works.
|
J('[] 23 "b" Tree-add 88 "a" Tree-add 44 "c" Tree-add') # Still works.
|
||||||
|
|
||||||
|
|
@ -685,14 +685,14 @@ Working backward:
|
||||||
|
|
||||||
Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec
|
Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec')
|
define('Tree-iter == [not] [pop] roll< [dupdip rest rest] cons [step] genrec')
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] [foo] Tree-iter') # It doesn't matter what F is as it won't be used.
|
J('[] [foo] Tree-iter') # It doesn't matter what F is as it won't be used.
|
||||||
|
|
||||||
|
|
@ -702,7 +702,7 @@ Examples
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [first] Tree-iter")
|
J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [first] Tree-iter")
|
||||||
|
|
||||||
|
|
@ -712,7 +712,7 @@ Examples
|
||||||
'b' 'a' 'c'
|
'b' 'a' 'c'
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [second] Tree-iter")
|
J("['b' 23 ['a' 88 [] []] ['c' 44 [] []]] [second] Tree-iter")
|
||||||
|
|
||||||
|
|
@ -731,7 +731,7 @@ to it will only occur once within it, and we can query it in
|
||||||
`:math:`O(\log_2 N)` <https://en.wikipedia.org/wiki/Binary_search_tree#cite_note-2>`__
|
`:math:`O(\log_2 N)` <https://en.wikipedia.org/wiki/Binary_search_tree#cite_note-2>`__
|
||||||
time.
|
time.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step')
|
J('[] [3 9 5 2 8 6 7 8 4] [0 swap Tree-add] step')
|
||||||
|
|
||||||
|
|
@ -741,11 +741,11 @@ time.
|
||||||
[3 0 [2 0 [] []] [9 0 [5 0 [4 0 [] []] [8 0 [6 0 [] [7 0 [] []]] []]] []]]
|
[3 0 [2 0 [] []] [9 0 [5 0 [4 0 [] []] [8 0 [6 0 [] [7 0 [] []]] []]] []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('to_set == [] swap [0 swap Tree-add] step')
|
define('to_set == [] swap [0 swap Tree-add] step')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[3 9 5 2 8 6 7 8 4] to_set')
|
J('[3 9 5 2 8 6 7 8 4] to_set')
|
||||||
|
|
||||||
|
|
@ -758,11 +758,11 @@ time.
|
||||||
And with that we can write a little program ``unique`` to remove
|
And with that we can write a little program ``unique`` to remove
|
||||||
duplicate items from a list.
|
duplicate items from a list.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('unique == [to_set [first] Tree-iter] cons run')
|
define('unique == [to_set [first] Tree-iter] cons run')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique') # Filter duplicate items.
|
J('[3 9 3 5 2 9 8 8 8 6 2 7 8 4 3] unique') # Filter duplicate items.
|
||||||
|
|
||||||
|
|
@ -872,7 +872,7 @@ Let’s do a little semantic factoring:
|
||||||
|
|
||||||
Now we can sort sequences.
|
Now we can sort sequences.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
#define('Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec')
|
#define('Tree-iter-order == [not] [pop] [dup third] [[cons dip] dupdip [[first] dupdip] dip [rest rest rest first] dip i] genrec')
|
||||||
|
|
||||||
|
|
@ -892,7 +892,7 @@ Now we can sort sequences.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order')
|
J('[3 9 5 2 8 6 7 8 4] to_set Tree-iter-order')
|
||||||
|
|
||||||
|
|
@ -1070,7 +1070,7 @@ So:
|
||||||
|
|
||||||
Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec
|
Tree-get == [pop not] swap [] [P [T>] [E] [T<] cmp] genrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
# I don't want to deal with name conflicts with the above so I'm inlining everything here.
|
# I don't want to deal with name conflicts with the above so I'm inlining everything here.
|
||||||
# The original Joy system has "hide" which is a meta-command which allows you to use named
|
# The original Joy system has "hide" which is a meta-command which allows you to use named
|
||||||
|
|
@ -1088,7 +1088,7 @@ So:
|
||||||
] genrec
|
] genrec
|
||||||
''')
|
''')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["gary" 23 [] []] "mike" [popd " not in tree" +] Tree-get')
|
J('["gary" 23 [] []] "mike" [popd " not in tree" +] Tree-get')
|
||||||
|
|
||||||
|
|
@ -1098,7 +1098,7 @@ So:
|
||||||
'mike not in tree'
|
'mike not in tree'
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('["gary" 23 [] []] "gary" [popop "err"] Tree-get')
|
J('["gary" 23 [] []] "gary" [popop "err"] Tree-get')
|
||||||
|
|
||||||
|
|
@ -1108,7 +1108,7 @@ So:
|
||||||
23
|
23
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('''
|
J('''
|
||||||
|
|
||||||
|
|
@ -1124,7 +1124,7 @@ So:
|
||||||
2
|
2
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('''
|
J('''
|
||||||
|
|
||||||
|
|
@ -1500,7 +1500,7 @@ Refactoring
|
||||||
By the standards of the code I’ve written so far, this is a *huge* Joy
|
By the standards of the code I’ve written so far, this is a *huge* Joy
|
||||||
program.
|
program.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
DefinitionWrapper.add_definitions('''
|
DefinitionWrapper.add_definitions('''
|
||||||
first_two == uncons uncons pop
|
first_two == uncons uncons pop
|
||||||
|
|
@ -1519,7 +1519,7 @@ program.
|
||||||
Tree-Delete == [pop not] [pop] [R0] [R1] genrec
|
Tree-Delete == [pop not] [pop] [R0] [R1] genrec
|
||||||
''', D)
|
''', D)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' Tree-Delete ")
|
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' Tree-Delete ")
|
||||||
|
|
||||||
|
|
@ -1529,7 +1529,7 @@ program.
|
||||||
['a' 23 [] ['b' 88 [] []]]
|
['a' 23 [] ['b' 88 [] []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' Tree-Delete ")
|
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' Tree-Delete ")
|
||||||
|
|
||||||
|
|
@ -1539,7 +1539,7 @@ program.
|
||||||
['a' 23 [] ['c' 44 [] []]]
|
['a' 23 [] ['c' 44 [] []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' Tree-Delete ")
|
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' Tree-Delete ")
|
||||||
|
|
||||||
|
|
@ -1549,7 +1549,7 @@ program.
|
||||||
['b' 88 [] ['c' 44 [] []]]
|
['b' 88 [] ['c' 44 [] []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' Tree-Delete ")
|
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' Tree-Delete ")
|
||||||
|
|
||||||
|
|
@ -1559,7 +1559,7 @@ program.
|
||||||
['a' 23 [] ['b' 88 [] ['c' 44 [] []]]]
|
['a' 23 [] ['b' 88 [] ['c' 44 [] []]]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step')
|
J('[] [4 2 3 1 6 7 5 ] [0 swap Tree-add] step')
|
||||||
|
|
||||||
|
|
@ -1569,7 +1569,7 @@ program.
|
||||||
[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]]
|
[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete ")
|
J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 3 Tree-Delete ")
|
||||||
|
|
||||||
|
|
@ -1579,7 +1579,7 @@ program.
|
||||||
[4 0 [2 0 [1 0 [] []] []] [6 0 [5 0 [] []] [7 0 [] []]]]
|
[4 0 [2 0 [1 0 [] []] []] [6 0 [5 0 [] []] [7 0 [] []]]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete ")
|
J("[4 0 [2 0 [1 0 [] []] [3 0 [] []]] [6 0 [5 0 [] []] [7 0 [] []]]] 4 Tree-Delete ")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import J, V, define
|
from notebook_preamble import J, V, define
|
||||||
|
|
||||||
|
|
@ -81,13 +81,13 @@ the variables:
|
||||||
The three arguments are to the left, so we can “chop off” everything to
|
The three arguments are to the left, so we can “chop off” everything to
|
||||||
the right and say it’s the definition of the ``quadratic`` function:
|
the right and say it’s the definition of the ``quadratic`` function:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
|
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
|
||||||
|
|
||||||
Let’s try it out:
|
Let’s try it out:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('3 1 1 quadratic')
|
J('3 1 1 quadratic')
|
||||||
|
|
||||||
|
|
@ -102,7 +102,7 @@ lines are the ``dip`` and ``dipd`` combinators building the main program
|
||||||
by incorporating the values on the stack. Then that program runs and you
|
by incorporating the values on the stack. Then that program runs and you
|
||||||
get the results. This is pretty typical of Joy code.
|
get the results. This is pretty typical of Joy code.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('-5 1 4 quadratic')
|
V('-5 1 4 quadratic')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import D, DefinitionWrapper, J, V, define
|
from notebook_preamble import D, DefinitionWrapper, J, V, define
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ is a recursive function ``H :: A -> C`` that converts a value of type
|
||||||
It may be helpful to see this function implemented in imperative Python
|
It may be helpful to see this function implemented in imperative Python
|
||||||
code.
|
code.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def hylomorphism(c, F, P, G):
|
def hylomorphism(c, F, P, G):
|
||||||
'''Return a hylomorphism function H.'''
|
'''Return a hylomorphism function H.'''
|
||||||
|
|
@ -185,7 +185,7 @@ the left so we have a definition for ``hylomorphism``:
|
||||||
|
|
||||||
hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec
|
hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
|
define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
|
||||||
|
|
||||||
|
|
@ -203,13 +203,13 @@ To sum a range of integers from 0 to *n* - 1:
|
||||||
- ``[G]`` is ``[-- dup]``
|
- ``[G]`` is ``[-- dup]``
|
||||||
- ``[F]`` is ``[+]``
|
- ``[F]`` is ``[+]``
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
|
define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
|
||||||
|
|
||||||
Let’s try it:
|
Let’s try it:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('5 triangular_number')
|
J('5 triangular_number')
|
||||||
|
|
||||||
|
|
@ -219,7 +219,7 @@ Let’s try it:
|
||||||
10
|
10
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[0 1 2 3 4 5 6] [triangular_number] map')
|
J('[0 1 2 3 4 5 6] [triangular_number] map')
|
||||||
|
|
||||||
|
|
@ -405,11 +405,11 @@ Each of the above variations can be used to make four slightly different
|
||||||
H1 == [P] [pop c] [G] [dip F] genrec
|
H1 == [P] [pop c] [G] [dip F] genrec
|
||||||
== [0 <=] [pop []] [-- dup] [dip swons] genrec
|
== [0 <=] [pop []] [-- dup] [dip swons] genrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
|
define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('5 range')
|
J('5 range')
|
||||||
|
|
||||||
|
|
@ -427,11 +427,11 @@ Each of the above variations can be used to make four slightly different
|
||||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||||
== [] swap [0 <=] [pop] [-- dup [swons] dip] primrec
|
== [] swap [0 <=] [pop] [-- dup [swons] dip] primrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
|
define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('5 range_reverse')
|
J('5 range_reverse')
|
||||||
|
|
||||||
|
|
@ -449,11 +449,11 @@ Each of the above variations can be used to make four slightly different
|
||||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||||
== [0 <=] [pop []] [[--] dupdip] [dip swons] genrec
|
== [0 <=] [pop []] [[--] dupdip] [dip swons] genrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
|
define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('5 ranger')
|
J('5 ranger')
|
||||||
|
|
||||||
|
|
@ -471,11 +471,11 @@ Each of the above variations can be used to make four slightly different
|
||||||
H4 == c swap [P] [pop] [[F] dupdip G ] primrec
|
H4 == c swap [P] [pop] [[F] dupdip G ] primrec
|
||||||
== [] swap [0 <=] [pop] [[swons] dupdip --] primrec
|
== [] swap [0 <=] [pop] [[swons] dupdip --] primrec
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
|
define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('5 ranger_reverse')
|
J('5 ranger_reverse')
|
||||||
|
|
||||||
|
|
@ -501,7 +501,7 @@ and makes some new value.
|
||||||
|
|
||||||
C == [not] c [uncons swap] [F] hylomorphism
|
C == [not] c [uncons swap] [F] hylomorphism
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('swuncons == uncons swap') # Awkward name.
|
define('swuncons == uncons swap') # Awkward name.
|
||||||
|
|
||||||
|
|
@ -511,11 +511,11 @@ An example of a catamorphism is the sum function.
|
||||||
|
|
||||||
sum == [not] 0 [swuncons] [+] hylomorphism
|
sum == [not] 0 [swuncons] [+] hylomorphism
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('sum == [not] 0 [swuncons] [+] hylomorphism')
|
define('sum == [not] 0 [swuncons] [+] hylomorphism')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[5 4 3 2 1] sum')
|
J('[5 4 3 2 1] sum')
|
||||||
|
|
||||||
|
|
@ -531,7 +531,7 @@ The ``step`` combinator
|
||||||
The ``step`` combinator will usually be better to use than
|
The ``step`` combinator will usually be better to use than
|
||||||
``catamorphism``.
|
``catamorphism``.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[step] help')
|
J('[step] help')
|
||||||
|
|
||||||
|
|
@ -560,11 +560,11 @@ The ``step`` combinator will usually be better to use than
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('sum == 0 swap [+] step')
|
define('sum == 0 swap [+] step')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[5 4 3 2 1] sum')
|
J('[5 4 3 2 1] sum')
|
||||||
|
|
||||||
|
|
@ -592,11 +592,11 @@ With:
|
||||||
G == --
|
G == --
|
||||||
P == 1 <=
|
P == 1 <=
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
|
define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('5 factorial')
|
J('5 factorial')
|
||||||
|
|
||||||
|
|
@ -635,11 +635,11 @@ We would use:
|
||||||
G == rest dup
|
G == rest dup
|
||||||
P == not
|
P == not
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
|
define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1 2 3] tails')
|
J('[1 2 3] tails')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ dictionary. However, there’s no function that does that. Adding a new
|
||||||
function to the dictionary is a meta-interpreter action, you have to do
|
function to the dictionary is a meta-interpreter action, you have to do
|
||||||
it in Python, not Joy.
|
it in Python, not Joy.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import D, J, V
|
from notebook_preamble import D, J, V
|
||||||
|
|
||||||
A long trace
|
A long trace
|
||||||
------------
|
------------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[23 18] average')
|
V('[23 18] average')
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ An efficient ``sum`` function is already in the library. But for
|
||||||
``size`` we can use a “compiled” version hand-written in Python to speed
|
``size`` we can use a “compiled” version hand-written in Python to speed
|
||||||
up evaluation and make the trace more readable.
|
up evaluation and make the trace more readable.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from joy.library import SimpleFunctionWrapper
|
from joy.library import SimpleFunctionWrapper
|
||||||
from joy.utils.stack import iter_stack
|
from joy.utils.stack import iter_stack
|
||||||
|
|
@ -99,7 +99,7 @@ up evaluation and make the trace more readable.
|
||||||
Now we replace the old version in the dictionary with the new version,
|
Now we replace the old version in the dictionary with the new version,
|
||||||
and re-evaluate the expression.
|
and re-evaluate the expression.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
D['size'] = size
|
D['size'] = size
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ A shorter trace
|
||||||
|
|
||||||
You can see that ``size`` now executes in a single step.
|
You can see that ``size`` now executes in a single step.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[23 18] average')
|
V('[23 18] average')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,11 @@ Working backwards:
|
||||||
Define ``treestep``
|
Define ``treestep``
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import D, J, V, define, DefinitionWrapper
|
from notebook_preamble import D, J, V, define, DefinitionWrapper
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
DefinitionWrapper.add_definitions('''
|
DefinitionWrapper.add_definitions('''
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ all nodes in a tree with this function:
|
||||||
|
|
||||||
sumtree == [pop 0] [] [sum +] treestep
|
sumtree == [pop 0] [] [sum +] treestep
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('sumtree == [pop 0] [] [sum +] treestep')
|
define('sumtree == [pop 0] [] [sum +] treestep')
|
||||||
|
|
||||||
|
|
@ -185,7 +185,7 @@ Running this function on an empty tree value gives zero:
|
||||||
------------------------------------
|
------------------------------------
|
||||||
0
|
0
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[] sumtree') # Empty tree.
|
J('[] sumtree') # Empty tree.
|
||||||
|
|
||||||
|
|
@ -205,7 +205,7 @@ Running it on a non-empty node:
|
||||||
n m +
|
n m +
|
||||||
n+m
|
n+m
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23] sumtree') # No child trees.
|
J('[23] sumtree') # No child trees.
|
||||||
|
|
||||||
|
|
@ -215,7 +215,7 @@ Running it on a non-empty node:
|
||||||
23
|
23
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 []] sumtree') # Child tree, empty.
|
J('[23 []] sumtree') # Child tree, empty.
|
||||||
|
|
||||||
|
|
@ -225,7 +225,7 @@ Running it on a non-empty node:
|
||||||
23
|
23
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees.
|
J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees.
|
||||||
|
|
||||||
|
|
@ -235,7 +235,7 @@ Running it on a non-empty node:
|
||||||
32
|
32
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc...
|
J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc...
|
||||||
|
|
||||||
|
|
@ -245,7 +245,7 @@ Running it on a non-empty node:
|
||||||
49
|
49
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling".
|
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling".
|
||||||
|
|
||||||
|
|
@ -255,7 +255,7 @@ Running it on a non-empty node:
|
||||||
49
|
49
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node.
|
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node.
|
||||||
|
|
||||||
|
|
@ -265,7 +265,7 @@ Running it on a non-empty node:
|
||||||
[23 [23 [23] [23]] [23] [23 []]]
|
[23 [23 [23] [23]] [23] [23 []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
|
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
|
||||||
|
|
||||||
|
|
@ -275,7 +275,7 @@ Running it on a non-empty node:
|
||||||
[1 [1 [1] [1]] [1] [1 []]]
|
[1 [1 [1] [1]] [1] [1 []]]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
|
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
|
||||||
|
|
||||||
|
|
@ -285,7 +285,7 @@ Running it on a non-empty node:
|
||||||
6
|
6
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
||||||
|
|
||||||
|
|
@ -295,7 +295,7 @@ Running it on a non-empty node:
|
||||||
6
|
6
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
||||||
|
|
||||||
|
|
@ -339,7 +339,7 @@ Traversal
|
||||||
|
|
||||||
This doesn’t quite work:
|
This doesn’t quite work:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
|
J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
|
||||||
|
|
||||||
|
|
@ -369,7 +369,7 @@ So:
|
||||||
|
|
||||||
[] [first] [flatten cons] treestep
|
[] [first] [flatten cons] treestep
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep')
|
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep')
|
||||||
|
|
||||||
|
|
@ -401,7 +401,7 @@ So:
|
||||||
|
|
||||||
[] [i roll< swons concat] [first] treestep
|
[] [i roll< swons concat] [first] treestep
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep')
|
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep')
|
||||||
|
|
||||||
|
|
@ -429,7 +429,7 @@ Plugging in our BTree structure:
|
||||||
|
|
||||||
[key value] N [left right] [K] C
|
[key value] N [left right] [K] C
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
|
J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
|
||||||
|
|
||||||
|
|
@ -444,7 +444,7 @@ Plugging in our BTree structure:
|
||||||
|
|
||||||
Iteration through the nodes
|
Iteration through the nodes
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind')
|
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind')
|
||||||
|
|
||||||
|
|
@ -456,7 +456,7 @@ Iteration through the nodes
|
||||||
|
|
||||||
Sum the nodes’ keys.
|
Sum the nodes’ keys.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind')
|
J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind')
|
||||||
|
|
||||||
|
|
@ -468,7 +468,7 @@ Sum the nodes’ keys.
|
||||||
|
|
||||||
Rebuild the tree using ``map`` (imitating ``treestep``.)
|
Rebuild the tree using ``map`` (imitating ``treestep``.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind')
|
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind')
|
||||||
|
|
||||||
|
|
@ -574,7 +574,7 @@ Putting it together
|
||||||
|
|
||||||
To me, that seems simpler than the ``genrec`` version.
|
To me, that seems simpler than the ``genrec`` version.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
DefinitionWrapper.add_definitions('''
|
DefinitionWrapper.add_definitions('''
|
||||||
|
|
||||||
|
|
@ -587,7 +587,7 @@ To me, that seems simpler than the ``genrec`` version.
|
||||||
|
|
||||||
''', D)
|
''', D)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('''\
|
J('''\
|
||||||
|
|
||||||
|
|
@ -603,7 +603,7 @@ To me, that seems simpler than the ``genrec`` version.
|
||||||
15
|
15
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('''\
|
J('''\
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Type Checking
|
Type Checking
|
||||||
=============
|
=============
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
import logging, sys
|
import logging, sys
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ Type Checking
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
)
|
)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from joy.utils.types import (
|
from joy.utils.types import (
|
||||||
doc_from_stack_effect,
|
doc_from_stack_effect,
|
||||||
|
|
@ -22,7 +22,7 @@ Type Checking
|
||||||
JoyTypeError,
|
JoyTypeError,
|
||||||
)
|
)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
D = FUNCTIONS.copy()
|
D = FUNCTIONS.copy()
|
||||||
del D['product']
|
del D['product']
|
||||||
|
|
@ -31,7 +31,7 @@ Type Checking
|
||||||
An Example
|
An Example
|
||||||
----------
|
----------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
|
fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ An Example
|
||||||
40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
|
40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print doc_from_stack_effect(fi, fo)
|
print doc_from_stack_effect(fi, fo)
|
||||||
|
|
||||||
|
|
@ -56,13 +56,13 @@ An Example
|
||||||
([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
|
([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from joy.parser import text_to_expression
|
from joy.parser import text_to_expression
|
||||||
from joy.utils.stack import stack_to_string
|
from joy.utils.stack import stack_to_string
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
e = text_to_expression('0 1 2 [3 4]') # reverse order
|
e = text_to_expression('0 1 2 [3 4]') # reverse order
|
||||||
print stack_to_string(e)
|
print stack_to_string(e)
|
||||||
|
|
@ -73,7 +73,7 @@ An Example
|
||||||
[3 4] 2 1 0
|
[3 4] 2 1 0
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
u = unify(e, fi)[0]
|
u = unify(e, fi)[0]
|
||||||
u
|
u
|
||||||
|
|
@ -87,7 +87,7 @@ An Example
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
g = reify(u, (fi, fo))
|
g = reify(u, (fi, fo))
|
||||||
print doc_from_stack_effect(*g)
|
print doc_from_stack_effect(*g)
|
||||||
|
|
@ -101,11 +101,11 @@ An Example
|
||||||
Unification Works “in Reverse”
|
Unification Works “in Reverse”
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
e = text_to_expression('[2 3]')
|
e = text_to_expression('[2 3]')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
u = unify(e, fo)[0] # output side, not input side
|
u = unify(e, fo)[0] # output side, not input side
|
||||||
u
|
u
|
||||||
|
|
@ -119,7 +119,7 @@ Unification Works “in Reverse”
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
g = reify(u, (fi, fo))
|
g = reify(u, (fi, fo))
|
||||||
print doc_from_stack_effect(*g)
|
print doc_from_stack_effect(*g)
|
||||||
|
|
@ -133,7 +133,7 @@ Unification Works “in Reverse”
|
||||||
Failing a Check
|
Failing a Check
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
fi, fo = infer(dup, mul)[0]
|
fi, fo = infer(dup, mul)[0]
|
||||||
|
|
||||||
|
|
@ -146,7 +146,7 @@ Failing a Check
|
||||||
31 (i1 -- i2) ∘
|
31 (i1 -- i2) ∘
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
e = text_to_expression('"two"')
|
e = text_to_expression('"two"')
|
||||||
print stack_to_string(e)
|
print stack_to_string(e)
|
||||||
|
|
@ -157,7 +157,7 @@ Failing a Check
|
||||||
'two'
|
'two'
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
try:
|
try:
|
||||||
unify(e, fi)
|
unify(e, fi)
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ Compiling ``pop∘swap∘roll<``
|
||||||
|
|
||||||
The simplest way to “compile” this function would be something like:
|
The simplest way to “compile” this function would be something like:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def poswrd(s, e, d):
|
def poswrd(s, e, d):
|
||||||
return rolldown(*swap(*pop(s, e, d)))
|
return rolldown(*swap(*pop(s, e, d)))
|
||||||
|
|
@ -200,7 +200,7 @@ Looking ahead for a moment, from the stack effect comment:
|
||||||
|
|
||||||
We should be able to directly write out a Python function like:
|
We should be able to directly write out a Python function like:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def poswrd(stack):
|
def poswrd(stack):
|
||||||
(_, (a, (b, (c, stack)))) = stack
|
(_, (a, (b, (c, stack)))) = stack
|
||||||
|
|
@ -393,7 +393,7 @@ And there you have it, the stack effect for
|
||||||
From this stack effect comment it should be possible to construct the
|
From this stack effect comment it should be possible to construct the
|
||||||
following Python code:
|
following Python code:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def F(stack):
|
def F(stack):
|
||||||
(_, (d, (c, ((a, (b, S0)), stack)))) = stack
|
(_, (d, (c, ((a, (b, S0)), stack)))) = stack
|
||||||
|
|
@ -408,7 +408,7 @@ Representing Stack Effect Comments in Python
|
||||||
I’m going to use pairs of tuples of type descriptors, which will be
|
I’m going to use pairs of tuples of type descriptors, which will be
|
||||||
integers or tuples of type descriptors:
|
integers or tuples of type descriptors:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
roll_dn = (1, 2, 3), (2, 3, 1)
|
roll_dn = (1, 2, 3), (2, 3, 1)
|
||||||
|
|
||||||
|
|
@ -419,7 +419,7 @@ integers or tuples of type descriptors:
|
||||||
``compose()``
|
``compose()``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def compose(f, g):
|
def compose(f, g):
|
||||||
|
|
||||||
|
|
@ -465,7 +465,7 @@ integers or tuples of type descriptors:
|
||||||
``unify()``
|
``unify()``
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def unify(u, v, s=None):
|
def unify(u, v, s=None):
|
||||||
if s is None:
|
if s is None:
|
||||||
|
|
@ -483,7 +483,7 @@ integers or tuples of type descriptors:
|
||||||
``update()``
|
``update()``
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def update(s, term):
|
def update(s, term):
|
||||||
if not isinstance(term, tuple):
|
if not isinstance(term, tuple):
|
||||||
|
|
@ -493,7 +493,7 @@ integers or tuples of type descriptors:
|
||||||
``relabel()``
|
``relabel()``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def relabel(left, right):
|
def relabel(left, right):
|
||||||
return left, _1000(right)
|
return left, _1000(right)
|
||||||
|
|
@ -517,7 +517,7 @@ integers or tuples of type descriptors:
|
||||||
``delabel()``
|
``delabel()``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def delabel(f):
|
def delabel(f):
|
||||||
s = {u: i for i, u in enumerate(sorted(_unique(f)))}
|
s = {u: i for i, u in enumerate(sorted(_unique(f)))}
|
||||||
|
|
@ -551,7 +551,7 @@ At last we put it all together in a function ``C()`` that accepts two
|
||||||
stack effect comments and returns their composition (or raises and
|
stack effect comments and returns their composition (or raises and
|
||||||
exception if they can’t be composed due to type conflicts.)
|
exception if they can’t be composed due to type conflicts.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def C(f, g):
|
def C(f, g):
|
||||||
f, g = relabel(f, g)
|
f, g = relabel(f, g)
|
||||||
|
|
@ -560,7 +560,7 @@ exception if they can’t be composed due to type conflicts.)
|
||||||
|
|
||||||
Let’s try it out.
|
Let’s try it out.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(pop, swap)
|
C(pop, swap)
|
||||||
|
|
||||||
|
|
@ -573,7 +573,7 @@ Let’s try it out.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(C(pop, swap), roll_dn)
|
C(C(pop, swap), roll_dn)
|
||||||
|
|
||||||
|
|
@ -586,7 +586,7 @@ Let’s try it out.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(swap, roll_dn)
|
C(swap, roll_dn)
|
||||||
|
|
||||||
|
|
@ -599,7 +599,7 @@ Let’s try it out.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(pop, C(swap, roll_dn))
|
C(pop, C(swap, roll_dn))
|
||||||
|
|
||||||
|
|
@ -612,7 +612,7 @@ Let’s try it out.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
poswrd = reduce(C, (pop, swap, roll_dn))
|
poswrd = reduce(C, (pop, swap, roll_dn))
|
||||||
poswrd
|
poswrd
|
||||||
|
|
@ -633,13 +633,13 @@ Here’s that trick to represent functions like ``rest`` and ``cons`` that
|
||||||
manipulate stacks. We use a cons-list of tuples and give the tails their
|
manipulate stacks. We use a cons-list of tuples and give the tails their
|
||||||
own numbers. Then everything above already works.
|
own numbers. Then everything above already works.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
rest = ((1, 2),), (2,)
|
rest = ((1, 2),), (2,)
|
||||||
|
|
||||||
cons = (1, 2), ((1, 2),)
|
cons = (1, 2), ((1, 2),)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(poswrd, rest)
|
C(poswrd, rest)
|
||||||
|
|
||||||
|
|
@ -671,7 +671,7 @@ The translation table, if you will, would be:
|
||||||
0: 0,
|
0: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
F = reduce(C, (pop, swap, roll_dn, rest, rest, cons, cons))
|
F = reduce(C, (pop, swap, roll_dn, rest, rest, cons, cons))
|
||||||
|
|
||||||
|
|
@ -699,11 +699,11 @@ Dealing with ``cons`` and ``uncons``
|
||||||
However, if we try to compose e.g. ``cons`` and ``uncons`` it won’t
|
However, if we try to compose e.g. ``cons`` and ``uncons`` it won’t
|
||||||
work:
|
work:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
uncons = ((1, 2),), (1, 2)
|
uncons = ((1, 2),), (1, 2)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
try:
|
try:
|
||||||
C(cons, uncons)
|
C(cons, uncons)
|
||||||
|
|
@ -723,7 +723,7 @@ The problem is that the ``unify()`` function as written doesn’t handle
|
||||||
the case when both terms are tuples. We just have to add a clause to
|
the case when both terms are tuples. We just have to add a clause to
|
||||||
deal with this recursively:
|
deal with this recursively:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def unify(u, v, s=None):
|
def unify(u, v, s=None):
|
||||||
if s is None:
|
if s is None:
|
||||||
|
|
@ -753,7 +753,7 @@ deal with this recursively:
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(cons, uncons)
|
C(cons, uncons)
|
||||||
|
|
||||||
|
|
@ -771,7 +771,7 @@ Part III: Compiling Yin Functions
|
||||||
|
|
||||||
Now consider the Python function we would like to derive:
|
Now consider the Python function we would like to derive:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def F_python(stack):
|
def F_python(stack):
|
||||||
(_, (d, (c, ((a, (b, S0)), stack)))) = stack
|
(_, (d, (c, ((a, (b, S0)), stack)))) = stack
|
||||||
|
|
@ -779,7 +779,7 @@ Now consider the Python function we would like to derive:
|
||||||
|
|
||||||
And compare it to the input stack effect comment tuple we just computed:
|
And compare it to the input stack effect comment tuple we just computed:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
F[0]
|
F[0]
|
||||||
|
|
||||||
|
|
@ -816,7 +816,7 @@ Eh?
|
||||||
|
|
||||||
And the return tuple
|
And the return tuple
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
F[1]
|
F[1]
|
||||||
|
|
||||||
|
|
@ -848,7 +848,7 @@ Python Identifiers
|
||||||
We want to substitute Python identifiers for the integers. I’m going to
|
We want to substitute Python identifiers for the integers. I’m going to
|
||||||
repurpose ``joy.parser.Symbol`` class for this:
|
repurpose ``joy.parser.Symbol`` class for this:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from joy.parser import Symbol
|
from joy.parser import Symbol
|
||||||
|
|
@ -874,7 +874,7 @@ effect comment tuples to reasonable text format. There are some details
|
||||||
in how this code works that related to stuff later in the notebook, so
|
in how this code works that related to stuff later in the notebook, so
|
||||||
you should skip it for now and read it later if you’re interested.
|
you should skip it for now and read it later if you’re interested.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def doc_from_stack_effect(inputs, outputs):
|
def doc_from_stack_effect(inputs, outputs):
|
||||||
return '(%s--%s)' % (
|
return '(%s--%s)' % (
|
||||||
|
|
@ -914,7 +914,7 @@ Now we can write a compiler function to emit Python source code. (The
|
||||||
underscore suffix distiguishes it from the built-in ``compile()``
|
underscore suffix distiguishes it from the built-in ``compile()``
|
||||||
function.)
|
function.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def compile_(name, f, doc=None):
|
def compile_(name, f, doc=None):
|
||||||
if doc is None:
|
if doc is None:
|
||||||
|
|
@ -932,7 +932,7 @@ function.)
|
||||||
|
|
||||||
Here it is in action:
|
Here it is in action:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
source = compile_('F', F)
|
source = compile_('F', F)
|
||||||
|
|
||||||
|
|
@ -949,7 +949,7 @@ Here it is in action:
|
||||||
|
|
||||||
Compare:
|
Compare:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def F_python(stack):
|
def F_python(stack):
|
||||||
(_, (d, (c, ((a, (b, S0)), stack)))) = stack
|
(_, (d, (c, ((a, (b, S0)), stack)))) = stack
|
||||||
|
|
@ -957,7 +957,7 @@ Compare:
|
||||||
|
|
||||||
Next steps:
|
Next steps:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
L = {}
|
L = {}
|
||||||
|
|
||||||
|
|
@ -976,16 +976,16 @@ Next steps:
|
||||||
|
|
||||||
Let’s try it out:
|
Let’s try it out:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import D, J, V
|
from notebook_preamble import D, J, V
|
||||||
from joy.library import SimpleFunctionWrapper
|
from joy.library import SimpleFunctionWrapper
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
D['F'] = SimpleFunctionWrapper(L['F'])
|
D['F'] = SimpleFunctionWrapper(L['F'])
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[4 5 ...] 2 3 1 F')
|
J('[4 5 ...] 2 3 1 F')
|
||||||
|
|
||||||
|
|
@ -1012,7 +1012,7 @@ Compiling Library Functions
|
||||||
We can use ``compile_()`` to generate many primitives in the library
|
We can use ``compile_()`` to generate many primitives in the library
|
||||||
from their stack effect comments:
|
from their stack effect comments:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def defs():
|
def defs():
|
||||||
|
|
||||||
|
|
@ -1036,7 +1036,7 @@ from their stack effect comments:
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for name, stack_effect_comment in sorted(defs().items()):
|
for name, stack_effect_comment in sorted(defs().items()):
|
||||||
print
|
print
|
||||||
|
|
@ -1205,7 +1205,7 @@ Python class hierarchy of Joy types and use the ``issubclass()`` method
|
||||||
to establish domain ordering, as well as other handy behaviour that will
|
to establish domain ordering, as well as other handy behaviour that will
|
||||||
make it fairly easy to reuse most of the code above.
|
make it fairly easy to reuse most of the code above.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
class AnyJoyType(object):
|
class AnyJoyType(object):
|
||||||
|
|
||||||
|
|
@ -1251,14 +1251,14 @@ make it fairly easy to reuse most of the code above.
|
||||||
|
|
||||||
Mess with it a little:
|
Mess with it a little:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from itertools import permutations
|
from itertools import permutations
|
||||||
|
|
||||||
“Any” types can be specialized to numbers and stacks, but not vice
|
“Any” types can be specialized to numbers and stacks, but not vice
|
||||||
versa:
|
versa:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for a, b in permutations((A[0], N[0], S[0]), 2):
|
for a, b in permutations((A[0], N[0], S[0]), 2):
|
||||||
print a, '>=', b, '->', a >= b
|
print a, '>=', b, '->', a >= b
|
||||||
|
|
@ -1278,7 +1278,7 @@ Our crude `Numerical
|
||||||
Tower <https://en.wikipedia.org/wiki/Numerical_tower>`__ of *numbers* >
|
Tower <https://en.wikipedia.org/wiki/Numerical_tower>`__ of *numbers* >
|
||||||
*floats* > *integers* works as well (but we’re not going to use it yet):
|
*floats* > *integers* works as well (but we’re not going to use it yet):
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for a, b in permutations((A[0], N[0], FloatJoyType(0), IntJoyType(0)), 2):
|
for a, b in permutations((A[0], N[0], FloatJoyType(0), IntJoyType(0)), 2):
|
||||||
print a, '>=', b, '->', a >= b
|
print a, '>=', b, '->', a >= b
|
||||||
|
|
@ -1303,13 +1303,13 @@ Tower <https://en.wikipedia.org/wiki/Numerical_tower>`__ of *numbers* >
|
||||||
Typing ``sqr``
|
Typing ``sqr``
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
dup = (A[1],), (A[1], A[1])
|
dup = (A[1],), (A[1], A[1])
|
||||||
|
|
||||||
mul = (N[1], N[2]), (N[3],)
|
mul = (N[1], N[2]), (N[3],)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
dup
|
dup
|
||||||
|
|
||||||
|
|
@ -1322,7 +1322,7 @@ Typing ``sqr``
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
mul
|
mul
|
||||||
|
|
||||||
|
|
@ -1340,7 +1340,7 @@ Modifying the Inferencer
|
||||||
|
|
||||||
Re-labeling still works fine:
|
Re-labeling still works fine:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
foo = relabel(dup, mul)
|
foo = relabel(dup, mul)
|
||||||
|
|
||||||
|
|
@ -1361,7 +1361,7 @@ Re-labeling still works fine:
|
||||||
The ``delabel()`` function needs an overhaul. It now has to keep track
|
The ``delabel()`` function needs an overhaul. It now has to keep track
|
||||||
of how many labels of each domain it has “seen”.
|
of how many labels of each domain it has “seen”.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
|
|
@ -1383,7 +1383,7 @@ of how many labels of each domain it has “seen”.
|
||||||
|
|
||||||
return tuple(delabel(inner, seen, c) for inner in f)
|
return tuple(delabel(inner, seen, c) for inner in f)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
delabel(foo)
|
delabel(foo)
|
||||||
|
|
||||||
|
|
@ -1399,7 +1399,7 @@ of how many labels of each domain it has “seen”.
|
||||||
``unify()`` version 3
|
``unify()`` version 3
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def unify(u, v, s=None):
|
def unify(u, v, s=None):
|
||||||
if s is None:
|
if s is None:
|
||||||
|
|
@ -1449,7 +1449,7 @@ of how many labels of each domain it has “seen”.
|
||||||
|
|
||||||
Rewrite the stack effect comments:
|
Rewrite the stack effect comments:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def defs():
|
def defs():
|
||||||
|
|
||||||
|
|
@ -1503,11 +1503,11 @@ Rewrite the stack effect comments:
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
DEFS = defs()
|
DEFS = defs()
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for name, stack_effect_comment in sorted(DEFS.items()):
|
for name, stack_effect_comment in sorted(DEFS.items()):
|
||||||
print name, '=', doc_from_stack_effect(*stack_effect_comment)
|
print name, '=', doc_from_stack_effect(*stack_effect_comment)
|
||||||
|
|
@ -1543,14 +1543,14 @@ Rewrite the stack effect comments:
|
||||||
uncons = ([a1 .1.] -- a1 [.1.])
|
uncons = ([a1 .1.] -- a1 [.1.])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
globals().update(DEFS)
|
globals().update(DEFS)
|
||||||
|
|
||||||
Compose ``dup`` and ``mul``
|
Compose ``dup`` and ``mul``
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(dup, mul)
|
C(dup, mul)
|
||||||
|
|
||||||
|
|
@ -1565,7 +1565,7 @@ Compose ``dup`` and ``mul``
|
||||||
|
|
||||||
Revisit the ``F`` function, works fine.
|
Revisit the ``F`` function, works fine.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||||
F
|
F
|
||||||
|
|
@ -1579,7 +1579,7 @@ Revisit the ``F`` function, works fine.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print doc_from_stack_effect(*F)
|
print doc_from_stack_effect(*F)
|
||||||
|
|
||||||
|
|
@ -1592,12 +1592,12 @@ Revisit the ``F`` function, works fine.
|
||||||
Some otherwise inefficient functions are no longer to be feared. We can
|
Some otherwise inefficient functions are no longer to be feared. We can
|
||||||
also get the effect of combinators in some limited cases.
|
also get the effect of combinators in some limited cases.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def neato(*funcs):
|
def neato(*funcs):
|
||||||
print doc_from_stack_effect(*reduce(C, funcs))
|
print doc_from_stack_effect(*reduce(C, funcs))
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
# e.g. [swap] dip
|
# e.g. [swap] dip
|
||||||
neato(rollup, swap, rolldown)
|
neato(rollup, swap, rolldown)
|
||||||
|
|
@ -1608,7 +1608,7 @@ also get the effect of combinators in some limited cases.
|
||||||
(a1 a2 a3 -- a2 a1 a3)
|
(a1 a2 a3 -- a2 a1 a3)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
# e.g. [popop] dipd
|
# e.g. [popop] dipd
|
||||||
neato(popdd, rolldown, pop)
|
neato(popdd, rolldown, pop)
|
||||||
|
|
@ -1619,7 +1619,7 @@ also get the effect of combinators in some limited cases.
|
||||||
(a1 a2 a3 a4 -- a3 a4)
|
(a1 a2 a3 a4 -- a3 a4)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
# Reverse the order of the top three items.
|
# Reverse the order of the top three items.
|
||||||
neato(rollup, swap)
|
neato(rollup, swap)
|
||||||
|
|
@ -1636,7 +1636,7 @@ also get the effect of combinators in some limited cases.
|
||||||
Because the type labels represent themselves as valid Python identifiers
|
Because the type labels represent themselves as valid Python identifiers
|
||||||
the ``compile_()`` function doesn’t need to generate them anymore:
|
the ``compile_()`` function doesn’t need to generate them anymore:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def compile_(name, f, doc=None):
|
def compile_(name, f, doc=None):
|
||||||
inputs, outputs = f
|
inputs, outputs = f
|
||||||
|
|
@ -1652,7 +1652,7 @@ the ``compile_()`` function doesn’t need to generate them anymore:
|
||||||
%s = stack
|
%s = stack
|
||||||
return %s''' % (name, doc, i, o)
|
return %s''' % (name, doc, i, o)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print compile_('F', F)
|
print compile_('F', F)
|
||||||
|
|
||||||
|
|
@ -1668,7 +1668,7 @@ the ``compile_()`` function doesn’t need to generate them anymore:
|
||||||
But it cannot magically create new functions that involve e.g. math and
|
But it cannot magically create new functions that involve e.g. math and
|
||||||
such. Note that this is *not* a ``sqr`` function implementation:
|
such. Note that this is *not* a ``sqr`` function implementation:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print compile_('sqr', C(dup, mul))
|
print compile_('sqr', C(dup, mul))
|
||||||
|
|
||||||
|
|
@ -1696,7 +1696,7 @@ The functions that *can* be compiled are the ones that have only
|
||||||
``AnyJoyType`` and ``StackJoyType`` labels in their stack effect
|
``AnyJoyType`` and ``StackJoyType`` labels in their stack effect
|
||||||
comments. We can write a function to check that:
|
comments. We can write a function to check that:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from itertools import imap
|
from itertools import imap
|
||||||
|
|
||||||
|
|
@ -1704,7 +1704,7 @@ comments. We can write a function to check that:
|
||||||
def compilable(f):
|
def compilable(f):
|
||||||
return isinstance(f, tuple) and all(imap(compilable, f)) or stacky(f)
|
return isinstance(f, tuple) and all(imap(compilable, f)) or stacky(f)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for name, stack_effect_comment in sorted(defs().items()):
|
for name, stack_effect_comment in sorted(defs().items()):
|
||||||
if compilable(stack_effect_comment):
|
if compilable(stack_effect_comment):
|
||||||
|
|
@ -1828,7 +1828,7 @@ the “truthiness” of ``StackJoyType`` to false to let e.g.
|
||||||
``joy.utils.stack.concat`` work with our stack effect comment cons-list
|
``joy.utils.stack.concat`` work with our stack effect comment cons-list
|
||||||
tuples.)
|
tuples.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def compose(f, g):
|
def compose(f, g):
|
||||||
(f_in, f_out), (g_in, g_out) = f, g
|
(f_in, f_out), (g_in, g_out) = f, g
|
||||||
|
|
@ -1840,7 +1840,7 @@ tuples.)
|
||||||
I don’t want to rewrite all the defs myself, so I’ll write a little
|
I don’t want to rewrite all the defs myself, so I’ll write a little
|
||||||
conversion function instead. This is programmer’s laziness.
|
conversion function instead. This is programmer’s laziness.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def sequence_to_stack(seq, stack=StackJoyType(23)):
|
def sequence_to_stack(seq, stack=StackJoyType(23)):
|
||||||
for item in seq: stack = item, stack
|
for item in seq: stack = item, stack
|
||||||
|
|
@ -1854,7 +1854,7 @@ conversion function instead. This is programmer’s laziness.
|
||||||
NEW_DEFS['swaack'] = (S[1], S[0]), (S[0], S[1])
|
NEW_DEFS['swaack'] = (S[1], S[0]), (S[0], S[1])
|
||||||
globals().update(NEW_DEFS)
|
globals().update(NEW_DEFS)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(stack, uncons)
|
C(stack, uncons)
|
||||||
|
|
||||||
|
|
@ -1867,7 +1867,7 @@ conversion function instead. This is programmer’s laziness.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
reduce(C, (stack, uncons, uncons))
|
reduce(C, (stack, uncons, uncons))
|
||||||
|
|
||||||
|
|
@ -1887,7 +1887,7 @@ The display function should be changed too.
|
||||||
|
|
||||||
Clunky junk, but it will suffice for now.
|
Clunky junk, but it will suffice for now.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def doc_from_stack_effect(inputs, outputs):
|
def doc_from_stack_effect(inputs, outputs):
|
||||||
switch = [False] # Do we need to display the '...' for the rest of the main stack?
|
switch = [False] # Do we need to display the '...' for the rest of the main stack?
|
||||||
|
|
@ -1935,7 +1935,7 @@ Clunky junk, but it will suffice for now.
|
||||||
a.append(end)
|
a.append(end)
|
||||||
return '[%s]' % ' '.join(a)
|
return '[%s]' % ' '.join(a)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for name, stack_effect_comment in sorted(NEW_DEFS.items()):
|
for name, stack_effect_comment in sorted(NEW_DEFS.items()):
|
||||||
print name, '=', doc_from_stack_effect(*stack_effect_comment)
|
print name, '=', doc_from_stack_effect(*stack_effect_comment)
|
||||||
|
|
@ -1973,7 +1973,7 @@ Clunky junk, but it will suffice for now.
|
||||||
uncons = ([a1 .1.] -- a1 [.1.])
|
uncons = ([a1 .1.] -- a1 [.1.])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print ; print doc_from_stack_effect(*stack)
|
print ; print doc_from_stack_effect(*stack)
|
||||||
print ; print doc_from_stack_effect(*C(stack, uncons))
|
print ; print doc_from_stack_effect(*C(stack, uncons))
|
||||||
|
|
@ -1993,7 +1993,7 @@ Clunky junk, but it will suffice for now.
|
||||||
(... a1 -- ... a1 [a1 ...])
|
(... a1 -- ... a1 [a1 ...])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print doc_from_stack_effect(*C(ccons, stack))
|
print doc_from_stack_effect(*C(ccons, stack))
|
||||||
|
|
||||||
|
|
@ -2003,7 +2003,7 @@ Clunky junk, but it will suffice for now.
|
||||||
(... a2 a1 [.1.] -- ... [a2 a1 .1.] [[a2 a1 .1.] ...])
|
(... a2 a1 [.1.] -- ... [a2 a1 .1.] [[a2 a1 .1.] ...])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
Q = C(ccons, stack)
|
Q = C(ccons, stack)
|
||||||
|
|
||||||
|
|
@ -2024,7 +2024,7 @@ Clunky junk, but it will suffice for now.
|
||||||
This makes the ``compile_()`` function pretty simple as the stack effect
|
This makes the ``compile_()`` function pretty simple as the stack effect
|
||||||
comments are now already in the form needed for the Python code:
|
comments are now already in the form needed for the Python code:
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def compile_(name, f, doc=None):
|
def compile_(name, f, doc=None):
|
||||||
i, o = f
|
i, o = f
|
||||||
|
|
@ -2035,7 +2035,7 @@ comments are now already in the form needed for the Python code:
|
||||||
%s = stack
|
%s = stack
|
||||||
return %s''' % (name, doc, i, o)
|
return %s''' % (name, doc, i, o)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print compile_('Q', Q)
|
print compile_('Q', Q)
|
||||||
|
|
||||||
|
|
@ -2053,12 +2053,12 @@ comments are now already in the form needed for the Python code:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
unstack = (S[1], S[0]), S[1]
|
unstack = (S[1], S[0]), S[1]
|
||||||
enstacken = S[0], (S[0], S[1])
|
enstacken = S[0], (S[0], S[1])
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print doc_from_stack_effect(*unstack)
|
print doc_from_stack_effect(*unstack)
|
||||||
|
|
||||||
|
|
@ -2068,7 +2068,7 @@ comments are now already in the form needed for the Python code:
|
||||||
([.1.] --)
|
([.1.] --)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print doc_from_stack_effect(*enstacken)
|
print doc_from_stack_effect(*enstacken)
|
||||||
|
|
||||||
|
|
@ -2078,7 +2078,7 @@ comments are now already in the form needed for the Python code:
|
||||||
(-- [.0.])
|
(-- [.0.])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print doc_from_stack_effect(*C(cons, unstack))
|
print doc_from_stack_effect(*C(cons, unstack))
|
||||||
|
|
||||||
|
|
@ -2088,7 +2088,7 @@ comments are now already in the form needed for the Python code:
|
||||||
(a1 [.1.] -- a1)
|
(a1 [.1.] -- a1)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
print doc_from_stack_effect(*C(cons, enstacken))
|
print doc_from_stack_effect(*C(cons, enstacken))
|
||||||
|
|
||||||
|
|
@ -2098,7 +2098,7 @@ comments are now already in the form needed for the Python code:
|
||||||
(a1 [.1.] -- [[a1 .1.] .2.])
|
(a1 [.1.] -- [[a1 .1.] .2.])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
C(cons, unstack)
|
C(cons, unstack)
|
||||||
|
|
||||||
|
|
@ -2117,7 +2117,7 @@ Part VI: Multiple Stack Effects
|
||||||
|
|
||||||
…
|
…
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
class IntJoyType(NumberJoyType): prefix = 'i'
|
class IntJoyType(NumberJoyType): prefix = 'i'
|
||||||
|
|
||||||
|
|
@ -2125,7 +2125,7 @@ Part VI: Multiple Stack Effects
|
||||||
F = map(FloatJoyType, _R)
|
F = map(FloatJoyType, _R)
|
||||||
I = map(IntJoyType, _R)
|
I = map(IntJoyType, _R)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
muls = [
|
muls = [
|
||||||
((I[2], (I[1], S[0])), (I[3], S[0])),
|
((I[2], (I[1], S[0])), (I[3], S[0])),
|
||||||
|
|
@ -2134,7 +2134,7 @@ Part VI: Multiple Stack Effects
|
||||||
((F[2], (F[1], S[0])), (F[3], S[0])),
|
((F[2], (F[1], S[0])), (F[3], S[0])),
|
||||||
]
|
]
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for f in muls:
|
for f in muls:
|
||||||
print doc_from_stack_effect(*f)
|
print doc_from_stack_effect(*f)
|
||||||
|
|
@ -2148,7 +2148,7 @@ Part VI: Multiple Stack Effects
|
||||||
(f1 f2 -- f3)
|
(f1 f2 -- f3)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for f in muls:
|
for f in muls:
|
||||||
try:
|
try:
|
||||||
|
|
@ -2164,7 +2164,7 @@ Part VI: Multiple Stack Effects
|
||||||
(a1 -- a1 a1) (f1 f2 -- f3) (f1 -- f2)
|
(a1 -- a1 a1) (f1 f2 -- f3) (f1 -- f2)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from itertools import product
|
from itertools import product
|
||||||
|
|
||||||
|
|
@ -2180,7 +2180,7 @@ Part VI: Multiple Stack Effects
|
||||||
def MC(F, G):
|
def MC(F, G):
|
||||||
return sorted(set(meta_compose(F, G)))
|
return sorted(set(meta_compose(F, G)))
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for f in MC([dup], [mul]):
|
for f in MC([dup], [mul]):
|
||||||
print doc_from_stack_effect(*f)
|
print doc_from_stack_effect(*f)
|
||||||
|
|
@ -2191,7 +2191,7 @@ Part VI: Multiple Stack Effects
|
||||||
(n1 -- n2)
|
(n1 -- n2)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for f in MC([dup], muls):
|
for f in MC([dup], muls):
|
||||||
print doc_from_stack_effect(*f)
|
print doc_from_stack_effect(*f)
|
||||||
|
|
@ -2264,7 +2264,7 @@ Giving us two unifiers:
|
||||||
{c: a, d: b, .1.: .0.}
|
{c: a, d: b, .1.: .0.}
|
||||||
{c: a, d: e, .1.: A* b .0.}
|
{c: a, d: e, .1.: A* b .0.}
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
class KleeneStar(object):
|
class KleeneStar(object):
|
||||||
|
|
||||||
|
|
@ -2314,7 +2314,7 @@ Giving us two unifiers:
|
||||||
|
|
||||||
Can now return multiple results…
|
Can now return multiple results…
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def unify(u, v, s=None):
|
def unify(u, v, s=None):
|
||||||
if s is None:
|
if s is None:
|
||||||
|
|
@ -2386,7 +2386,7 @@ Can now return multiple results…
|
||||||
def stacky(thing):
|
def stacky(thing):
|
||||||
return thing.__class__ in {AnyJoyType, StackJoyType}
|
return thing.__class__ in {AnyJoyType, StackJoyType}
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
a = (As[1], S[1])
|
a = (As[1], S[1])
|
||||||
a
|
a
|
||||||
|
|
@ -2400,7 +2400,7 @@ Can now return multiple results…
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
b = (A[1], S[2])
|
b = (A[1], S[2])
|
||||||
b
|
b
|
||||||
|
|
@ -2414,7 +2414,7 @@ Can now return multiple results…
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for result in unify(b, a):
|
for result in unify(b, a):
|
||||||
print result, '->', update(result, a), update(result, b)
|
print result, '->', update(result, a), update(result, b)
|
||||||
|
|
@ -2426,7 +2426,7 @@ Can now return multiple results…
|
||||||
{a1: a10001, s2: (a1*, s1)} -> (a1*, s1) (a10001, (a1*, s1))
|
{a1: a10001, s2: (a1*, s1)} -> (a1*, s1) (a10001, (a1*, s1))
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for result in unify(a, b):
|
for result in unify(a, b):
|
||||||
print result, '->', update(result, a), update(result, b)
|
print result, '->', update(result, a), update(result, b)
|
||||||
|
|
@ -2446,7 +2446,7 @@ Can now return multiple results…
|
||||||
|
|
||||||
(a1*, s1) [a1*] (a2, (a1*, s1)) [a2 a1*]
|
(a1*, s1) [a1*] (a2, (a1*, s1)) [a2 a1*]
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
sum_ = ((Ns[1], S[1]), S[0]), (N[0], S[0])
|
sum_ = ((Ns[1], S[1]), S[0]), (N[0], S[0])
|
||||||
|
|
||||||
|
|
@ -2458,7 +2458,7 @@ Can now return multiple results…
|
||||||
([n1* .1.] -- n0)
|
([n1* .1.] -- n0)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
f = (N[1], (N[2], (N[3], S[1]))), S[0]
|
f = (N[1], (N[2], (N[3], S[1]))), S[0]
|
||||||
|
|
||||||
|
|
@ -2470,7 +2470,7 @@ Can now return multiple results…
|
||||||
(-- [n1 n2 n3 .1.])
|
(-- [n1 n2 n3 .1.])
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for result in unify(sum_[0], f):
|
for result in unify(sum_[0], f):
|
||||||
print result, '->', update(result, sum_[1])
|
print result, '->', update(result, sum_[1])
|
||||||
|
|
@ -2489,7 +2489,7 @@ Can now return multiple results…
|
||||||
|
|
||||||
This function has to be modified to yield multiple results.
|
This function has to be modified to yield multiple results.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def compose(f, g):
|
def compose(f, g):
|
||||||
(f_in, f_out), (g_in, g_out) = f, g
|
(f_in, f_out), (g_in, g_out) = f, g
|
||||||
|
|
@ -2501,7 +2501,7 @@ This function has to be modified to yield multiple results.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def meta_compose(F, G):
|
def meta_compose(F, G):
|
||||||
for f, g in product(F, G):
|
for f, g in product(F, G):
|
||||||
|
|
@ -2517,7 +2517,7 @@ This function has to be modified to yield multiple results.
|
||||||
for fg in compose(f, g):
|
for fg in compose(f, g):
|
||||||
yield delabel(fg)
|
yield delabel(fg)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for f in MC([dup], muls):
|
for f in MC([dup], muls):
|
||||||
print doc_from_stack_effect(*f)
|
print doc_from_stack_effect(*f)
|
||||||
|
|
@ -2529,7 +2529,7 @@ This function has to be modified to yield multiple results.
|
||||||
(i1 -- i2)
|
(i1 -- i2)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2542,7 +2542,7 @@ This function has to be modified to yield multiple results.
|
||||||
([n1* .1.] -- [n1* .1.] n1)
|
([n1* .1.] -- [n1* .1.] n1)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2556,7 +2556,7 @@ This function has to be modified to yield multiple results.
|
||||||
(n1 [n1* .1.] -- n2)
|
(n1 [n1* .1.] -- n2)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
sum_ = (((N[1], (Ns[1], S[1])), S[0]), (N[0], S[0]))
|
sum_ = (((N[1], (Ns[1], S[1])), S[0]), (N[0], S[0]))
|
||||||
print doc_from_stack_effect(*cons),
|
print doc_from_stack_effect(*cons),
|
||||||
|
|
@ -2571,7 +2571,7 @@ This function has to be modified to yield multiple results.
|
||||||
(a1 [.1.] -- [a1 .1.]) ([n1 n1* .1.] -- n0) (n1 [n1* .1.] -- n2)
|
(a1 [.1.] -- [a1 .1.]) ([n1 n1* .1.] -- n0) (n1 [n1* .1.] -- n2)
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
a = (A[4], (As[1], (A[3], S[1])))
|
a = (A[4], (As[1], (A[3], S[1])))
|
||||||
a
|
a
|
||||||
|
|
@ -2585,7 +2585,7 @@ This function has to be modified to yield multiple results.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
b = (A[1], (A[2], S[2]))
|
b = (A[1], (A[2], S[2]))
|
||||||
b
|
b
|
||||||
|
|
@ -2599,7 +2599,7 @@ This function has to be modified to yield multiple results.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for result in unify(b, a):
|
for result in unify(b, a):
|
||||||
print result
|
print result
|
||||||
|
|
@ -2611,7 +2611,7 @@ This function has to be modified to yield multiple results.
|
||||||
{a1: a4, s2: (a1*, (a3, s1)), a2: a10003}
|
{a1: a4, s2: (a1*, (a3, s1)), a2: a10003}
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
for result in unify(a, b):
|
for result in unify(a, b):
|
||||||
print result
|
print result
|
||||||
|
|
@ -2681,7 +2681,7 @@ We need a type variable for Joy functions that can go in our expressions
|
||||||
and be used by the hybrid inferencer/interpreter. They have to store a
|
and be used by the hybrid inferencer/interpreter. They have to store a
|
||||||
name and a list of stack effects.
|
name and a list of stack effects.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
class FunctionJoyType(AnyJoyType):
|
class FunctionJoyType(AnyJoyType):
|
||||||
|
|
||||||
|
|
@ -2703,14 +2703,14 @@ Specialized for Simple Functions and Combinators
|
||||||
For non-combinator functions the stack effects list contains stack
|
For non-combinator functions the stack effects list contains stack
|
||||||
effect comments (represented by pairs of cons-lists as described above.)
|
effect comments (represented by pairs of cons-lists as described above.)
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
class SymbolJoyType(FunctionJoyType):
|
class SymbolJoyType(FunctionJoyType):
|
||||||
prefix = 'F'
|
prefix = 'F'
|
||||||
|
|
||||||
For combinators the list contains Python functions.
|
For combinators the list contains Python functions.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
class CombinatorJoyType(FunctionJoyType):
|
class CombinatorJoyType(FunctionJoyType):
|
||||||
|
|
||||||
|
|
@ -2731,7 +2731,7 @@ For combinators the list contains Python functions.
|
||||||
For simple combinators that have only one effect (like ``dip``) you only
|
For simple combinators that have only one effect (like ``dip``) you only
|
||||||
need one function and it can be the combinator itself.
|
need one function and it can be the combinator itself.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
import joy.library
|
import joy.library
|
||||||
|
|
||||||
|
|
@ -2741,7 +2741,7 @@ For combinators that can have more than one effect (like ``branch``) you
|
||||||
have to write functions that each implement the action of one of the
|
have to write functions that each implement the action of one of the
|
||||||
effects.
|
effects.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def branch_true(stack, expression, dictionary):
|
def branch_true(stack, expression, dictionary):
|
||||||
(then, (else_, (flag, stack))) = stack
|
(then, (else_, (flag, stack))) = stack
|
||||||
|
|
@ -2771,7 +2771,7 @@ updated along with the stack effects after doing unification or we risk
|
||||||
losing useful information. This was a straightforward, if awkward,
|
losing useful information. This was a straightforward, if awkward,
|
||||||
modification to the call structure of ``meta_compose()`` et. al.
|
modification to the call structure of ``meta_compose()`` et. al.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
ID = S[0], S[0] # Identity function.
|
ID = S[0], S[0] # Identity function.
|
||||||
|
|
||||||
|
|
@ -2833,7 +2833,7 @@ cruft to convert the definitions in ``DEFS`` to the new
|
||||||
``SymbolJoyType`` objects, and some combinators. Here is an example of
|
``SymbolJoyType`` objects, and some combinators. Here is an example of
|
||||||
output from the current code :
|
output from the current code :
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
1/0 # (Don't try to run this cell! It's not going to work. This is "read only" code heh..)
|
1/0 # (Don't try to run this cell! It's not going to work. This is "read only" code heh..)
|
||||||
|
|
||||||
|
|
@ -2956,7 +2956,7 @@ module. But if you’re interested in all that you should just use Prolog!
|
||||||
|
|
||||||
Anyhow, type *checking* is a few easy steps away.
|
Anyhow, type *checking* is a few easy steps away.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
def _ge(self, other):
|
def _ge(self, other):
|
||||||
return (issubclass(other.__class__, self.__class__)
|
return (issubclass(other.__class__, self.__class__)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ Huet <https://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-
|
||||||
Given a datastructure on the stack we can navigate through it, modify
|
Given a datastructure on the stack we can navigate through it, modify
|
||||||
it, and rebuild it using the “zipper” technique.
|
it, and rebuild it using the “zipper” technique.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
from notebook_preamble import J, V, define
|
from notebook_preamble import J, V, define
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ strings, Symbols (strings that are names of functions) and sequences
|
||||||
`trees <https://en.wikipedia.org/wiki/Tree_%28data_structure%29>`__ out
|
`trees <https://en.wikipedia.org/wiki/Tree_%28data_structure%29>`__ out
|
||||||
of sequences.
|
of sequences.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1 [2 [3 4 25 6] 7] 8]')
|
J('[1 [2 [3 4 25 6] 7] 8]')
|
||||||
|
|
||||||
|
|
@ -54,14 +54,14 @@ show the trace so you can see how it works. If we were going to use
|
||||||
these a lot it would make sense to write Python versions for efficiency,
|
these a lot it would make sense to write Python versions for efficiency,
|
||||||
but see below.
|
but see below.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('z-down == [] swap uncons swap')
|
define('z-down == [] swap uncons swap')
|
||||||
define('z-up == swons swap shunt')
|
define('z-up == swons swap shunt')
|
||||||
define('z-right == [swons] cons dip uncons swap')
|
define('z-right == [swons] cons dip uncons swap')
|
||||||
define('z-left == swons [uncons swap] dip swap')
|
define('z-left == swons [uncons swap] dip swap')
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[1 [2 [3 4 25 6] 7] 8] z-down')
|
V('[1 [2 [3 4 25 6] 7] 8] z-down')
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ but see below.
|
||||||
[] [[2 [3 4 25 6] 7] 8] 1 .
|
[] [[2 [3 4 25 6] 7] 8] 1 .
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[] [[2 [3 4 25 6] 7] 8] 1 z-right')
|
V('[] [[2 [3 4 25 6] 7] 8] 1 z-right')
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ but see below.
|
||||||
[1] [8] [2 [3 4 25 6] 7] .
|
[1] [8] [2 [3 4 25 6] 7] .
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [2 [3 4 25 6] 7] z-down')
|
J('[1] [8] [2 [3 4 25 6] 7] z-down')
|
||||||
|
|
||||||
|
|
@ -111,7 +111,7 @@ but see below.
|
||||||
[1] [8] [] [[3 4 25 6] 7] 2
|
[1] [8] [] [[3 4 25 6] 7] 2
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [] [[3 4 25 6] 7] 2 z-right')
|
J('[1] [8] [] [[3 4 25 6] 7] 2 z-right')
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ but see below.
|
||||||
[1] [8] [2] [7] [3 4 25 6]
|
[1] [8] [2] [7] [3 4 25 6]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [2] [7] [3 4 25 6] z-down')
|
J('[1] [8] [2] [7] [3 4 25 6] z-down')
|
||||||
|
|
||||||
|
|
@ -131,7 +131,7 @@ but see below.
|
||||||
[1] [8] [2] [7] [] [4 25 6] 3
|
[1] [8] [2] [7] [] [4 25 6] 3
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [2] [7] [] [4 25 6] 3 z-right')
|
J('[1] [8] [2] [7] [] [4 25 6] 3 z-right')
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ but see below.
|
||||||
[1] [8] [2] [7] [3] [25 6] 4
|
[1] [8] [2] [7] [3] [25 6] 4
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [2] [7] [3] [25 6] 4 z-right')
|
J('[1] [8] [2] [7] [3] [25 6] 4 z-right')
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ but see below.
|
||||||
[1] [8] [2] [7] [4 3] [6] 25
|
[1] [8] [2] [7] [4 3] [6] 25
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [2] [7] [4 3] [6] 25 sqr')
|
J('[1] [8] [2] [7] [4 3] [6] 25 sqr')
|
||||||
|
|
||||||
|
|
@ -161,7 +161,7 @@ but see below.
|
||||||
[1] [8] [2] [7] [4 3] [6] 625
|
[1] [8] [2] [7] [4 3] [6] 625
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[1] [8] [2] [7] [4 3] [6] 625 z-up')
|
V('[1] [8] [2] [7] [4 3] [6] 625 z-up')
|
||||||
|
|
||||||
|
|
@ -184,7 +184,7 @@ but see below.
|
||||||
[1] [8] [2] [7] [3 4 625 6] .
|
[1] [8] [2] [7] [3 4 625 6] .
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [2] [7] [3 4 625 6] z-up')
|
J('[1] [8] [2] [7] [3 4 625 6] z-up')
|
||||||
|
|
||||||
|
|
@ -194,7 +194,7 @@ but see below.
|
||||||
[1] [8] [2 [3 4 625 6] 7]
|
[1] [8] [2 [3 4 625 6] 7]
|
||||||
|
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1] [8] [2 [3 4 625 6] 7] z-up')
|
J('[1] [8] [2 [3 4 625 6] 7] z-up')
|
||||||
|
|
||||||
|
|
@ -210,7 +210,7 @@ but see below.
|
||||||
In Joy we have the ``dip`` and ``infra`` combinators which can “target”
|
In Joy we have the ``dip`` and ``infra`` combinators which can “target”
|
||||||
or “address” any particular item in a Joy tree structure.
|
or “address” any particular item in a Joy tree structure.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra')
|
V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra')
|
||||||
|
|
||||||
|
|
@ -270,13 +270,13 @@ been embedded in a nested series of quoted programs, e.g.:
|
||||||
|
|
||||||
The ``Z`` function isn’t hard to make.
|
The ``Z`` function isn’t hard to make.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
define('Z == [[] cons cons] step i')
|
define('Z == [[] cons cons] step i')
|
||||||
|
|
||||||
Here it is in action in a simplified scenario.
|
Here it is in action in a simplified scenario.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
V('1 [2 3 4] Z')
|
V('1 [2 3 4] Z')
|
||||||
|
|
||||||
|
|
@ -314,7 +314,7 @@ Here it is in action in a simplified scenario.
|
||||||
|
|
||||||
And here it is doing the main thing.
|
And here it is doing the main thing.
|
||||||
|
|
||||||
.. code:: ipython2
|
.. code:: python
|
||||||
|
|
||||||
J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z')
|
J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z')
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue