30 March 2010

My learning experience with the bare basics of Clojure

I've been too busy to really dig into Clojure programming, but I thought it'd be a good exercise as a mental note of what the last thing I was learning is by writing down a bit of my experience in the learning process...

As I begin to learn Clojure programming, I wanted to get some data to play with, to get a sense of what different functions do in Clojure, so I started with this:

(def x (for [x (range 5)] (rand)))
(def y (for [x (range 5)] (rand)))


This way I have two lists of random numbers, each having 5 numbers.  I wanted to match each element in x with its corresponding element in y (so that, eg, I could later add them together element wise as though they were vectors in math; or multiply them together later, then summed, as though I was doing a convolution, etc.)

So here's my first try:


(for [xi x
      yi y] (xi yi))

This creates a lazy sequence (the notion of laziness doesn't matter when working in the REPL, so forget about that for now). It demonstrates destructuring, giving the elements in the list x the name xi. Note also that for isn't a for-loop, but a list comprehension, but anyway.

Except I wasn't sure what it was doing because the random numbers were confusing.  So instead, I rewrote my demo data set as:

(def x (range 0 10))
(def y (range 20 30))


This creates two lists, one that's (0, 1, ..., 9), and one that's (20, 21, ..., 29).  Now what I hoped the (for ...) code would do was give me back a list ((0 20), (1 21), ..., (9 29)). But it didn't.

I realized it was doing essentially a nested for-loop, cycling through all combinations matching numbers in one list with the other. I recalled reading about [1] zipmap and thought it might help. I looked up its brief documentation in the REPL by executing the command (doc zipmap). Okay, I give it a try:

(zipmap x y)

Well, that's promising, but it gives me a map. I want a list.  I try (vector (zipmap x y)) but that just wrapped up the map in a vector. I look up the documentation.  Okay, so (vec (zipmap x y)) seems to give me what I want, at least as a vector rather than a list.

What to do?  How about converting the vector into a list? Let's Google search that!  This looks promising and looks like a good tutorial even. But bottomline,
(seq ...) does what I want, as in:

(seq (zipmap x y)).

Nice. That worked for me! Well, that's all the time I have to goof around with Clojure, so I'll have to carry on from here next time around.

[1] What worked well for me in learning programming in the past has been to  look for five or ten different tutorials, reference cheat sheets, etc, and browse, skim, and generally read through them in pieces. I've always found some explanations better in one source for one thing, but better from another source for another thing. So the browsing through the different sources gave me a chance to see the diversity of ideas, and also different interpretations and explanations for the same ideas. That way I can read what I find is the best explanations to learn from, but also get a sense of what I don't know yet. People tend to learn in an episodic manner, and browsing and grazing helps feed that style of learning.

No comments: