Functional Programming has many tools and tricks for writing elegant code. Here we see how they can be applied to make interesting patterns.
A round of regular polygons
Let's start with a simple function that makes a ring of n copies of an n-sided regular polygon.
(defn a-round
([n] (a-round n (p-color 0) (p-color 255)))
([n lc fc]
(clock-rotate n (poly 0 0.5 0.4 n
{:stroke lc
:fill fc
:stroke-weight 3}))))
(defn a-round ([n] (a-round n (p-color 0) (p-color 255))) ([n lc fc] (clock-rotate n (poly 0 0.5 0.4 n {:stroke lc :fill fc :stroke-weight 3})))) (let [lc (p-color 140 220 180) fc (p-color 190 255 200 100)] (a-round 8 lc fc))
As described previously, we can place this pattern into a grid.
(defn a-round ([n] (a-round n (p-color 0) (p-color 255))) ([n lc fc] (clock-rotate n (poly 0 0.5 0.4 n {:stroke lc :fill fc :stroke-weight 3})))) (let [lc (p-color 140 220 180) fc (p-color 190 255 200 100)] (grid-layout 4 (repeat (a-round 8 lc fc))))
The nature of repeat
The meaning of this code should be self-evident. But what about the call to repeat?
Layouts such as grid-layout take not just a single pattern to fill the grid, but a list of them. The algorithm starts by generating a sequence of positions to place each 'tile' at. And then runs through the list of positions and the list of patterns and places one pattern at one position. The number of positions is finite, so in Clojure we can pass in an infinite, lazily evaluated list of patterns.
repeat is a function that takes a single item and returns an infinite list of them.
But we can also use cycle to turn finite vector of patterns into an infinite list :
(cycle [(a-round 4) (a-round 8)])
(We also note here that the grid is filled column-wise from left to right.)
(defn a-round ([n] (a-round n (p-color 0) (p-color 255))) ([n lc fc] (clock-rotate n (poly 0 0.5 0.4 n {:stroke lc :fill fc :stroke-weight 3})))) (let [lc (p-color 140 220 180) fc (p-color 190 255 200 100)] (grid-layout 4 (cycle [(a-round 4 lc fc) (a-round 8 lc fc)])))