Amanuel Nega
Amanuel Nega

Reputation: 1977

Are clojure forms data or type?

I am beginning learning clojure. Coming majorly from Java and some scripting languages, the code as data part of clojure (and all functional languages, I assume) is not so clear.

Starting from the first pages of the book I see forms. And I see it mostly associated with data, like #{1 2}. But in some other places I saw Boolean labelled as form.

Now, I was under the assumption that false is a form of type Boolean, but I didn't see type being mentioned more than a few times, so I am confused.

Can someone give me a push to understand the concept of forms and also give me a push so that I can understand code as data part of the language?

Upvotes: 3

Views: 303

Answers (2)

Thumbnail
Thumbnail

Reputation: 13483

Are clojure forms data or type?

- data

A Clojure form is a piece of code viewed as data.

Clojure forms have a chemistry. The elements are things like

  • numbers (42, 3.1416, 22/7)
  • strings ("1, 2, buckle my shoe.")
  • symbols (a5, freds-white-teeth), whatever they denote.

The molecules are things like

  • expressions ((+ 1 1), (reduce * (range 1 n)))
  • argument lists ([f coll], [[forename surname :as name]])

The only structures used to bind molecular forms together are Clojure's own data structures. This is what code as data means.

Clojure uses

  • lists for expressions;
  • vectors for argument lists (and binding forms in general);
  • (maps for associative binding forms).

    (Leave these for now).

At the top level, we typically have def and defn forms. These can be many layers deep.

  • def is a special form. It has its own evaluation rules.
  • defn looks like a special form, but it isn't.

Because Clojure programs are written as Clojure data, we can write functions that

  • take forms as arguments and
  • return a form result.

The final piece of the jigsaw is that Clojure supplies a special mode of function, called a macro, that

  • operates on its arguments as forms
  • turns the call form into the form result.

This turns out to be a mechanism of great power. For example, defn is a macro that wraps a fn form inside a def form. A cheap and cheerful analogue is

(defmacro my-defn [name & args-and-body]
  (list 'def name (cons 'fn (cons name args-and-body))))

The real defn is considerably more complicated. But this one is enough to cope with

(my-defn twice [n] (* 2 n))

(twice 3)
;6

We can see what's going on by doing

(macroexpand '(my-defn twice [n] (* 2 n)))
;(def twice (fn twice [n] (* 2 n)))

We can even define recursive functions:

(my-defn fact [n]
  (if (pos? n)
    (* n (fact (dec n)))
    1))

(map fact (range 1 5))
;(1 2 6 24)

  • The above applies to any Lisp, not only to Clojure.
  • Other Lisps use only lists for structuring forms.
  • No other significant language has the code as data property.
  • Functional languages are no exception: the ML family (ML, OCaml, Haskell, F#, ...) have fairly conventional syntax.

Upvotes: 4

Thumbnail
Thumbnail

Reputation: 13483

Clojure has forms because it is a Lisp.

  • A Clojure form is an element or data structure presented as part of a program.
  • Clojure and other Lisps have forms in this sense.
  • Most programming languages, apart from Lisps, do not: the structures used to compose program structure are nothing like the native data structures.
  • Functional languages are no exception. Look, for example, at the ML family.

The rules for evaluation tell you how forms work.

  • The payoff for using the native data structures to express program structure is that you can write programs that manipulate forms almost as easily as you can write any other kind.
  • Such programs are called macros.

For example, take a look at the source for and. You can't do this in Java.


This answers your question for Lisps in general.

Upvotes: 6

Related Questions