In Scheme, we just had define for all the definition, why does Clojure and Lisp use different keywords for different declarations?
They define different kinds of objects (functions, special variables, macros, structures, classes, generic functions, methods, packages). In Common Lisp, they also are in different namespaces. Different definition forms also have different syntax (Scheme's define
combines variable and function definition. But can it define a class?)
defn
, defmacro
, defstruct
and such are just macros for defining their corresponding structure, making it unnecessary to write boilerplate code. For example, defn
makes it easier to write functions since you no longer have to worry about putting in the lambda term (which you can do in Scheme just by bracketing the arguments immediately after the name being defined):
Scheme:
(define hello
(lambda (name)
(display (string-append "hello, " name))))
(define (hello name)
(display (string-append "hello, " name)))
Clojure:
(def hello
(fn [name]
(println (str "hello, " name))))
(defn hello [name]
(println (str "hello, " name)))
You can look at defn
as a mnemomic device for def
+ fn
. Such shortcuts make for less boilerplate coding and make the code just easier to read in general. I'm teaching someone how to program Scheme at the moment and I make them use the long forms so that they have in mind at all times what the language is doing (and will appreciate the work-saving macros all the more when they finally start using them).
The define
or def
forms give a name to some expression that follows. The lambda
or fn
form gives the name a set of bindings when used within a define
or def
expression. That's where things start to get more complex and the use of macro forms keeps you sane and protects you from typing boredom.
def
in Clojure is a special form and it's nice to keep special forms as simple and primitive as possible. defn
is a macro that adds sugar for easily setting docstrings and metadata, and (as others have said) removes the need for extraneous parens. defn
also automatically sets up some metadata on your function itself (showing arglists etc.) which makes no sense for a general def
.
Functions are by far the most common thing you're going to be defining toplevel in Clojure. Toplevel mutable variables are discouraged. So it makes sense to have an easy and fast way to define a toplevel function. Using def
for everything would result in a lot of boilerplate. If there was no defn
we'd all be reinventing it ourselves to avoid being annoyed to death.