PCL -> Clojure, Chapter 10

This article is part of a series describing a port of the samples from Practical Common Lisp (PCL) to Clojure. You will probably want to read the intro first.

This article covers Chapter 10, Numbers, Characters, and Strings.

Lisp with Java guts

Because Clojure is Java under the covers, you can always use Java's support for numbers, characters, and strings. The Java interop syntax is clean and simple, so it is idiomatic to call Java directly, rather than write wrappers to make code look more Lisp-like. A few examples follow:

  user=> (Math/pow 3 3)
  27.0

  user=> (.compareTo "a" "b")
  -1

  user=> (Character/toLowerCase \A)
  \a

Numbers are numbers

In Clojure, as in most Lisps, numbers are numbers. They don't do irritating things like overflow:

  user=> (* 1000000 1000000 1000000)
  1000000000000000000

Also, integer division is exact:

  user=> (/ 10 3)
  10/3

Under the covers, Clojure's numeric representation switches Java types as necessary to do the right thing.

  user=> (class (* 1000 1000))
  java.lang.Integer
  user=> (class (* 1000000 1000000))
  java.lang.Long
  user=> (class (* 1000000 1000000 1000000))
  java.math.BigInteger

Study the API docs

Clojure does a good job of balancing the purity of math (Lisp) and the practical reality of efficient representation (Java's primitives). But you still have to know your way around. Some things are wrapped in Lisp, and some things aren't. For example, numbers support the mathematical comparison operators, but Strings use Java's compareTo:

For example:

  user=> (< 1 2)
  true
  user=> (< "a" "b")
  java.lang.ClassCastException: java.lang.String
  user=> (.compareTo "a" "b")
  -1
  user=> (.compareTo 1 2)
  -1

If you aren't sure whether there is a Lispy wrapper for some functionality, you can check the API docs, or just try it in the REPL.

Wrapping up

For numbers, characters, and strings, Clojure provides some of the trappings a Lisp programmer would expect, e.g. exact integer division. But under the covers, it's all Java. If you don't find what you need in the Clojure API, drop to Java using the interop syntax.


Notes