Programming ≈ Fun

Written by Krešimir Bojčić

Are Those (Lisp) Wackos Actually Right?!

For the last week I am having this crazy thoughts. What if Lisp really is an asymptote that all programming languages are converging to. It seems to me more power you have, closer to Lisp you are. I’ve heard it hundreds of times, but never “bought” it. What if you really don’t see parentheses after a while? How would the syntax look then? Ever since BASIC on C-64 I was exposed to Algol like syntax. That was 24 years ago, and I was 10 at a time. Is it strange that I find “other” syntax strange (pun intended).

So the burning question in my mind is: Is Ruby just a transition to Lisp. Ruby has all this nice stuff that enables me to better express myself. Best part is that feeling that I get while working with Ruby. It is cozy and familiar, but is Ruby just softening me up to see the Light?

This is how I see Lisp programmers. They are crazy, bearded and ambushing poor language syntax from their beloved S-expressions. They are making poor syntax do stuff they(syntaxes) are too ashamed to tell their mothers. Stuff that is terrible beyond imagination. Stuff that you hear only happening in third world jails in banged-up-abroad kinds of show. I am talking about stuff like making method private only in production and public for test and development… hey wait, that might actually come in handy.

With this heresy in my mind, that Lisp might actually be right I started checking out Clojure. My hipster glands got a little bit swollen, but I can see that all the hype was justified.

What I like:

  • Somebody spending 2.5 years on his obsession +1
  • Realisation that plan for Lisp dominance is progressing rather slowly, but creating a strong niche to counter
  • Closing an eye on purity in favor of making me feel more at home
    • Literals for hash, array, function variables…
    • Symbols with : and making , behave like space
    • Parenthesis are not always a must
  • Piggyback riding on JVM - this is winner for “enterprise”(You know expensive stuff that barely works for 300 users at most)
    • JVM makes this scenario possible: Boss can I use Clojure? What is it? A small Java library for concurrency. Sure.
  • Vim is a first class citizen

Let’s look at the couple of examples from Programming Clojure book and translate them to Ruby.

This made me want to slap end on the last line like this ;end. But I resisted the urge.

(defn square-corners [bottom left size]
  (let [top (+ bottom size)
        right (+ left size)]
    [[bottom left] [top left] [top right] [bottom right]]))
def square_corners(bottom, left, size)
  top = bottom + size
  rigth = left + size
  [[bottom,left], [top,left], [top,right], [bottom,right]]
end

Clojure has a really cool way of making :first_name also a function. It reads even better than Ruby version:

(defn greet-author-1 [author]
  (println "Hello, " (:first_name author)))
def greet_author_1(author)
  print "Hello, #{author[:first_name]}"
end

Destructuring, I wanted to write about it but Ruby Weekly and Tony Pitgula has beaten me to the punch with Destrucuring with Ruby. Ruby counter is inadequate, but it’s the best I got:

(defn greet-author-2 [{fname :first-name}]
  (println "Hello, " fname))
def greet_author_2(name)
  print "Hello, #{name}"
end

All is not grim for Ruby because this you can do:

(let [[x y] [1 2 3]])

(let [[_ _ z] [1 2 3]])

(let [[x y :as coords] [1 2 3 4 5 6]])
x,y = [1,2,3]

_,_,z = [1,2,3]

x,y = coords = [1,2,3,4,5,6]

For the next example I found Ruby version looking better:

(ns test
  (:use clojure.contrib.str-utils))

(defn ellipsize [words]
  (let [[w1 w2 w3] (re-split #"\s+" words)]
    (str-join " " [w1 w2 w3 " ..."])))

(println (ellipsize "The quick brown fox jumps over the lazy dog."))
def ellipsize(words)
  w1, w2, w3 = words.split(/\s+/)
  "#{w1} #{w2} #{w3} ..."
end

print ellipsize "The quick brown fox jumps over the lazy dog."

My second take was to do same thing a bit differently.

(defn ellipsize2 [words]
 (str-join " "
  (concat ( take 3 (re-split #"\s+" words)) " ...")))

(println (ellipsize2 "The quick brown fox jumps over the lazy dog."))
def ellipsize2(words)
  words.split(' ').take(3).join(' ') + " ..."
end

print ellipsize2 "The quick brown fox jumps over the lazy dog."

Notice that in all examples, you can almost map it line to line. That tells me that Ruby is rather good, and also good enough for me.

The thing is, I’ve found stuff that Ruby can’t do. I haven’t found anything like that the other way around. I still much prefer Ruby syntax, I sill prefer 20 years of hard wiring my brain for certain stuff to mean certain things, and I still hate to browse documentation to find that I need function named conj…

I am excited that Ruby 2.0 is including keyword arguments, and I would love to see destructuring in method definitions in Ruby 2.x (I also suspect that keyword arguments will drive a tear of joy in Kent Becks eye, seeing (also) Smalltalk legacy living on)

So some might argue that Ruby is lame implementation of old ideas, but I still love it. And Ruby is really holding it’s ground with dignity. It seems that most of the stuff that is interesting enough got implemented. You know how love is blind, so even if something is missing I’ll look the other way… Important thing is to think about customers (us) even if you are making programming language. Not that many people want to unlearn 10+ years and go the other way. For every interface it is important to be human friendly. And Ruby is for vast majority of users more user friendly but I suspect that after you get accustomed with S-expressions, there is really nothing wrong with it and it does allow you to be really flexible.

For a conclusion my verdict is(if you got this far I am impressed with your stamina for my lamenting, you sir are a good material for weekly status meetings with customers) that Ruby is not a transition to Lisp. It just borrowed lot’s of good stuff from it, but that’s life. I think they will converge even further. You can also argue that Clojure also borrowed from Ruby, or Perl with literals, and also from Python for :use :only. Anyhow I like it.

I don’t think S-expressions will ever be “mainstream”. Just like OS/2 never quite made it. You need a lot of traction and a community that is pushing forward fast.

Also I find that Lisp is rather great, and once you get accustomed on syntax, you can do a lots of cool stuff with it. If I ever need to do any functional programming I’ll make sure to work in Clojure.

Comments