History always repeats itself and sometimes that's good. Here's a second chance to be part of it: tmdtc.com

Tuesday 10 March 2009

Generate a random string in Clojure

In my quest to learn Lisp, I discovered Clojure, a List inspired language on the JVM. I really like it and hope to be able to use it more and more.
Here's a code snippet to generate a random string in Clojure. This is something I end up using a many projects. This is a version that is not made to be the shortest, but the most readable. And as you can see, access to Java's classes and libraries is very easy:

:use java's random generator
(def random (java.util.Random.))
;define characters list to use to generate string
(def chars
(map char (concat (range 48 58) (range 66 92) (range 97 123))))
;generates 1 random character
(defn random-char []
(nth chars (.nextInt random (count chars))))
; generates random string of length characters
(defn random-string [length]
(apply str (take length (repeatedly random-char))))

Suggestions to improve the code are welcome, I'm still a newbie in Lisp-style programming and Clojure!


Jeff said...

A slightly modified version, without using Java's random and with corrected ranges for the characters. (Annoying that blogger won't allow code or pre tags...)

(map char (concat (range 48 58) ; 0-9
(range 66 91) ; A-Z
(range 97 123)))) ; a-z

(defn random-char []
(nth VALID-CHARS (rand (count VALID-CHARS))))

(defn random-str [length]
(apply str (take length (repeatedly random-char))))

Aaron B. Iba said...

Jeff, I think you meant:

(range 65 91) ; A-Z

Don't want to forget A!

Topher said...

Jeff, your random-char function could be simplified like this:

(defn random-char []
(random-nth VALID-CHARS))

Jeff said...

Yeah, now we can use rand-nth, but this function wasn't around when I first commented.

Filip said...
This comment has been removed by the author.
Filip said...

This is my version:

(defn random-string [length]
(let [ascii-codes (concat (range 48 58) (range 66 91) (range 97 123))]
(apply str (repeatedly length #(char (rand-nth ascii-codes))))))

Rob said...

Exactly what I was looking for, thanks!

Unknown said...

UUID version:

(defn new-uuid []


A Breaking Change said...

(Integer/toString (.nextInt random) 36)

A Breaking Change said...

Microsoft-style product keys

(defn r1ss [] (clojure.string/upper-case (Integer/toString (.nextInt random Integer/MAX_VALUE) 36)))
(defn r25s [] (->> (repeatedly r1ss)
(apply concat)
(take 25)
(partition 5)
(map (partial apply str))
(interpose "-")
(apply str)))

Inez said...


Theresa said...

This is gorgeous!