XXIIVV

Rejoice!

Rejoice is a concatenative programming language and notation where data is encoded as multisets that compose by multiplication. Think Fractran, without the rule-searching, or Forth without a stack.

Basics

Multiple instances of things are grouped as thing^count. The empty bag, or identity, is represented as [].

Evaluation consists of applying fractions in a sequence when their denominators are found in the bag. The program halts when there are no more fractions left to apply.

blue^3 red           cyan/pink red [cyan^2]/red red/[blue^2 cyan]
blue^3 red           red [cyan^2]/red red/[blue^2 cyan]
blue^3 red^2         [cyan^2]/red red/[blue^2 cyan]
blue^3 red cyan^2    red/[blue^2 cyan]
blue red^2 cyan

Logic I

Here is the implementation of a NOT logic gate.

false not  true/[false not] false/[true not]
true       false/[true not]
true
true not  true/[false not] false/[true not]
true not  false/[true not]
false

The different handlers are sequenced one after the other, here is a OR gate. Notice the need for a sentinel or symbol.

x y or  true/[x y or] true/[x or] true/[y or] false/or
true    true/[x or] true/[y or] false/or
true    true/[y or] false/or
true    false/or
true
or     true/[x y or] true/[x or] true/[y or] false/or
or     true/[x or] true/[y or] false/or
or     true/[y or] false/or
or     false/or
false

Loops

A @label is a special symbol that holds an address that is jumped to upon entering the bag. This documentation will capitalize the labels to make them explicit, but it is merely a convention. Here is a how a simple loop is created:

times^5
@Loop ( t -- )
	Loop/times
done
[times^5] Loop/times 
[times^4] Loop/times 
[times^3] Loop/times 
[times^2] Loop/times 
[times] Loop/times 
[] Loop/times 
[]

If two or more functions are called at once, the interpreter may choose to evaluated them non-deterministically, throw an error or evaluate them in symbolic order.

Logic II

Here is the implementation of a greater comparison.

x^3 y^2
@Gth ( x y -- x y true/false )
	Gth/[x y]
	true/x Gth/x
	false/y Gth/y
[x^3 y^2] Gth/[x y] true/x Gth/x false/y Gth/y 
[x^2 y] Gth/[x y] true/x Gth/x false/y Gth/y 
[x] Gth/[x y] true/x Gth/x false/y Gth/y 
[x] true/x Gth/x false/y Gth/y 
[true] Gth/x false/y Gth/y 
[true] false/y Gth/y 
[true] Gth/y 
[true]

Arithmetic

The function [x Add]/y drains y into x and calls itself again for as long as y is in the bag, effectively finding the sum by resource transfer.

x^3 y^4
@Add ( x y -- xres )
	[x Add]/y
[x^3 y^4] [x add]/y 
[x^4 y^3] [x add]/y 
[x^5 y^2] [x add]/y 
[x^6 y] [x add]/y 
[x^7] [x add]/y 
[x^7]

To find the difference between two symbols, the program can take out one of each symbol until exhaustion, leaving either x for a positive result, or y for a negative result. The following recursive function can find the result:

x^5 y^3
@Sub ( x y -- xres )
	Sub/[x y]
[x^5 y^3] Sub/[x y] 
[x^4 y^2] Sub/[x y] 
[x^3 y] Sub/[x y] 
[x^2] Sub/[x y] 
[x^2]

Relationship to Fractran

A Fractran program can be thought of as a Rejoice program with a single label at the top. For example, the Fractran program: 225, 7/3, 7/5

r3^2 r5^2
@Fractran ( r3 r5 -- r3+r5.r7 )
	[Fractran r7]/r3
	[Fractran r7]/r5
[r3^2 r5^2] [Fractran r7]/r3 [Fractran r7]/r5 
[r3 r5^2 r7] [Fractran r7]/r3 [Fractran r7]/r5 
[r5^2 r7^2] [Fractran r7]/r3 [Fractran r7]/r5 
[r5^2 r7^2] [Fractran r7]/r5 
[r5 r7^3] [Fractran r7]/r3 [Fractran r7]/r5 
[r5 r7^3] [Fractran r7]/r5 
[r7^4] [Fractran r7]/r3 [Fractran r7]/r5 
[r7^4] [Fractran r7]/r5 
[r7^4]

incoming: tropical arithmetic fractran bagel 2026