code7 interactive

From Ruby to Lisp

My first steps as a Ruby developer towards learning Lisp.

For more than a decade now, I have been paid to do what I love, write code. During all this time I’ve been using quite a few different languages and web frameworks.

Ruby has been my favorite language for many years now, and before that my two main programming languages were PHP and Perl.

Also, due to me being a web developer, I use JavaScript all the time. (I ❤ CoffeeScript)

I’ve been thinking about learning a functional programming language for quite some time now and I started out with Erlang but I could never wrap my head around the syntax.

And then, out of the blue, a friend of mine told me about the book “Land of Lisp” and how it would change my life… OK, slight exaggeration.

Background

The name Lisp derives from “LISt Processing”. Linked lists are one of Lisp languages’ major data structures, and Lisp source code is itself made up of lists.

The first version of Lisp was released in 1958, some 35 years before the initial release of Ruby. It was introduced in the era of FORTRAN and COBOL.

Since then, a myriad of Lisp dialects have surfaced. The most popular general purpose Lisp dialects seems to be; Common Lisp, Scheme and Clojure.

Land of Lisp

With its eye-catching subtitle Learn to Program in Lisp, One Game at a Time! you immediately get the feeling that this isn’t your normal, run-of-the-mill programming book. And it turns out to be something completely different.

(Hint: It’s a comic book in the same vein as Why’s (Poignant) Guide to Ruby)

I have a repo on GitHub where I will push notes and code while I read the book.

Instead of writing a long winded book review, I’ll opt for linking to a few that I think do the book justice: Slashdot, I do robots, Jorge Tavares and the Ruby Rogues.

newLISP

All of the examples in “Land of Lisp” are written in Common Lisp, but I actually started out by playing with a younger Lisp dialect; newLISP.

newLISP is a scripting Lisp for people who are fascinated by Lisp’s beauty and power of expression, but who need it stripped down to easy-to-learn essentials.

If you are using OS X and have Homebrew installed, then you can install newLISP with the following command: brew install newlisp

Examples

Lisp is using prefix notation, also known as Polish notation.

Most programming languages are limited to two operands per operator but Lisp can have any number of operands per operator.

Compute the sum of 4,2,1

; newLISP
(+ 4 2 1)
# Ruby
[4,2,1].inject(:+)

Check if 4 is greater than 3, and 3 is greater than 2

; newLISP
(if (> 4 3 2) (println "4 is greater than 3, and 3 is greater than 2"))
# Ruby
puts "4 is greater than 3, and 3 is greater than 2" if 4 > 3 && 3 > 2

Learn more about newLISP

You should definitely take a look at the Introduction to newLISP after you have read the newLISP User Manual.

OSNews: A Look at newLISP

A collection of modules for a variety of things are available over at GitHub (Including the dependency-managing library QWERTY).

Common Lisp

Common Lisp, commonly abbreviated CL, is a dialect of the Lisp programming language, published in ANSI standard document ANSI INCITS 226-1994 (R2004)

There are a lot of Common Lisp implementations available, both commercial and freely redistributable; I’m using the very portable GNU CLISP.

You can install it using Homebrew: brew install clisp

Quicklisp

My friend Joel told me about the best thing to have happened to CL since like ever: Quicklisp

Quicklisp is a library manager for Common Lisp. It works with your existing Common Lisp implementation to download, install, and load any of nearly 700 libraries with a few simple commands.

Examples

You will find a lot of examples in the article Features of Common Lisp.

Rational numbers

; CLISP
(/ 1 2)
; => 1/2
# Ruby
(1.0/2).to_r
# => (1/2)

Multiple return values

; CLISP
(floor pi)
; 3 ;
; 0.14159265358979323851L0

Conveniently, functions that return multiple values are treated, by default, as though only the first value was returned:

; CLISP
(+ (floor pi) 2)
; => 5

To achieve something similar in Ruby (slightly contrived example):

# Ruby
class MultiValue < BasicObject
  attr_reader :secondary

  def initialize(obj, *secondary)
    @obj, @secondary = obj, secondary
  end

  def method_missing(sym, *args, &block)
    @obj.__send__(sym, *args, &block)
  end
end

class Array
  def to_mv
    MultiValue.new(*self) unless empty?
  end
end

class Numeric
  def floor_with_remainder
    [floor, remainder(floor)].to_mv
  end
end

This allows us to do the following:

# Ruby
Math::PI.floor_with_remainder + 2
# => 5

mv = Math::PI.floor_with_remainder
mv.secondary.inject(mv, :+)
# => 3.141592653589793

If you want to learn more about writing Lispy Ruby, then you should take a look at Chapter 8 in the book Practical Ruby Projects: Ideas for the Eclectic Programmer by Topher Cyll.

Learn more about Common Lisp