Pramode C.E - Code Clojure2010-06-06T05:55:56+00:00http://pramode.net/clojure/Pramode C.Email@pramode.netFun with Fourier series, Clojure lazy sequences and Incanter2010-06-06T00:00:00+00:00http://pramode.net/clojure/2010/06/06/fourier-clojure-incanter<h2>Fun with Fourier series, Clojure lazy sequences and Incanter</h2>
<p><em> Jun 6, 2010</em></p>
<p>
The fourier series expansion of a square wave is given by:
<pre>
sin(x) + (1/3)sin(3x) + (1/5)sin(5x) + ...
</pre>
<p>
Let's try to generate (and plot) this series in Clojure.
<p>
We need to install a program called `Incanter' to generate plots; Incanter is an
R-like statistical computing environment for Clojure; you can download it from
<a href="http://incanter.org/downloads/incanter-latest.zip">here</a>. The downloaded
zip archive is self-contained - you need not install anything else to run Incanter.
Just unzip the package, change into the `incanter' directory and start the Clojure
REPL by running a script called `script/repl'. You can test the installation by
executing this code fragment:
<pre>
user=> (use '(incanter core charts stats))
user=> (def x (range 0 6.28 0.01))
user=> (def y (map sin x))
user=> (view (xy-plot x y))
</pre>
<p>
We have plotted the first term of the fourier expansion - a simple sin curve!
<p>
What does the following code fragment do?
<pre>
(defn seq-mul [n s]
(map (fn [x] (* n x)) s))
</pre>
<p>
It takes a number `n' and a sequence `s' and returns another sequence each
element of which is multiplied by `n'.
<p>
Here is a function which will add two sequences:
<pre>
(defn seq-add [a b]
(map + a b))
</pre>
<p>
We need a list of odd numbers:
<pre>
(def odds (iterate #(+ % 2) 1))
</pre>
<p>
Now we can generate the sequence: (x, 3x, 5x ... )
<pre>
(def odd-multiples
(map seq-mul odds (repeat x)))
</pre>
<p>
`odd-multiples' is a sequence each element of which is again a sequence. We use
`odd-multiples' to generate the sequence (sin(x), sin(3x), sin(5x) ...):
<pre>
(def odd-harmonics
(map (fn [x] (map sin x)) odd-multiples))
</pre>
<p>
Now we need to `scale' each value in the sequence - we first generate the
scale values 1, 1/3, 1/5, 1/7 ...
<pre>
(def scale-values
(map (fn [x] (/ 1.0 x)) odds))
</pre>
<p>
We are now ready to generate the sequence (sin(x), (1/3)sin(3x), (1/5)sin(5x) ...):
<pre>
(def fourier-series
(map seq-mul scale-values odd-harmonics))
</pre>
<p>
`fourier-series' represents an infinite series. We can take say the first 10 terms and
add them up by:
<pre>
(reduce seq-add (take 10 fourier))
</pre>
<p>
Let's wrap this up in a convenient function:
<pre>
(defn plot-fourier [n]
(let [y (reduce seq-add (take n fourier))]
(view (xy-plot x y))))
</pre>
<p>
`plot-fourier' plots the sum of the first `n' terms of the series. Have fun by
trying out different values for `n'!
Lazy sequences in Clojure2010-06-01T00:00:00+00:00http://pramode.net/clojure/2010/06/01/lazy-sequences-in-clojure<h2>Lazy Sequences in Clojure</h2>
<p><em>Jun 1, 2010</em></p>
<p>
Clojure has the wonderful ability to represent and manipulate infinite sequences using
small, finite amount of memory. Look at the following example:
<p>
<pre>
user=> (def p (iterate inc 1))
user=> (take 10 p)
(1 2 3 4 5 6 7 8 9 10)
</pre>
<p>
The `iterate' function: (iterate f x) - generates an infinite sequence x, f(x), f(f(x)), f(f(f(x))), and so
on. How is it that an infinite sequence is stored in a small, finite number of bytes in memory? The logic
is simple - there is really nothing infinite about the sequence - what we have in memory is a simple two
element sequence, the first element being `x' itself and the next element a function which will compute the
subsequent elements of the sequence when required. When we request the second element of the sequence, this function
computes the second element plus yet another function which will yield the remaining elements of the sequence and so
on.
<p>
The `take' function in the above examples gives us the first 10 elements of the sequence.
<p>
Though infinite sequences are easy to use, there is a subtle problem. Let's try an
experiment:
<p>
<pre>
user=> (def p (range 0 1e7))
user=> (time (reduce + p))
user=> (time (reduce + p))
</pre>
<p>
On my slow AMD Sempron system, the first `reduce' took around 12 seconds while the second
one took only 1.1 second! Why is this so? The `range' function returns a lazy sequence. The
first time `reduce' was called, each element of the sequence had to be computed. The next time
`reduce' is called, Clojure no longer has to compute the individual elements - the elements
`cached' during the previous call to `reduce' can be used directly. This seems to be a good
idea.
<p>
Let's look at another example:
<pre>
user=> (def p (range 0 1e11))
user=> (nth p 1000000000)
</pre>
<p>
Keep the `top' command (which displays information about system memory, processes etc continuously) running
in another console before executing the above two functions. You will observe that as soon as you call the
function `nth', available memory starts dropping; very soon your system is forced to use swap memory; if
you wait long enough, you may even be able to see your program crashing.
<p>
To complicate things further, you will see that the following code fragment:
<p>
<pre>
user=> (nth (range 0 1e11) 1000000000)
</pre>
<p>
works perfectly and does not consume excessive amount of RAM.
<p>
Why is this so?
<p>
The nth element of a sequence can be visited only after visiting the first (n-1) elements.
As each element is `visited', it is computed and stored in memory. Because you have a
reference `p' pointing to the first element of the sequence, none of these computed elements
can be freed up. So, if `n' is sufficiently large, very soon all available memory gets eaten
up by these `cached' elements.
<p>
In the second case, we have no reference pointing to the head of the sequence. The JVM is
free to garbage collect the memory used by the already computed elements of the sequence
to make way for the newly computed elements.
Creating Objects in Clojure2010-05-26T00:00:00+00:00http://pramode.net/clojure/2010/05/26/creating-objects-in-clojure<h2>Creating Objects in Clojure</h2>
<p><em>May 26, 2010</em></p>
<p>
If you have a Java background and can't imagine life without objects,
don't worry! Using closures, it's easy to build the kind of `objects'
which you are familiar with in Java.
<p>
Let's create a simple `student' class with fields `name' and `age'
and two methods - `set' and `get'.
<pre>
(defn student []
(let [name (atom nil)
age (atom nil)
set (fn [n a]
(do (reset! name n)
(reset! age a)))
get (fn [] [@name @age])]
(fn [m]
(cond (= m :set) set
(= m :get) get))))
</pre>
<p>
Now, let's create a student and try to set/get the fields:
<pre>
(def s1 (student)) ; think of s1 as our student `object'
((s1 :set) "foo" 34) ; call the `set' function
((s1 :get)) ; returns ["foo" 34]
</pre>
<p>
The logic is simple - the `student' function defines four local variables
`name', `age', 'set' and `get' of which `set' and `get' are themselves
functions. The body of the let is a function which accepts one parameter and
depending on the value of that parameter (either :set or :get) returns one
of the functions `set' or `get'.
<p>
The key to understanding the code fragment given above is to realize
that `s1' is a function - this function, when called with parameter :set,
yields yet another function to which we can pass a name and an age. The
same function, when called with parameter :get yields a function which
when invoked returns the values of the atoms `name' and `age'.
<p>
Object oriented programming does not end with creating objects - we need
stuff like inheritance, polymorphism etc. Clojure can do all these - and
more!