hornbeck

thoughts on business, community and customer service

First Thoughts on Clojure

leave a comment »

Clojure

After completing the second chapter in Programming Clojure I figured I would take a few moments to jot down my initial thoughts and highlight a few pieces that have grabbed my attention.

  1. () != nil

    My initial reaction to an empty list not being nil was “wtf!” but then I decided to ask why. Lucky for me, Rich Hickey responded with a link explaining.

  2. Why can’t I have (doc ) in Ruby?

    After seeing (doc ) I went to Google to see if someone had ported this to Ruby yet. This is how it works,

    user> (doc reduce)
    ————————-
    clojure.core/reduce
    ([f coll] [f val coll])
    f should be a function of 2 arguments. If val is not supplied,
    returns the result of applying f to the first 2 items in coll, then
    applying f to that result and the 3rd item, etc. If coll contains no
    items, f must accept no arguments as well, and reduce returns the
    result of calling f with no arguments. If coll has only 1 item, it
    is returned and f is not called. If val is supplied, returns the
    result of applying f to val and the first item in coll, then
    applying f to that result and the 2nd item, etc. If coll contains no
    items, returns val and f is not called.

    I found this to be very helpful while reading code and working from a REPL.

  3. I can search for docs (find-doc )
    If you are not sure what function you are actually needing but know that it contains the string “reduce”, you can search for it,

    user> (find-doc “reduce”)
    ————————-
    clojure.contrib.seq-utils/reductions
    ([f coll] [f init coll])
    Returns a lazy seq of the intermediate values of the reduction (as
    per reduce) of coll by f, starting with init.
    ————————-
    clojure.core/areduce
    ([a idx ret init expr])
    Macro
    Reduces an expression across an array a, using an index named idx,
    and return value named ret, initialized to init, setting ret to the evaluation of expr at
    each step, returning ret.
    ————————-
    clojure.core/reduce
    ([f coll] [f val coll])
    f should be a function of 2 arguments. If val is not supplied,
    returns the result of applying f to the first 2 items in coll, then
    applying f to that result and the 3rd item, etc. If coll contains no
    items, f must accept no arguments as well, and reduce returns the
    result of calling f with no arguments. If coll has only 1 item, it
    is returned and f is not called. If val is supplied, returns the
    result of applying f to val and the first item in coll, then
    applying f to that result and the 2nd item, etc. If coll contains no
    items, returns val and f is not called.
    ————————-

    The output allows me to read through and figure out which function I’m looking for without having to go to a book or browser to look it up.

  4. How did they do that? Using (source ) to view the code.

    One of the best way to learn a language and it’s idiosyncrasies is to read code written in that language. Using the source function from clojure-contrib allows you to do this with ease.

    user> (source reduce)
    (defn reduce
    “f should be a function of 2 arguments. If val is not supplied,
    returns the result of applying f to the first 2 items in coll, then
    applying f to that result and the 3rd item, etc. If coll contains no
    items, f must accept no arguments as well, and reduce returns the
    result of calling f with no arguments. If coll has only 1 item, it
    is returned and f is not called. If val is supplied, returns the
    result of applying f to val and the first item in coll, then
    applying f to that result and the 2nd item, etc. If coll contains no
    items, returns val and f is not called.”
    ([f coll]
      (let [s (seq coll)]
        (if s
          (if (instance? clojure.lang.IReduce s)
           (. #^clojure.lang.IReduce s (reduce f))
           (reduce f (first s) (next s)))
          (f))))
    ([f val coll]
      (let [s (seq coll)]
        (if (instance? clojure.lang.IReduce s)
          (. #^clojure.lang.IReduce s (reduce f val))
          ((fn [f val s]
            (if s
              (recur f (f val (first s)) (next s))
              val))
          f val s)))))

  5. Functions must be declared before you call them.
    Something I have always found interesting about Lisp in general is the work flow. If I am writing a function and I think that I can abstract a piece of code out of it and into another function I will put in a place holder function name and drop to the bottom of the file to add the new function. Clojure does not allow this without me jumping back to the top of the file to add in a (declare ) statement.

    Not allowed:

    (defn foo [blah]
      (bar blah))

    (defn bar [blah]
      (str (“Hello ” blah)))

    Allowed:

    (declare bar)

    (defn foo [blah]
      (bar blah))

    (defn bar [blah]
      (str (“Hello ” blah)))

    So I either need to defn bar first or I need to add a declare statement before foo. This is something I think the compiler should handle, not something that should require extra syntax.

  6. Java Java Java

    I am a very vocal hater of Java. It’s not really the language that I dislike, it’s more the culture that I have had to deal with that causes anything associated to Java to put a bad taste in my mouth. There is a lot of code out there that can connect to just about any type of system and it’s also the language that a lot of new/interesting projects are written in. Hadoop, Cassandra and Project Voldemort are all written in Java making a language that speaks Java a huge plus while working with them. Clojure does just that, you can import existing Java code using

    (import ‘(org.apache.hadoop.mapred MapReduceBase)
       ‘(org.apache.hadoop.mapred Mapper))

    All you have to do is make sure the Java classes you want to import are in your CLASSPATH. Working with the classes you import isn’t that bad either but I will save most of that for another post.

    So after a couple of days reading and playing with Clojure I’m enjoying it, warts and all. I don’t think these things are enough to keep me from using it as it’s nice to have a language that talks Java but still feels like a Lisp.

Written by hornbeck

July 5, 2009 at 4:32 pm

Posted in clojure

Tagged with , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: