I'm still resonating from the awesome Alpaca Festival I attended a few weeks ago. There were many stimulating ideas there. Not least another presentation by Rocco Lorenzo Modugno and his colleagues. Building on an earlier tak on the tiling pattern notation of Dominique Douat which uses the letters A,B,C and D to represent 4 orientations of a square tile, divided diagonally into black and white triangles. You can build many complex patterns out of such triangles simply by playing with their orientation.

Anyway, inspired by this, I decided to implement something similar in my Patterning library. A simple notation, or "Domain Specific Language" for the orientation of tiles.
But as Patterning is all about composition of smaller patterns into larger ones, I made A,B,C and D represent not simply rotated tiles, but functions to rotate any pattern in one of the four orientations. I then invented a structure I called the Douat.
A Douat is slightly strange and convoluted to explain. But very easy to work with.
Essentially a Douat object starts with a pattern inside it. And we pass it through a series of these "Douatic" transformation functions. Initially it starts taking those transformations and storing copies of its pattern transformed by them. Then when it has collected 4 of these transformed patterns it turns itself into a larger pattern with one of each of these transformed versions of the pattern in each quadrant. If we continue to pass it through the Douatic functions we will be able to play the same game with this first compound.
Let's step through.
If we pass the Douat through the following
A A A A
we will get the same tile repeated in each quadrant.

On the other hand, if we pass it through
A B C D
we get different orientations in each quadrant

If we move to a second row,
A B C D
A A A A
We get that initial compound of four tiles now repeated itself 4 times.

In practice that original compounded pattern made with A B C D has a rotational symmetry so it doesn't matter what orientation we make it. But suppose we make the first level less rotationally symmetric, as in
A B D C

Then
A B D C
A A A A
will look like

But
A B D C
A B C D
will look like

And we can keep going as long as we like.
We can supplement the rotations with reflections : horizontal, vertical and both. These are defined as the functions E, G and F respectively. This gives us a wider vocabulary of transformations to play with.
We can start with a simple A E G F combination. As in

and build it into complex patterns like

with
A E G F
A B C D
A B F B
C F C D
The first pattern on this page is made with :
A E E A
A B C D
A E G F
A A A A
Because this is Patterning, we aren't restricted to just the Truchet triangle tiles. Any pattern can work. So we can start with any simple tile and build it into something beautiful.

Here's the fairly short code implementation of the Douat itself.
(defn Douat [p]
{:p p
:ps []
:depth 0}
)
(defn add-douat [f]
(fn [{:keys [p ps depth]}]
(if (< (count ps) 3)
{:p p
:ps (concat ps [(f p)])
:depth depth
}
(let [q
(stack
(->> (nth ps 0) (scale 0.5) (translate -0.5 -0.5))
(->> (nth ps 1) (scale 0.5) (translate 0.5 -0.5))
(->> (nth ps 2) (scale 0.5) (translate 0.5 0.5))
(->> (f p) (scale 0.5) (translate -0.5 0.5))
)]
{:ps []
:p q
:depth (+ 1 depth)
}))))
(def A (add-douat identity))
(def B (add-douat (fn [p] (rotate (/ PI 2) p))))
(def C (add-douat (fn [p] (rotate PI p))))
(def D (add-douat (fn [p] (rotate (* 3 (/ PI 2)) p))))
(def E (add-douat (fn [p] (h-reflect p))))
(def F (add-douat (fn [p] (v-reflect p))))
(def G (add-douat (fn [p] (-> p (h-reflect) (v-reflect)))))
(defn R [douat]
((rand-nth [A B C D]) douat))
(defn Q [douat]
((rand-nth [A B C D E F G]) douat))
The implementation consists of defining a Douat itself. It's a simple map or dictionary with three fields : :p is the current pattern, :ps is the list of the next collection of patterns we are building up. And :depth is a depth tracker. The Douat function creates that map from an initial pattern.
The functionality of the Douat is encapsulated in the function add-douat which is not intended to be used directly but which is a higher-order function that adapts any function that transforms a normal pattern, into a function which works on a Douat-wrapped version of the pattern.
This allows us to use it in the Douat world. Is it like a "monad"? It not really a monad, but it's kinda that way of thinking. We want to make a bunch of functions composable into a pipeline where they all receive and return Douats.
So when we call a Douatic function on a Douat it does one of two things.
If we haven't yet collected four new pieces of pattern, it just applies the wrapped transformation to the Douat's current pattern, and appends it to the list that's building up at the :ps key. And returns the Douat
If it is passing through the fourth Douatic function in the sequence, it now creates a new pattern with one of the transformations of the old pattern in each quadrant and makes this the new pattern at :p. And then it wipes the :ps list to start collecting four more transformations.
So as the Douat passes through a pipeline of Douatic functions it collects them into groups of four, using each to make one quadrant of a new pattern. And this is indefinitely recursive, to build up increasingly complex patterns of more and more tiles.
The functions we currently create are the orginal A, B, C and D inspired by Douat's notation. We then extend this with E, F and G which are reflections (as opposed to rotations). And R and Q which randomly choose one of the others.
Why do we use such short cryptic names? Because this lets us write code like this :
(def my-tile
(stack
(square {:fill (p-color 90 0 0)})
[(->SShape
{:fill (p-color 0)
:stroke-weight 1
:stroke (p-color 255 255 0)}
[[1 1] [-1 1] [-1 -1] [1 0]])]))
(-> my-tile
Douat
A E E A
A B C D
A E E A
B E E B
(:p)
)
Here we create the initial tile with standard Patterning functions.
Then we use the threading macro to make the simple pipeline that will send the pattern first through the Douat function to wrap it as a Douat. Then through a series of Douatic functions. Because these are single letter names we can just group them in lines of 4 to make them intelligible.
Finally we want to extract the end pattern from the Douat wrapper, this is what the (:p) does.
In practice we could wrap any of Patterning's functions that transform patterns to work in this Douatic way.
You can play with the Douat within the Patterning Workbench on my Alchemy Islands site.
The nice thing about the Douat is not just that it gives us a very powerful and concise way to make a lot of quite beautiful patterns. But that the implementation turns out to be so simple and elegant. Inventing it has taught and inspired me a lot about the power of functional thinking. You can imagine building up many other expressive DSLs this way in Clojure. The fluent "MailQuery" library I wrote in Python recently has some similarities. But this one I really find cool.