Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure let vs Common Lisp let

In Common Lisp, the let uses a list for a bindings, i.e:

(let ((var1 1)
      (var2 2))
  ...)

While Clojure uses a vector instead:

(let [a 1
      b 2]
  ...)

Is there any specific reason, other than readability, for Clojure to use a vector?

like image 223
kamituel Avatar asked Mar 31 '15 09:03

kamituel


People also ask

Is clojure better than Common Lisp?

Clojure is really your better bet. It is highly practical with a good community and excellent Java interop. You never have to worry about finding a good library. The syntax is also a bit more easily parsable than CL.

What are let and let * forms in Lisp?

LET suggests that you're just doing standard parallel binding with nothing tricky going on. LET* induces restrictions on the compiler and suggests to the user that there's a reason that sequential bindings are needed. In terms of style, LET is better when you don't need the extra restrictions imposed by LET*.

How does let work in Lisp?

The let expression is a special form in Lisp that you will need to use in most function definitions. let is used to attach or bind a symbol to a value in such a way that the Lisp interpreter will not confuse the variable with a variable of the same name that is not part of the function.

Is clojure a Lisp-1 or LISP 2?

Clojure is a lisp-1, meaning it uses the same name resolution for both functions and value bindings.


2 Answers

You can find Rich Hickey's argument at Simple Made Easy - slide 14, about 26 minutes in:

Simple Made Easy - slide 14

like image 125
Thumbnail Avatar answered Sep 24 '22 07:09

Thumbnail


Rich's line on this was as follows

"Since we were talking about syntax, let’s look at classic Lisp. It seems to be the simplest of syntax, everything is a parenthesized list of symbols, numbers, and a few other things. What could be simpler? But in reality, it is not the simplest, since to achieve that uniformity, there has to be substantial overloading of the meaning of lists. They might be function calls, grouping constructs, or data literals, etc. And determining which requires using context, increasing the cognitive load when scanning code to assess its meaning. Clojure adds a couple more composite data literals to lists, and uses them for syntax. In doing so, it means that lists are almost always call-like things, and vectors are used for grouping, and maps have their own literals. Moving from one data structure to three reduces the cognitive load substantially."

One of the things he believes was overloaded in the standard syntax was access time. So vector syntax in arguments is related to the constant access time when you used them. He said:

Seems odd though as it only is valid for that one form...as soon as it is stored in a variable or passed in any way the information is 'lost'. For example...

(defn test [a]
  (nth a 0)) ;;<- what is the access time of and element of a?

I personally prefer harsh syntax changes like brackets to be reserved for when the programmer has to switch mental models e.g. for embedded languages.

;; Example showing a possible syntax for an embedded prolog.

{size [],0}
{size([H|T],N) :- size(T,N1), N is N1+1}

(size '(1 2 3 4) 'n) ;; here we are back to lisp code

Such a concept is syntactically constant. You don't 'pass around' structure at runtime. Before runtime (read/macro/compile time) is another matter though so where possible it is often better to keep things as lists.

[edit] The original source seems to have gone, but here is another record of the interview: https://gist.github.com/rduplain/c474a80d173e6ae78980b91bc92f43d1#file-code-quarterly-rich-hickey-2011-md

like image 33
Baggers Avatar answered Sep 21 '22 07:09

Baggers