Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are clojure forms data or type?

Tags:

clojure

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?

like image 230
Amanuel Nega Avatar asked Dec 17 '25 21:12

Amanuel Nega


1 Answers

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.
like image 150
Thumbnail Avatar answered Dec 20 '25 15:12

Thumbnail



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!