1
votes

I am new to clojure. I want to use quote in clojure the following way:

First I define a variable:

(def dog "animal")

And then a function::

(defn what-is [name]

('name (str " is an " name)))

If I call the function what-is with the variable dog as the parameter: (what-is dog)

The result should be:

USER>> dog is an animal

Here I returned the name of the argument I passed to the function what-is, not its value:

What I get instead is:

is an animal

no mention of the parameter dog here.

Again what I am looking for is to repeat "literally" the name of the parameter I pass the function, as in this template:

(what-is x )=> x is an ...

Thank you.

2

2 Answers

5
votes

This is not something that you can do with a function. A function receives only runtime values, not the code that was evaluated to produce those values. If you want to define a piece of code that makes use of the actual source code, rather than the runtime values, you can use a macro:

(defmacro what-is [x]
  `(str '~x " is an " ~x))

(what-is dog)
;;=> "dog is an animal"

As you can see, this what-is macro looks different from your what-is function; it makes use of Clojure's syntax-quote reader macro. Rather than being called at runtime with a string as input and returning a string as output, this macro is called at compile time with a piece of code (x) at compile time and returns another piece of code, which will then be evaluated. You can use the macroexpand-1 function to see exactly what code the what-is macro returns:

(macroexpand-1 '(what-is dog))
;;=> (clojure.core/str (quote dog) " is an " dog)

If you want, you can then evaluate this expanded piece of code to see that it gives the same result:

(clojure.core/str (quote dog) " is an " dog)
;;=> "dog is an animal"
2
votes

Here is another way to do what I think you want to do. Instead of defining the categories of a variable to be its value, use a Clojure map. For example using the basic {} map syntax:

(def what-is-map {"dog"  "animal"
                  "cat"  "animal"
                  "Fiat" "auto"
                  "flu"  "illness"})

(defn what-is [thing]
  (str thing " is an " (what-is-map thing)))

The last expression works because maps can be used like functions in many situations.

(what-is "dog") ;=> "dog is an animal"
(what-is "flu") ;=> "flu is an illness"

You can also provide a default for things that aren't in your map. Here's one way:

(defn what-is [thing]
  (let [what-it-is (what-is-map thing)]
    (if what-it-is
      (str thing " is a " what-it-is)
      (str "I don't know what a " thing " is"))))

The if works because when a key isn't found in a map, nil is returned. (nil is one of the false values. The other is false.)

(what-is "fish") ;=> I don't know what a fish is"

There are other, perhaps better ways to write these functions, but I wanted to keep things basic.