I've been an Object-Oriented Programmer (Ruby, Java) for my entire career. I even approached JavaScript as a classical OO language (many do), though my thoughts on that have changed recently.

Now, I want to try my hand at learning a functional programming (FP) language. Though I played with Lisp in school, I didn't fully grasp the core concepts of FP. After checking out Haskell and Elixir, I settled on Clojure.

What is Clojure Newbie?

Clojure Newbie is where I'll be tracking my progress as I learn aspects of using the language and consume core FP concepts.

(def clojure-newbie [] "A Work in Progress")

Taking inspiration from Living Clojure, I'll be following Clojure news and working through problems sets on sites like 4clojure. The goal will be to build and launch a non-trivial Clojure application and/or library.

Noob Resources

Interested in learning more about Clojure yourself? Here are some good starter resources I've come across:



Built With

Share this project:


posted an update

Holy smokes!

So, I just labored through ["Pascal's Triangle" on 4clojure](].

For background, the first 5 rows of Pascal's Triangle looks something like this:

         [1 1]
       [1 2 1]
      [1 3 3 1]
     [1 4 6 4 1]

The problem calls for simply returning the nth row, not the whole triangle. I finally got a working solution:

(fn [n] 
  (map #(apply 
         (fn pas [x y] 
           (if (or (zero? x) (= x y)) 1 
             (+ (pas (dec x) (dec y)) (pas x (dec y))))) %) 
       (for [x (range n)] [x (dec n)])))

Without explaining in detail, I didn't like having to use an if/else branch and recursion.

I was really impressed to find another user build up the whole triangle without either:

(take n (iterate (fn next-row [v] (vec (map + (apply conj [0] v) (conj v 0)))) [1]))

It hadn't occurred to me to use iterate with a vector to build up the rows. Very cool!

Log in or sign up for Devpost to join the conversation.

posted an update

I've now finished 66 / 156 problems on 4clojure!

I'm coming to understand one of the powerful features of Clojure, and Lisp languages in general, is the interchangeability between code and data. That Clojure code is itself a data structure allows programmers to extend the language through use of macros. There are also cases where data structures can themselves be treated as functions.

Example. In "Set Intersection", the challenge is to re-implement set intersection with out using the intersection function. This means that, given two sets, find the elements that are present in both. The straightforward imperative algorithm may be to iterate over the first set and simply add items to a new set when also present in the second.

# pseudocode

s = new Set
for item in set1 do
  if set2 contains? item do
    s add item

In Clojure, we can pass a function to filter out items from one set using a predicate capturing logic:

(set (filter #(contains? set2 %1) set1))

Even, better, filter allows us to use a set in place of the first arg to filter, effectively treating it as a predicate to each item in the other set.

(set (filter set2 set1))

How simple? Code <=> Data for the win.

Log in or sign up for Devpost to join the conversation.

posted an update

I was proud of myself for coming up with a terse solution to @4clojure Problem 33 "Replicate a Sequence" until I discovered "interleave" doesn't accept 1 argument in older versions of clojure

So for Clojure 1.6.0, my solution:

#(apply interleave (repeat %2 %1))

will satisfy the following when replacing the fill-in-the-blank symbol:

(= (__ [1 2 3] 2) '(1 1 2 2 3 3))

(= (__ [4 5 6] 1) '(4 5 6))

Unfortunately, on 4clojure, the second example above fails with an arity exception on interleave, i.e., wrong number of arguments. Then I came across this thread citing the same issue. So 4clojure must be using an older version of Clojure to verify the results... at least I wasn't going crazy!

Rather than re-implement interleave, my uninteresting workaround is to return the collection if n is 1:

#(if (> %2 1) (apply interleave (repeat %2 %1)) %1)

User _pcl came up with a great solution. Rather than repeating the sequences then combining them with interleave, the approach is to map the sequence onto a result that repeats each item and flatten the result. The "map then flatten" is expressed as mapcat in Clojure

So a better solution:

#(mapcat (partial repeat %2) %1)

Log in or sign up for Devpost to join the conversation.

posted an update

Along with learning #clojure, I'm still working toward thinking like a functional programmer. This includes grasping the concepts and knowing the tools. It helps to get something working in the more-familiar imperative style - then figure out a better - more functional - solution.

For example, Problem 30: Compress a Sequence on 4clojure requires the programmer to remove consecutive duplicates from a sequence. So vector [1 1 2 3 3 2 2 3] should become a sequence '(1 2 3 2 3) and the string "Leeeeeerrroyyy" would be "Leroy" (when reassembled as a string). My first attempt simple built up new sequence while perform an "if/else" check: only add the next item to the new sequence if the last item doesn't match. This can be done with a reducing function, like so:

(reduce (fn [coll val] (if (some #{val} coll) coll (conj coll val))) [] (seq "Leeeeeerrroyyy"))
# => \L \e \r \o \y

Kind of boring. I then found a much cooler (!), i.e., functional, approach. The partition-by function allows the programmer to split up a sequence based on the result of some other function while retaining the order. This would be like taking a line of school children and asking them to pair up with the person to their left and/or right if they were wearing the same color. Turns out, in #clojure, you can partition by identity (if the values are equal). This would return a list of lists:

(partition-by identity [1 1 2 3 3 2 2 3])
# => ((1 1) (2) (3 3) (2 2) (3))

Not quite the full solution, but what we have done is provided a intermediate sequence that can be converted into the solution by mapping over the result simply taking the first item of each sub-list:

(map first (partition-by identity [1 1 2 3 3 2 2 3]))
# => (1 2 3 2 3)

No "if/else" statements, uses built-in functions, much more elegant!

Log in or sign up for Devpost to join the conversation.