Thun/docs/2._Library_Examples.rst

981 lines
14 KiB
ReStructuredText

Examples (and some documentation) for the Words in the Library
==============================================================
.. code:: ipython2
from notebook_preamble import J, V
Stack Chatter
=============
This is what I like to call the functions that just rearrange things on
the stack. (One thing I want to mention is that during a hypothetical
compilation phase these "stack chatter" words effectively disappear,
because we can map the logical stack locations to registers that remain
static for the duration of the computation. This remains to be done but
it's "off the shelf" technology.)
``clear``
~~~~~~~~~
.. code:: ipython2
J('1 2 3 clear')
.. parsed-literal::
``dup`` ``dupd``
~~~~~~~~~~~~~~~~
.. code:: ipython2
J('1 2 3 dup')
.. parsed-literal::
1 2 3 3
.. code:: ipython2
J('1 2 3 dupd')
.. parsed-literal::
1 2 2 3
``enstacken`` ``disenstacken`` ``stack`` ``unstack``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(I may have these paired up wrong. I.e. ``disenstacken`` should be
``unstack`` and vice versa.)
.. code:: ipython2
J('1 2 3 enstacken') # Replace the stack with a quote of itself.
.. parsed-literal::
[3 2 1]
.. code:: ipython2
J('4 5 6 [3 2 1] disenstacken') # Unpack a list onto the stack.
.. parsed-literal::
4 5 6 3 2 1
.. code:: ipython2
J('1 2 3 stack') # Get the stack on the stack.
.. parsed-literal::
1 2 3 [3 2 1]
.. code:: ipython2
J('1 2 3 [4 5 6] unstack') # Replace the stack with the list on top.
# The items appear reversed but they are not,
# 4 is on the top of both the list and the stack.
.. parsed-literal::
6 5 4
``pop`` ``popd`` ``popop``
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('1 2 3 pop')
.. parsed-literal::
1 2
.. code:: ipython2
J('1 2 3 popd')
.. parsed-literal::
1 3
.. code:: ipython2
J('1 2 3 popop')
.. parsed-literal::
1
``roll<`` ``rolldown`` ``roll>`` ``rollup``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The "down" and "up" refer to the movement of two of the top three items
(displacing the third.)
.. code:: ipython2
J('1 2 3 roll<')
.. parsed-literal::
2 3 1
.. code:: ipython2
J('1 2 3 roll>')
.. parsed-literal::
3 1 2
``swap``
~~~~~~~~
.. code:: ipython2
J('1 2 3 swap')
.. parsed-literal::
1 3 2
``tuck`` ``over``
~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('1 2 3 tuck')
.. parsed-literal::
1 3 2 3
.. code:: ipython2
J('1 2 3 over')
.. parsed-literal::
1 2 3 2
``unit`` ``quoted`` ``unquoted``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('1 2 3 unit')
.. parsed-literal::
1 2 [3]
.. code:: ipython2
J('1 2 3 quoted')
.. parsed-literal::
1 [2] 3
.. code:: ipython2
J('1 [2] 3 unquoted')
.. parsed-literal::
1 2 3
.. code:: ipython2
V('1 [dup] 3 unquoted') # Unquoting evaluates. Be aware.
.. parsed-literal::
. 1 [dup] 3 unquoted
1 . [dup] 3 unquoted
1 [dup] . 3 unquoted
1 [dup] 3 . unquoted
1 [dup] 3 . [i] dip
1 [dup] 3 [i] . dip
1 [dup] . i 3
1 . dup 3
1 1 . 3
1 1 3 .
List words
==========
``concat`` ``swoncat`` ``shunt``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('[1 2 3] [4 5 6] concat')
.. parsed-literal::
[1 2 3 4 5 6]
.. code:: ipython2
J('[1 2 3] [4 5 6] swoncat')
::
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-22-15579491b615> in <module>()
----> 1 J('[1 2 3] [4 5 6] swoncat')
/home/sforman/Desktop/ArchLayer/System/source/Thun/docs/notebook_preamble.py in J(text, stack, dictionary)
30
31 def J(text, stack=S, dictionary=D):
---> 32 print stack_to_string(run(text, stack, dictionary)[0])
33
34
/home/sforman/Desktop/ArchLayer/System/source/Thun/venv/local/lib/python2.7/site-packages/joy/joy.pyc in run(text, stack, dictionary, viewer)
77 '''
78 expression = text_to_expression(text)
---> 79 return joy(stack, expression, dictionary, viewer)
80
81
/home/sforman/Desktop/ArchLayer/System/source/Thun/venv/local/lib/python2.7/site-packages/joy/joy.pyc in joy(stack, expression, dictionary, viewer)
56 term, expression = expression
57 if isinstance(term, Symbol):
---> 58 term = dictionary[term]
59 stack, expression, dictionary = term(stack, expression, dictionary)
60 else:
KeyError: swoncat
.. code:: ipython2
J('[1 2 3] [4 5 6] shunt')
``cons`` ``swons`` ``uncons``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('1 [2 3] cons')
.. code:: ipython2
J('[2 3] 1 swons')
.. code:: ipython2
J('[1 2 3] uncons')
``first`` ``second`` ``third`` ``rest``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('[1 2 3 4] first')
.. code:: ipython2
J('[1 2 3 4] second')
.. code:: ipython2
J('[1 2 3 4] third')
.. code:: ipython2
J('[1 2 3 4] rest')
``flatten``
~~~~~~~~~~~
.. code:: ipython2
J('[[1] [2 [3] 4] [5 6]] flatten')
``getitem`` ``at`` ``of`` ``drop`` ``take``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``at`` and ``getitem`` are the same function. ``of == swap at``
.. code:: ipython2
J('[10 11 12 13 14] 2 getitem')
.. code:: ipython2
J('[1 2 3 4] 0 at')
.. code:: ipython2
J('2 [1 2 3 4] of')
.. code:: ipython2
J('[1 2 3 4] 2 drop')
.. code:: ipython2
J('[1 2 3 4] 2 take') # reverses the order
``reverse`` could be defines as ``reverse == dup size take``
``remove``
~~~~~~~~~~
.. code:: ipython2
J('[1 2 3 1 4] 1 remove')
``reverse``
~~~~~~~~~~~
.. code:: ipython2
J('[1 2 3 4] reverse')
``size``
~~~~~~~~
.. code:: ipython2
J('[1 1 1 1] size')
``swaack``
~~~~~~~~~~
"Swap stack" swap the list on the top of the stack for the stack, and
put the old stack on top of the new one. Think of it as a context
switch. Niether of the lists/stacks change their order.
.. code:: ipython2
J('1 2 3 [4 5 6] swaack')
``choice`` ``select``
~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 1 choice')
.. code:: ipython2
J('23 9 0 choice')
.. code:: ipython2
J('[23 9 7] 1 select') # select is basically getitem, should retire it?
.. code:: ipython2
J('[23 9 7] 0 select')
``zip``
~~~~~~~
.. code:: ipython2
J('[1 2 3] [6 5 4] zip')
.. code:: ipython2
J('[1 2 3] [6 5 4] zip [sum] map')
Math words
==========
``+`` ``add``
~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 +')
``-`` ``sub``
~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 -')
``*`` ``mul``
~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 *')
``/`` ``div`` ``floordiv`` ``truediv``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 /')
.. code:: ipython2
J('23 -9 truediv')
.. code:: ipython2
J('23 9 div')
.. code:: ipython2
J('23 9 floordiv')
.. code:: ipython2
J('23 -9 div')
.. code:: ipython2
J('23 -9 floordiv')
``%`` ``mod`` ``modulus`` ``rem`` ``remainder``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 %')
``neg``
~~~~~~~
.. code:: ipython2
J('23 neg -5 neg')
pow
~~~
.. code:: ipython2
J('2 10 pow')
``sqr`` ``sqrt``
~~~~~~~~~~~~~~~~
.. code:: ipython2
J('23 sqr')
.. code:: ipython2
J('23 sqrt')
``++`` ``succ`` ``--`` ``pred``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('1 ++')
.. code:: ipython2
J('1 --')
``<<`` ``lshift`` ``>>`` ``rshift``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('8 1 <<')
.. code:: ipython2
J('8 1 >>')
``average``
~~~~~~~~~~~
.. code:: ipython2
J('[1 2 3 5] average')
``range`` ``range_to_zero`` ``down_to_zero``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('5 range')
.. code:: ipython2
J('5 range_to_zero')
.. code:: ipython2
J('5 down_to_zero')
``product``
~~~~~~~~~~~
.. code:: ipython2
J('[1 2 3 5] product')
``sum``
~~~~~~~
.. code:: ipython2
J('[1 2 3 5] sum')
``min``
~~~~~~~
.. code:: ipython2
J('[1 2 3 5] min')
``gcd``
~~~~~~~
.. code:: ipython2
J('45 30 gcd')
``least_fraction``
~~~~~~~~~~~~~~~~~~
If we represent fractions as a quoted pair of integers [q d] this word
reduces them to their ... least common factors or whatever.
.. code:: ipython2
J('[45 30] least_fraction')
.. code:: ipython2
J('[23 12] least_fraction')
Logic and Comparison
====================
``?`` ``truthy``
~~~~~~~~~~~~~~~~
Get the Boolean value of the item on the top of the stack.
.. code:: ipython2
J('23 truthy')
.. code:: ipython2
J('[] truthy') # Python semantics.
.. code:: ipython2
J('0 truthy')
::
? == dup truthy
.. code:: ipython2
V('23 ?')
.. code:: ipython2
J('[] ?')
.. code:: ipython2
J('0 ?')
``&`` ``and``
~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 &')
``!=`` ``<>`` ``ne``
~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('23 9 !=')
| The usual suspects: - ``<`` ``lt`` - ``<=`` ``le``
| - ``=`` ``eq`` - ``>`` ``gt`` - ``>=`` ``ge`` - ``not`` - ``or``
``^`` ``xor``
~~~~~~~~~~~~~
.. code:: ipython2
J('1 1 ^')
.. code:: ipython2
J('1 0 ^')
Miscellaneous
=============
``help``
~~~~~~~~
.. code:: ipython2
J('[help] help')
``parse``
~~~~~~~~~
.. code:: ipython2
J('[parse] help')
.. code:: ipython2
J('1 "2 [3] dup" parse')
``run``
~~~~~~~
Evaluate a quoted Joy sequence.
.. code:: ipython2
J('[1 2 dup + +] run')
Combinators
===========
``app1`` ``app2`` ``app3``
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('[app1] help')
.. code:: ipython2
J('10 4 [sqr *] app1')
.. code:: ipython2
J('10 3 4 [sqr *] app2')
.. code:: ipython2
J('[app2] help')
.. code:: ipython2
J('10 2 3 4 [sqr *] app3')
``anamorphism``
~~~~~~~~~~~~~~~
Given an initial value, a predicate function ``[P]``, and a generator
function ``[G]``, the ``anamorphism`` combinator creates a sequence.
::
n [P] [G] anamorphism
---------------------------
[...]
Example, ``range``:
::
range == [0 <=] [1 - dup] anamorphism
.. code:: ipython2
J('3 [0 <=] [1 - dup] anamorphism')
``branch``
~~~~~~~~~~
.. code:: ipython2
J('3 4 1 [+] [*] branch')
.. code:: ipython2
J('3 4 0 [+] [*] branch')
``cleave``
~~~~~~~~~~
::
... x [P] [Q] cleave
From the original Joy docs: "The cleave combinator expects two
quotations, and below that an item ``x`` It first executes ``[P]``, with
``x`` on top, and saves the top result element. Then it executes
``[Q]``, again with ``x``, and saves the top result. Finally it restores
the stack to what it was below ``x`` and pushes the two results P(X) and
Q(X)."
Note that ``P`` and ``Q`` can use items from the stack freely, since the
stack (below ``x``) is restored. ``cleave`` is a kind of *parallel*
primitive, and it would make sense to create a version that uses, e.g.
Python threads or something, to actually run ``P`` and ``Q``
concurrently. The current implementation of ``cleave`` is a definition
in terms of ``app2``:
::
cleave == [i] app2 [popd] dip
.. code:: ipython2
J('10 2 [+] [-] cleave')
``dip`` ``dipd`` ``dipdd``
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('1 2 3 4 5 [+] dip')
.. code:: ipython2
J('1 2 3 4 5 [+] dipd')
.. code:: ipython2
J('1 2 3 4 5 [+] dipdd')
``dupdip``
~~~~~~~~~~
Expects a quoted program ``[Q]`` on the stack and some item under it,
``dup`` the item and ``dip`` the quoted program under it.
::
n [Q] dupdip == n Q n
.. code:: ipython2
V('23 [++] dupdip *') # N(N + 1)
``genrec`` ``primrec``
~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython2
J('[genrec] help')
.. code:: ipython2
J('3 [1 <=] [] [dup --] [i *] genrec')
``i``
~~~~~
.. code:: ipython2
V('1 2 3 [+ +] i')
``ifte``
~~~~~~~~
::
[predicate] [then] [else] ifte
.. code:: ipython2
J('1 2 [1] [+] [*] ifte')
.. code:: ipython2
J('1 2 [0] [+] [*] ifte')
``infra``
~~~~~~~~~
.. code:: ipython2
V('1 2 3 [4 5 6] [* +] infra')
``loop``
~~~~~~~~
.. code:: ipython2
J('[loop] help')
.. code:: ipython2
V('3 dup [1 - dup] loop')
``map`` ``pam``
~~~~~~~~~~~~~~~
.. code:: ipython2
J('10 [1 2 3] [*] map')
.. code:: ipython2
J('10 5 [[*][/][+][-]] pam')
``nullary`` ``unary`` ``binary`` ``ternary``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run a quoted program enforcing
`arity <https://en.wikipedia.org/wiki/Arity>`__.
.. code:: ipython2
J('1 2 3 4 5 [+] nullary')
.. code:: ipython2
J('1 2 3 4 5 [+] unary')
.. code:: ipython2
J('1 2 3 4 5 [+] binary') # + has arity 2 so this is technically pointless...
.. code:: ipython2
J('1 2 3 4 5 [+] ternary')
``step``
~~~~~~~~
.. code:: ipython2
J('[step] help')
.. code:: ipython2
V('0 [1 2 3] [+] step')
``times``
~~~~~~~~~
.. code:: ipython2
V('3 2 1 2 [+] times')
``b``
~~~~~
.. code:: ipython2
J('[b] help')
.. code:: ipython2
V('1 2 [3] [4] b')
``while``
~~~~~~~~~
::
[predicate] [body] while
.. code:: ipython2
J('3 [0 >] [dup --] while')
``x``
~~~~~
.. code:: ipython2
J('[x] help')
.. code:: ipython2
V('1 [2] [i 3] x') # Kind of a pointless example.
``void``
========
Implements `**Laws of Form**
*arithmetic* <https://en.wikipedia.org/wiki/Laws_of_Form#The_primary_arithmetic_.28Chapter_4.29>`__
over quote-only datastructures (that is, datastructures that consist
soley of containers, without strings or numbers or anything else.)
.. code:: ipython2
J('[] void')
.. code:: ipython2
J('[[]] void')
.. code:: ipython2
J('[[][[]]] void')
.. code:: ipython2
J('[[[]][[][]]] void')