1 Examples (and some documentation) for the Words in the Library
2 ==============================================================
6 from notebook_preamble import J, V
11 This is what I like to call the functions that just rearrange things on
12 the stack. (One thing I want to mention is that during a hypothetical
13 compilation phase these "stack chatter" words effectively disappear,
14 because we can map the logical stack locations to registers that remain
15 static for the duration of the computation. This remains to be done but
16 it's "off the shelf" technology.)
54 ``enstacken`` ``disenstacken`` ``stack`` ``unstack``
55 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57 Replace the stack with a quote of itself.
69 Unpack a list onto the stack.
73 J('4 5 6 [3 2 1] unstack')
81 Get the stack on the stack.
93 Replace the stack with the list on top. The items appear reversed but
94 they are not, is on the top of both the list and the stack.
98 J('1 2 3 [4 5 6] disenstacken')
106 ``pop`` ``popd`` ``popop``
107 ~~~~~~~~~~~~~~~~~~~~~~~~~~
139 ``roll<`` ``rolldown`` ``roll>`` ``rollup``
140 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142 The "down" and "up" refer to the movement of two of the top three items
143 (displacing the third.)
201 ``unit`` ``quoted`` ``unquoted``
202 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
226 J('1 [2] 3 unquoted')
236 V('1 [dup] 3 unquoted') # Unquoting evaluates. Be aware.
256 ``concat`` ``swoncat`` ``shunt``
257 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261 J('[1 2 3] [4 5 6] concat')
271 J('[1 2 3] [4 5 6] swoncat')
281 J('[1 2 3] [4 5 6] shunt')
289 ``cons`` ``swons`` ``uncons``
290 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
322 ``first`` ``second`` ``third`` ``rest``
323 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
337 J('[1 2 3 4] second')
370 J('[[1] [2 [3] 4] [5 6]] flatten')
378 ``getitem`` ``at`` ``of`` ``drop`` ``take``
379 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
381 ``at`` and ``getitem`` are the same function. ``of == swap at``
385 J('[10 11 12 13 14] 2 getitem')
415 J('[1 2 3 4] 2 drop')
425 J('[1 2 3 4] 2 take') # reverses the order
433 ``reverse`` could be defines as ``reverse == dup size take``
440 J('[1 2 3 1 4] 1 remove')
453 J('[1 2 3 4] reverse')
477 "Swap stack" swap the list on the top of the stack for the stack, and
478 put the old stack on top of the new one. Think of it as a context
479 switch. Niether of the lists/stacks change their order.
483 J('1 2 3 [4 5 6] swaack')
491 ``choice`` ``select``
492 ~~~~~~~~~~~~~~~~~~~~~
516 J('[23 9 7] 1 select') # select is basically getitem, should retire it?
526 J('[23 9 7] 0 select')
539 J('[1 2 3] [6 5 4] zip')
549 J('[1 2 3] [6 5 4] zip [sum] map')
599 ``/`` ``div`` ``floordiv`` ``truediv``
600 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
662 ``%`` ``mod`` ``modulus`` ``rem`` ``remainder``
663 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
724 ``++`` ``succ`` ``--`` ``pred``
725 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
747 ``<<`` ``lshift`` ``>>`` ``rshift``
748 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
775 J('[1 2 3 5] average')
783 ``range`` ``range_to_zero`` ``down_to_zero``
784 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
821 J('[1 2 3 5] product')
871 If we represent fractions as a quoted pair of integers [q d] this word
872 reduces them to their ... least common factors or whatever.
876 J('[45 30] least_fraction')
886 J('[23 12] least_fraction')
900 Get the Boolean value of the item on the top of the stack.
914 J('[] truthy') # Python semantics.
996 | The usual suspects: - ``<`` ``lt`` - ``<=`` ``le``
997 | - ``=`` ``eq`` - ``>`` ``gt`` - ``>=`` ``ge`` - ``not`` - ``or``
1036 ==== Help on help ====
1038 Accepts a quoted symbol on the top of the stack and prints its docs.
1056 ==== Help on parse ====
1058 Parse the string on the stack to a Joy expression.
1067 J('1 "2 [3] dup" parse')
1078 Evaluate a quoted Joy sequence.
1082 J('[1 2 dup + +] run')
1093 ``app1`` ``app2`` ``app3``
1094 ~~~~~~~~~~~~~~~~~~~~~~~~~~
1104 ==== Help on app1 ====
1106 Given a quoted program on TOS and anything as the second stack item run
1107 the program and replace the two args with the first result of the
1112 -----------------------------------
1113 ... [x ...] [Q] . infra first
1122 J('10 4 [sqr *] app1')
1132 J('10 3 4 [sqr *] app2')
1148 ==== Help on app2 ====
1150 Like app1 with two items.
1154 -----------------------------------
1155 ... [y ...] [Q] . infra first
1156 [x ...] [Q] infra first
1165 J('10 2 3 4 [sqr *] app3')
1176 Given an initial value, a predicate function ``[P]``, and a generator
1177 function ``[G]``, the ``anamorphism`` combinator creates a sequence.
1181 n [P] [G] anamorphism
1182 ---------------------------
1189 range == [0 <=] [1 - dup] anamorphism
1193 J('3 [0 <=] [1 - dup] anamorphism')
1206 J('3 4 1 [+] [*] branch')
1216 J('3 4 0 [+] [*] branch')
1229 ... x [P] [Q] cleave
1231 From the original Joy docs: "The cleave combinator expects two
1232 quotations, and below that an item ``x`` It first executes ``[P]``, with
1233 ``x`` on top, and saves the top result element. Then it executes
1234 ``[Q]``, again with ``x``, and saves the top result. Finally it restores
1235 the stack to what it was below ``x`` and pushes the two results P(X) and
1238 Note that ``P`` and ``Q`` can use items from the stack freely, since the
1239 stack (below ``x``) is restored. ``cleave`` is a kind of *parallel*
1240 primitive, and it would make sense to create a version that uses, e.g.
1241 Python threads or something, to actually run ``P`` and ``Q``
1242 concurrently. The current implementation of ``cleave`` is a definition
1243 in terms of ``app2``:
1247 cleave == [i] app2 [popd] dip
1251 J('10 2 [+] [-] cleave')
1259 ``dip`` ``dipd`` ``dipdd``
1260 ~~~~~~~~~~~~~~~~~~~~~~~~~~
1264 J('1 2 3 4 5 [+] dip')
1274 J('1 2 3 4 5 [+] dipd')
1284 J('1 2 3 4 5 [+] dipdd')
1295 Expects a quoted program ``[Q]`` on the stack and some item under it,
1296 ``dup`` the item and ``dip`` the quoted program under it.
1300 n [Q] dupdip == n Q n
1304 V('23 [++] dupdip *') # N(N + 1)
1318 ``genrec`` ``primrec``
1319 ~~~~~~~~~~~~~~~~~~~~~~
1329 ==== Help on genrec ====
1331 General Recursion Combinator.
1334 [if] [then] [rec1] [rec2] genrec
1335 ---------------------------------------------------------------------
1336 [if] [then] [rec1 [[if] [then] [rec1] [rec2] genrec] rec2] ifte
1338 From "Recursion Theory and Joy" (j05cmp.html) by Manfred von Thun:
1339 "The genrec combinator takes four program parameters in addition to
1340 whatever data parameters it needs. Fourth from the top is an if-part,
1341 followed by a then-part. If the if-part yields true, then the then-part
1342 is executed and the combinator terminates. The other two parameters are
1343 the rec1-part and the rec2-part. If the if-part yields false, the
1344 rec1-part is executed. Following that the four program parameters and
1345 the combinator are again pushed onto the stack bundled up in a quoted
1346 form. Then the rec2-part is executed, where it will find the bundled
1347 form. Typically it will then execute the bundled form, either with i or
1348 with app2, or some other combinator."
1350 The way to design one of these is to fix your base case [then] and the
1351 test [if], and then treat rec1 and rec2 as an else-part "sandwiching"
1352 a quotation of the whole function.
1354 For example, given a (general recursive) function 'F':
1357 F == [I] [T] [R1] [R2] genrec
1359 If the [I] if-part fails you must derive R1 and R2 from:
1364 Just set the stack arguments in front, and figure out what R1 and R2
1365 have to do to apply the quoted [F] in the proper way. In effect, the
1366 genrec combinator turns into an ifte combinator with a quoted copy of
1367 the original definition in the else-part:
1370 F == [I] [T] [R1] [R2] genrec
1371 == [I] [T] [R1 [F] R2] ifte
1373 Primitive recursive functions are those where R2 == i.
1376 P == [I] [T] [R] tailrec
1377 == [I] [T] [R [P] i] ifte
1378 == [I] [T] [R P] ifte
1387 J('3 [1 <=] [] [dup --] [i *] genrec')
1420 [predicate] [then] [else] ifte
1424 J('1 2 [1] [+] [*] ifte')
1434 J('1 2 [0] [+] [*] ifte')
1447 V('1 2 3 [4 5 6] [* +] infra')
1452 • 1 2 3 [4 5 6] [* +] infra
1453 1 • 2 3 [4 5 6] [* +] infra
1454 1 2 • 3 [4 5 6] [* +] infra
1455 1 2 3 • [4 5 6] [* +] infra
1456 1 2 3 [4 5 6] • [* +] infra
1457 1 2 3 [4 5 6] [* +] • infra
1458 6 5 4 • * + [3 2 1] swaack
1459 6 20 • + [3 2 1] swaack
1476 ==== Help on loop ====
1478 Basic loop combinator.
1482 -----------------------
1486 ------------------------
1496 V('3 dup [1 - dup] loop')
1501 • 3 dup [1 - dup] loop
1502 3 • dup [1 - dup] loop
1503 3 3 • [1 - dup] loop
1504 3 3 [1 - dup] • loop
1505 3 • 1 - dup [1 - dup] loop
1506 3 1 • - dup [1 - dup] loop
1507 2 • dup [1 - dup] loop
1508 2 2 • [1 - dup] loop
1509 2 2 [1 - dup] • loop
1510 2 • 1 - dup [1 - dup] loop
1511 2 1 • - dup [1 - dup] loop
1512 1 • dup [1 - dup] loop
1513 1 1 • [1 - dup] loop
1514 1 1 [1 - dup] • loop
1515 1 • 1 - dup [1 - dup] loop
1516 1 1 • - dup [1 - dup] loop
1517 0 • dup [1 - dup] loop
1518 0 0 • [1 - dup] loop
1519 0 0 [1 - dup] • loop
1528 J('10 [1 2 3] [*] map')
1538 J('10 5 [[*][/][+][-]] pam')
1546 ``nullary`` ``unary`` ``binary`` ``ternary``
1547 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1549 Run a quoted program enforcing
1550 `arity <https://en.wikipedia.org/wiki/Arity>`__.
1554 J('1 2 3 4 5 [+] nullary')
1564 J('1 2 3 4 5 [+] unary')
1574 J('1 2 3 4 5 [+] binary') # + has arity 2 so this is technically pointless...
1584 J('1 2 3 4 5 [+] ternary')
1603 ==== Help on step ====
1605 Run a quoted program on each item in a sequence.
1609 -----------------------
1614 ------------------------
1618 ... [a b c] [Q] . step
1619 ----------------------------------------
1620 ... a . Q [b c] [Q] step
1622 The step combinator executes the quotation on each member of the list
1623 on top of the stack.
1632 V('0 [1 2 3] [+] step')
1637 • 0 [1 2 3] [+] step
1638 0 • [1 2 3] [+] step
1639 0 [1 2 3] • [+] step
1640 0 [1 2 3] [+] • step
1641 0 1 [+] • i [2 3] [+] step
1642 0 1 • + [2 3] [+] step
1646 1 2 [+] • i [3] [+] step
1647 1 2 • + [3] [+] step
1661 V('3 2 1 2 [+] times')
1672 3 2 1 • + 1 [+] times
1697 ... [P] [Q] b == ... [P] i [Q] i
1698 ... [P] [Q] b == ... P Q
1727 [predicate] [body] while
1731 J('3 [0 >] [dup --] while')
1756 ... [Q] x = ... [Q] dup i
1757 ... [Q] x = ... [Q] [Q] i
1758 ... [Q] x = ... [Q] Q
1767 V('1 [2] [i 3] x') # Kind of a pointless example.
1787 Implements `**Laws of Form**
1788 *arithmetic* <https://en.wikipedia.org/wiki/Laws_of_Form#The_primary_arithmetic_.28Chapter_4.29>`__
1789 over quote-only datastructures (that is, datastructures that consist
1790 soley of containers, without strings or numbers or anything else.)
1824 J('[[[]][[][]]] void')