Archive for August, 2012

I discovered an interesting trick today which I thought worth sharing – you can add a side effect to the end of a sequence in Clojure which will only get called after the sequence is fully consumed for the first time.


(defmacro on-consumed [seq code]
  `(lazy-cat ~seq (do ~code nil)))

(def coll
     (on-consumed [1 2 3] (println "DONE")))

(take 2 coll)   ;; not fully consumed
=> (1 2)

(take 3 coll)   ;; not fully consumed (not gone past third item)
=> (1 2 3)

(take 4 coll)   ;; fully consumed past end of sequence
=> (1 2 3)
DONE            ;; printed to *out*

(take 4 coll)   ;; fully consumed for second time, no side effect
=> (1 2 3)

So how does this work?

(more…)

Voronoi fishing net fractal

Posted: August 30, 2012 in Uncategorized

Another creative fractal design: this time using layered Voronoi patterns:

(show (let [voronoi1 (voronoi :points 32)]
  (fractal
    :while (v- 0.97 (voronoi-function
             (v- 1 (v* (vdivide (v- y x) y) (vdivide (v- z x) z)))
    :voronoi voronoi1))
    :update (v+ (v* pos 2) pos)
    :result (vdivide 3 (v+ 3 'i))
    :max-iterations 4)) 512 512)

 

(more…)

Mandelbrot fractals

Posted: August 30, 2012 in clisk
Tags: , , ,

I’ve added a new fractal generating function to Clisk. It’s pretty general purpose and can handle all kinds of iterative fractals.

Here’s the classic mandelbrot:

(show (viewport [-2 -1.5] [1 1.5]
  (fractal
    :while (v- 2 (length [x y]))
    :update (v+ c [(v- (v* x x) (v* y y)) (v* 2 x y)])
    :result (vplasma (v* 0.1 'i))
    :bailout-result black
    :max-iterations 1000)) 1024 1024)

Mandelbrot

I’m pretty happy with the little fractal DSL which is implemented using keyword arguments. You can control pretty much every aspect of the iterative procedure used to create the fractal. There are some handy shortcuts you can use in your formulae:

  • x, y, z, t – the current co-ordinates in space that gets updated in each iteration
  • pos – the current co-ordinate vector
  • c – the initial co-orinate vector (i.e. equal to pos on the first iteration)
  • ‘i – the iteration number. Note this is a symbol, I might make this into a function in the future for convenient to avoid the quote but you need it for now

For example, by tweaking the :result formula you can easily create some interesting fractal patterns:

(show (viewport [-2 -1.5] [1 1.5]
  (fractal
    :while (v- 2 (length [x y]))
    :update (v+ c [(v- (v* x x) (v* y y)) (v* 2 x y)])
    :result (v* (rgb-from-hsl [(v* 0.13 'i) 0.8 0.8])
                (scale 1.5 (checker black white)))
    :bailout-result black
    :max-iterations 1000)) 512 512)

Performance is also looking good – the image above took around 3secs to render on my machine. It’s amazing how much hardware has progressed – I still remember the days when I had to leave my Atari 800XL running overnight to get a low resolution mandelbrot image!

Clojure performs exceptionally well considering it is a dynamic language.

My rule of thumb is:

  • It’s 5-10x slower than optimised Java if you write idiomatic Clojure (with liberal use of higher order functions, lazy sequences and all that goodness)
  • It’s about the same speed as Java if you really optimise hard – you can basically generate approximately the same JVM bytecode.

This StackOverflow question prompted me to write a quicksort implementation in Clojure, which I’ve included here to demonstrate that matching Java speed is entirely possible within Clojure.

Warning against premature optimisation:¬†this is not pretty code. You shouldn’t be writing code like this unless you have profiled your code and identified a real performance issue.

(more…)

The sequence abstraction brings me much joy.

In honour of this humble construct I thought I’d write a quick blog post: covering what it is and some examples of how elegant it can make your Clojure code.

(more…)

I see this question debated hotly in various forums, so I thought that it was worth addressing. Mostly in the name of dispelling some myths, but also to highlight what I feel are the most crucial foundations of functional programming.

And also because I think that definitions are important. They are central to both how we think and how we communicate.

(more…)

Truthiness tricks

Posted: August 20, 2012 in Uncategorized
Tags: , , ,

In Clojure, any value can be considered as “truthy” or “falsey” for the purposes of a conditional expression.

The rule is very simple:

  • nil and false ¬†– are “falsey”
  • everything else – is considered “truthy”

This rule may seem strange if you come from a world with a strictly defined boolean type (like Java). But it turns out that it enables some neat tricks in Clojure code that are well worth knowing.

(more…)