I decided to start easy and just write some simple functions that I will eventually need in calculating ray traced images: dot product and cross product.

(ns cltrace.math)
(defn dot
"Returns the value of dot product of the vectors v1 and v2"
[v1 v2] (reduce + (map * v1 v2)))
(defn cross
"Return the cross product of vectors v1 and v2"
[v1 v2] [(- (* (v1 1) (v2 2)) (* (v1 2) (v2 1)))
(- (* (v1 2) (v2 0)) (* (v1 0) (v2 2)))
(- (* (v1 0) (v2 1)) (* (v1 1) (v2 0)))])

defn is a macro that is used to define a function. Here I’m defining two functions doc and cross for calculating dot and cross product respectively. First parameter is name of the function, second is optional string used for documentation, third one is a vector defining input parameters the function will accept and the last one is the actual function.

map function applies function to sequences, returning a sequence. For example (map * [1 2 3] [4 5 6]) will result [1*4 2*5 3*6], which equals to [4 10 18].

reduce function will apply function sequentially to elements of a sequence. For example (reduce + [4 10 18]) will perform [4 + 10 18] -> [14 + 18] -> 32.

Combine these two functions and you get a really pretty looking function to calculate dot product of two vectors that can be arbitrary long.

To test these two functions, I wrote some simple unit tests:

(ns cltrace.math-test
(:use clojure.test
cltrace.math))
(deftest test-dot-length-3
(is (= 29 (dot [2 3 4] [2 3 4]))))
(deftest test-dot-lentgh-1
(is (= 4 (dot [2] [2]))))
(deftest test-cross-simple
(is (= [-1 2 -1] (cross [1 2 3] [2 3 4]))))

That’s not that many lines of code, but it’s a start. I can tell that it’s really different way of looking code and structuring a program. When I get more comfortable with the language, I should go and try writing a minimum viable product. That would basically be a program that can save a picture of unshaded, mono-coloured sphere into a file.