views:

330

answers:

3

In Scheme, we just had define for all the definition, why does Clojure and Lisp use different keywords for different declarations?

+2  A: 

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?)

dmitry_vk
Scheme doesn't have classes. And 'define' only really defines variables — 'lambda' defines functions. (define (a b c) ...) is equivalent to (define a (lambda (b c) ...))
Anton Tykhyy
In Scheme, `lambda` does *not* define a function, it only creates one. `define` is used for *all* definitions. And yes, "Scheme" does not have classes, but in practically all Scheme class systems (and almost all implementations have some OO system) `define` is used to define classes as well, it just happens that the expression that is used in the definition evaluates to a class.
Eli Barzilay
+14  A: 

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.

Pinochle
Your Scheme is wrong there -- both the function name and the argument should be parenthesized. In addition, your explanation is only a small part of the whole picture. The "sugared" version of Scheme's definitions is *not* just to avoid boilerplate code -- it is easier to use (especially for newbies) since the thing that is defined *looks like* its uses. In other words, you define something that looks like a symbolic template for later uses of the function.
Eli Barzilay
You are right. Trying to keep too many diferent lisps in the head at once. Scheme is the odd lisp out on that particular bit of sugaring, and since I haven't been using Scheme much and have been avoiding the sugared form when I do, I blew it. Corrected.
Pinochle
I had not noticed the little cognitive 'priming trick' being played by the sugared form, that pre-echoing future use of the function in an s-expression, neat. I had not noticed that, at least not consciously. Something always bothered me about that form, and now I know what it is. The priming trick depends on the brain understanding the syntax of `define` to be loosely having something to do with a s-expression rather than giving a value to a name (an atom). I guess it is that sub-consciously noted 'semantic imprecision' had made me uneasy.
Pinochle
Huh? This is the same thing that is used in algebra: "define f(x) to be x+7, now compute f(22)" -- the definition is intentionally looking like its use. Same goes for *most* programming languages, including Scheme. Even the thing that bugs you -- that `f` itself has a value, has an algebraic equivalent: "define f(x) to be x^2, compute the derivative of f".
Eli Barzilay
I'm probably just trying to rationalize a question of taste; mine was formed using Common Lisp, so the `(define (function arg)...` has always seemed foreign to me. Again, thanks for pointing out the justification for its use.
Pinochle
+1  A: 

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.

Brian Carper
"defn is a macro that adds sugar for easily setting docstrings and metadata" : But even variables could benefit from such features. This argument would be valid only if the argument was that defn should behave as def. "def for everything would result in a lot of boilerplate." : Could you please elaborate on his this follows? Scheme code, as Eli has pointed out use define to name variables, functions, and classes... without any boilerplate.
kanak