Examples (and some documentation) for the Words in the Library

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

In [132]:
1 2 3 
1 1 3 1 2 3
In [133]:
clear

dup dupd

In [134]:
1 2 3 dup
1 2 3 3
In [135]:
clear

In [136]:
1 2 3 dupd
1 2 2 3
In [137]:
clear

enstacken disenstacken stack unstack

Replace the stack with a quote of itself.

In [138]:
1 2 3 enstacken
[3 2 1]
In [139]:
clear

Unpack a list onto the stack.

4 5 6 [3 2 1] unstack

Get the stack on the stack.

In [140]:
1 2 3 stack
1 2 3 [3 2 1]
In [141]:
clear

Replace the stack with the list on top. The items appear reversed but they are not, is on the top of both the list and the stack.

In [142]:
1 2 3 [4 5 6] disenstacken
6 5 4

pop popd popop

In [143]:
clear
1 2 3 pop
1 2
In [144]:
clear
1 2 3 popd
1 3
In [145]:
clear
1 2 3 popop
1

roll< rolldown roll> rollup

The "down" and "up" refer to the movement of two of the top three items (displacing the third.)

In [146]:
clear
1 2 3 roll<
2 3 1
In [147]:
clear
1 2 3 roll>
3 1 2

swap

In [148]:
clear
1 2 3 swap
1 3 2

tuck over

In [149]:
clear
1 2 3 tuck
1 3 2 3
In [150]:
clear
1 2 3 over
1 2 3 2

unit quoted unquoted

In [151]:
clear
1 2 3 unit
1 2 [3]
In [152]:
clear
1 2 3 quoted
1 [2] 3
In [153]:
clear
1 [2] 3 unquoted
1 2 3

Unquoting evaluates. Be aware.

In [154]:
clear
1 [dup] 3 unquoted
1 1 3

List words

concat swoncat shunt

In [155]:
clear
[1 2 3] [4 5 6] concat
[1 2 3 4 5 6]
In [156]:
clear
[1 2 3] [4 5 6] swoncat
[4 5 6 1 2 3]
In [157]:
clear
[1 2 3] [4 5 6] shunt
[6 5 4 1 2 3]

cons swons uncons

In [158]:
clear
1 [2 3] cons
[1 2 3]
In [159]:
clear
[2 3] 1 swons
[1 2 3]
In [160]:
clear
[1 2 3] uncons
1 [2 3]

first second third rest

In [161]:
clear
[1 2 3 4] first
1
In [162]:
clear
[1 2 3 4] second
2
In [163]:
clear
[1 2 3 4] third
3
In [166]:
clear
[1 2 3 4] rest
[2 3 4]

flatten

In [167]:
clear
[[1] [2 [3] 4] [5 6]] flatten
[1 2 [3] 4 5 6]

getitem at of drop take

at and getitem are the same function. of == swap at

In [168]:
clear
[10 11 12 13 14] 2 getitem
12
In [169]:
clear
[1 2 3 4] 0 at
1
In [170]:
clear
2 [1 2 3 4] of
3
In [171]:
clear
[1 2 3 4] 2 drop
[3 4]
In [172]:
clear
[1 2 3 4] 2 take
[2 1]

take reverses the order.

reverse could be defines as reverse == dup size take

remove

In [173]:
clear
[1 2 3 1 4] 1 remove
[2 3 1 4]

reverse

In [174]:
clear
[1 2 3 4] reverse
[4 3 2 1]

size

In [175]:
clear
[1 1 1 1] size
4

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.

In [176]:
clear
1 2 3 [4 5 6] swaack
6 5 4 [3 2 1]

choice select

In [180]:
clear
23 9 true choice
9
In [181]:
clear
23 9 false choice
23
In [182]:
clear
[23 9 7] 1 select
9

(select is basically getitem, should retire it?)

In [183]:
clear
[23 9 7] 0 select
23

zip

In [184]:
clear
[1 2 3] [6 5 4] zip
[[6 1] [5 2] [4 3]]
In [185]:
clear
[1 2 3] [6 5 4] zip [sum] map
[7 7 7]

Math words

+ add

In [186]:
clear
23 9 +
32

- sub

In [187]:
clear
23 9 -
14

* mul

In [188]:
clear
23 9 *
207

/ div

In [189]:
clear
23 9 /
2
In [191]:
clear
23 9 div
2
In [193]:
clear
23 -9 div
-3

% mod modulus rem remainder

In [195]:
clear
23 9 %
5

neg

In [196]:
clear
23 neg -5 neg
-23 5

pow

In [197]:
clear
2 10 pow
1024

sqr

In [198]:
clear
23 sqr
529

++ succ -- pred

In [199]:
clear
1 ++
2
In [200]:
clear
1 --
0

<< lshift >> rshift

