Confused by "let" in Clojure
clojure, eval, let
Solution
You have an extra set of parentheses around the `do` form. Your code is doing this:
((do ...))
It's trying to execute (as a function call) the value of the entire `do` form, but `do` is returning `nil`, because the last `println` in the `do` form returns `nil`.
Note, your indentation style is non-standard. You shouldn't put the closing parens on their own lines. And `let` has an implicit `do` so you don't need one there. Try this:
user> (doseq [exstr *exprs-to-test*]
(let [ex (read-string exstr)]
(println "===" (first ex) "=========================")
(println "Code: " exstr)
(println "Eval: " (eval ex))))
=== filter =========================
Code: (filter #(< % 3) '(1 2 3 4 3 2 1))
Eval: (1 2 2 1)
=== remove =========================
Code: (remove #(< % 3) '(1 2 3 4 3 2 1))
Eval: (3 4 3)
=== distinct =========================
Code: (distinct '(1 2 3 4 3 2 1))
Eval: (1 2 3 4)
Problem
I just started playing with Clojure, and I wrote a small script to help me understand some of the functions. It begins like this: ``` (def *exprs-to-test* [ "(filter #(< % 3) '(1 2 3 4 3 2 1))" "(remove #(< % 3) '(1 2 3 4 3 2 1))" "(distinct '(1 2 3 4 3 2 1))" ]) ``` Then it goes through `*exprs-to-test*`, evaluates them all, and prints the output like this: ``` (doseq [exstr *exprs-to-test*] (do (println "===" (first (read-string exstr)) "=========================") (println "Code: " exstr) (println "Eval: " (eval (read-string exstr))) ) ) ``` The above code is all working fine. However, `(read-string exstr)` is repeated so I tried to use `let` to eliminate the repetition like so: ``` (doseq [exstr *exprs-to-test*] (let [ex (read-string exstr)] ( (do (println "===" (first ex) "=========================") (println "Code: " exstr) (println "Eval: " (eval ex)) ) )) ) ``` But this works once for the first item in `*exprs-to-test*`, then crashes with a `NullPointerException`. Why is the addition of `let` causing the crash?