XXIIVV

Rejoice!

Rejoice is a concatenative programming language where data is encoded as multisets and compose by multiplication. Think Fractran, without the rule-searching of rewriting, or a strange Forth in which the program state is unordered.

Basics

The program state is a bag of unordered things, transformations are represented as fractions where the denominator indicates things to remove from the bag, and the numerator, things to add.

The documentation below displays the content of the bag in bold. Multiple instances of things are grouped as thing^count.

( a comment )

red green blue  [yellow red]/blue
red^2 yellow

Evaluation consists of applying fractions in a sequence when their denominators are found.

blue^3        black/pink white/blue red/[blue^2 white]
blue^3        white/blue red/[blue^2 white]
blue^2 white  red/[blue^2 white]
red

A fraction can also put fractions and symbols back in the bag.

x  [y z/y]/x
y  z/y
z

Logic

Here is the implemenation 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

Functions

Functions are symbols that are replaced their body if found in the bag. A definition starts with colon, and ends with a semi-colon. The definition comment indicates the state of the bag before and after the transformation.

: And? ( x y -- bool ) a true/[a x y] false/[a x] false/[a y] false/a ;
x y And?
x y a     true/[a x y] false/[a x] false/[a y] false/a
true      false/[a x] false/[a y] false/a
true      false/[a y] false/a
true      false/a
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.

: Add ( x y -- x^2 ) [x Add]/y ;
x^2 y^3 Add
x^2 y^3      [x Add]/y
x^3 y^2 Add
x^3 y^2      [x Add]/y
x^4 y Add  
x^4 y        [x Add]/y
x^5 Add    
x^5          [x Add]/y
x^5

To find the difference between two symbols, the following recursive function can find the result:

: Sub ( x y -- x|y ) Sub/[x y] ;
x^4 y^2 Sub
x^4 y^2      Sub/[x y]
x^3 y Sub
x^3 y        Sub/[x y]
x^2 Sub
x^2          Sub/[x y]
x^2

To double the value of a symbol:

: Double ( x -- res^2 ) [res^2 Double]/x ;
x^3 Double    
x^3               [res^2 Double]/x
x^2 res^2 Double
x^2 res^2         [res^2 Double]/x
x res^4 Double
x res^4           [res^2 Double]/x
res^6 Double
res^6             [res^2 Double]/x
res^6

Loops

A function can include its own name in the definition, allowing for loops:

: loop ( x -- ) x done/x^4 [x^2 loop]/x ;
x loop
x         done/x^4 [x^2 loop]/x
x         [x^2 loop]/x
x^2 loop
x^2       done/x^4 [x^2 loop]/x
x^2       [x^2 loop]/x
x^3 loop
x^3       done/x^4 [x^2 loop]/x
x^3       [x^2 loop]/x
x^4 loop
x^4       done/x^4 [x^2 loop]/x
done      [x^2 loop]/x
done

This is a first draft of the language, I'm currently working on an implementation. One last thing before I end this, here's a fizzbuzz:

: FizzBuzz ( i -- )
	i^2 f b 
	print-fb/[f^2 b^4] 
	print-f/[f^2] 
	print-b/[b^4] 
	done/[i^100] FizzBuzz/i ;

incoming: fractran bagel