user520621
user520621

Reputation:

Can't take value of a macro (clojure)

In this segment of clojure code:

(defn makeStructs ;line 27
 "open fName as a file and turns each line into a struct. Returns a Vector of structs"
 [fName]
   with-open[r (reader (file fName))]
   (let [r 
      res (doall (map makeStruct (line-seq r)))
      ]    
  (. r close)
     res
  ) 
)

I am getting this compiler error:

Exception in thread "main" java.lang.Exception: Can't take value of a macro: #'clojure.core/with-open (clojureHW.clj:27)

Line 27 is commented above.

Any idea what the problem is?

Upvotes: 13

Views: 9720

Answers (3)

nickik
nickik

Reputation: 5881

(defn makeStructs ;line 27
 "open fName as a file and turns each line into a struct. Returns a Vector of structs"
 [fName]
   with-open[r (reader (file fName))]
   (let [r 
      res (doall (map makeStruct (line-seq r)))
      ]    
  (. r close)
     res
  ) 
)

This cant work because

  1. You dont have parens around your with-open. This will be a normal symbol it its not called.
  2. You again have a uneven number of forms in your let. You have r, res aund (doall ...). You already make the right binding for 'r' in with-open. All you need is

    (let [res (doall (map makeStruct (line-seq r)))] .... )

  3. Why do you do (. r close) the with-open macro does that for you see here: http://clojuredocs.org/clojure_core/clojure.core/with-open

So you get:

(defn makeStructs 
 "open fName as a file and turns each line into a struct. Returns a Vector of structs"
 [fName]
   (with-open [r (reader (file fName))]
     (let [res (doall (map makeStruct (line-seq r)))]
        res)))

but since you only have one thing in let you dont really need that:

(defn makeStructs 
 "open fName as a file and turns each line into a struct. Returns a Vector of structs"
 [fName]
   (with-open [r (reader (file fName))]
     (doall (map makeStruct (line-seq r)))))

Lisp languages are really simple most programmers just want to make it hard for themselves because they're used to do it. A lot of the questions you have are because you've been used to things working like X, but now they work like Y. Try to not assume that things work like X and you will make your live easier.

Upvotes: 8

octopusgrabbus
octopusgrabbus

Reputation: 10685

To add to your debugging tool bag when you see this error, I suggest you look for a function being defined or called without the open parenthesis '('.

In your particular case, as other answers have already noted, your code is missing the '(' at with-open.

(defn makeStructs ;line 27
 "open fName as a file and turns each line into a struct. 
  Returns a Vector of structs"
 [fName]
-->   with-open[r (reader (file fName))]

You were not calling with-open, but taking its value.

My mistake looked like the following:

--> defn ret-col-match
    "Returns true false match on sequence position w/ cmp-val."

    [row cmp-val col-idx]
    (if (= (nth row col-idx nil) cmp-val)
        true
        false))

You can see the missing '(' right before the defn.

Upvotes: 1

Alex B
Alex B

Reputation: 84792

You need to actually call the macro,

(defn makeStructs ;line 27
 "..."
 [fName]
   (with-open ; note the extra paren

Upvotes: 8

Related Questions