3
votes

I have the following snippet of Common Lisp code:

(loop repeat len
  do
    (rotatef
      (nth (random len) list)
      (nth (random len) list))
  finally
    (return list)))))

that I would like to get to run using Clojure.

Anyway, the compiler tells me that

loop requires a vector for its binding

What exactly does this mean? Where do I have to introduce a vector?

2
Please note that this snippet does not perform a valid shuffle. If you do want a real shuffle, use the Fisher-Yates method. It's not hard. - Svante
Clojure and Common Lisp are very different languages. Code cannot be translated or ported. You need to re-develop most code. Don't expect that language constructs are compatible. Mostly they are not. Best to use a Clojure reference for its language constructs. - Rainer Joswig

2 Answers

3
votes

This is how you use loop:

(loop [n 0]
  (if (> n 10)
    n
    (recur (inc n))))

The "loop requires a vector for its binding" message comes from the first argument to loop, in the example above this is [n 0], which is a vector, saying we initialize the variable n to 0. later on when we use recur, we mean we want to repeat the body of the loop with a new value of n.

Reminder, loop in clojure is a function of a vector and some expressions as body:

 (loop [bindings*] exprs*)
3
votes

Shuffling

The purpose of your example is to shuffle a list. For completeness's sake, in Common Lisp, you could use alexandria:shuffle to perform the same task on generalized sequences and the equivalent function in clojure is clojure.core/shuffle.

Loop construct

There is a library called clj-iter which is inspired by CL's iterate function, which itself is a based on loop. However, people tend to avoid using such constructs in Clojure and prefer functional composition, etc.

Clojure is a separate language

Only very trivial expressions like (+ 3 4) can be parsed and interpreted as both Clojure and Common Lisp code. Clojure does not try to be compatible in any way with existing Lisp or Scheme languages and has its own computation model which discourages the use of mutable structures, like done with rotatef in your example. Hence, porting Common Lisp code to Clojure requires to redesign the existing code just as-if you had to rewrite it in Scala (or Python or Ruby).

ABCL

I don't really know what you are trying to perform, but if you want to run Common Lisp code on the JVM, you can use ABCL (Armed Bear Common Lisp), which is an efficient implementation of CL in Java.