In [201]:
clear
8 1 <<
16
In [202]:
clear
8 1 >>
4

range range_to_zero down_to_zero

In [204]:
clear
5 range
[4 3 2 1 0]
In [205]:
clear
5 range_to_zero
[0 1 2 3 4 5]
In [206]:
clear
5 down_to_zero
5 4 3 2 1 0
In [207]:
clear
[5 down_to_zero] run
[0 1 2 3 4 5]

product

In [208]:
clear
[1 2 3 5] product
30

sum

In [209]:
clear
[1 2 3 5] sum
11

min

In [210]:
clear
[1 2 3 5] min
1

gcd

In [211]:
clear
45 30 gcd
15

Logic and Comparison

? truthy

Get the Boolean value of the item on the top of the stack.

In [216]:
clear
23 bool
true
In [217]:
clear
[] bool
false
In [218]:
clear
0 bool
false
? == dup truthy
In [219]:
clear
23 ?
23 true
In [220]:
clear
[] ?
[] false
In [221]:
clear
0 ?
0 false

& and

In [223]:
clear
true false &
false

!= <> ne

In [224]:
clear
23 9 !=
true

The usual suspects:

  • < lt
  • <= le
  • = eq
  • > gt
  • >= ge
  • not
  • or

Miscellaneous

help

In [228]:
clear
[help] help
==== Help on help ====

Accepts a quoted symbol on the top of the stack and prints its docs.

---- end ( help )


run

Evaluate a quoted Joy sequence.

In [229]:
clear
[1 2 dup + +] run
[5]

Combinators

app1 app2 app3

In [230]:
clear
[app1] help
==== Help on app1 ====

app1 ≡ grba infrst

---- end ( app1 )


In [231]:
clear
10 4 [sqr *] app1
10 160
In [232]:
clear
10 3 4 [sqr *] app2
10 90 160
In [233]:
clear
[app2] help
==== Help on app2 ====

app2 ≡ [grba swap grba swap] dip [infrst] cons ii

---- end ( app2 )


In [234]:
clear
10 2 3 4 [sqr *] app3
160 90 40

(Wait... is that... backwards?)

It should be 40 90 160 shouldn't it?

In [235]:
clear
10 2 3 4 [sqr *] 3 [grabN] codi map reverse disenstacken
40 90 160

Ah! See? It needs reverse in there!

In [236]:
clear
10 2 3 4 5 [sqr *] 4 [grabN] codi map reverse disenstacken
40 90 160 250

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
In [ ]:
J('3 [0 <=] [1 - dup] anamorphism')

branch

In [ ]:
J('3 4 1 [+] [*] branch')
In [ ]:
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
In [ ]:
J('10 2 [+] [-] cleave')

dip dipd dipdd

In [ ]:
J('1 2 3 4 5 [+] dip')
In [ ]:
J('1 2 3 4 5 [+] dipd')
In [ ]:
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
In [ ]:
V('23 [++] dupdip *')  # N(N + 1)

genrec primrec

In [ ]:
J('[genrec] help')
In [ ]:
J('3 [1 <=] [] [dup --] [i *] genrec')

i

In [ ]:
V('1 2 3 [+ +] i')

ifte

[predicate] [then] [else] ifte
In [ ]:
J('1 2 [1] [+] [*] ifte')
In [ ]:
J('1 2 [0] [+] [*] ifte')

infra

In [ ]:
V('1 2 3 [4 5 6] [* +] infra')

loop

In [ ]:
J('[loop] help')
In [ ]:
V('3 dup [1 - dup] loop')

map pam

In [ ]:
J('10 [1 2 3] [*] map')
In [ ]:
J('10 5 [[*][/][+][-]] pam')

nullary unary binary ternary

Run a quoted program enforcing arity.

In [ ]:
J('1 2 3 4 5 [+] nullary')
In [ ]:
J('1 2 3 4 5 [+] unary')
In [ ]:
J('1 2 3 4 5 [+] binary')  # + has arity 2 so this is technically pointless...
In [ ]:
J('1 2 3 4 5 [+] ternary')

step

In [ ]:
J('[step] help')
In [ ]:
V('0 [1 2 3] [+] step')

times

In [ ]:
V('3 2 1 2 [+] times')

b

In [ ]:
J('[b] help')
In [ ]:
V('1 2 [3] [4] b')

while

[predicate] [body] while
In [ ]:
J('3 [0 >] [dup --] while')

x

In [ ]:
J('[x] help')
In [ ]:
V('1 [2] [i 3] x')  # Kind of a pointless example.

void

Implements Laws of Form arithmetic over quote-only datastructures (that is, datastructures that consist soley of containers, without strings or numbers or anything else.)

In [ ]:
J('[] void')
In [ ]:
J('[[]] void')
In [ ]:
J('[[][[]]] void')
In [ ]:
J('[[[]][[][]]] void')