Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Clojure: Eval-ing a String in Clojure

DZone's Guide to

Clojure: Eval-ing a String in Clojure

· Java Zone
Free Resource

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

I recently needed to eval a string into Clojure and found it was easy, but it wasn't accomplished in the way I expected. My recent experience with eval was in Ruby, so I naturally reached for Clojure's eval function. I quickly found that Clojure's eval was not what I was looking for, well, not exactly what I was looking for.

(eval "(+ 1 1)")
"(+ 1 1)"
This quick trip to the REPL reminded me of the last time I needed to eval a string, and the previous experiences I'd had with read-string and load-string. It turns out load-string does the trick, and read-string + eval can also get the job done.
user=> (load-string "(+ 1 1)")
2
user=> (eval (read-string "(+ 1 1)"))
2
Looking at the documentation for read-string and load-string can help point you at which you might need for your given situation.
read-string: Reads one object from the string [argument]
load-string: Sequentially read[s] and evaluate[s] the set of forms contained in the string [argument]
Okay, it looks like you'd probably want load-string if you had multiple forms. Back to the REPL.
user=> (load-string "(println 1) (println 2)")                
1
2
user=> (eval (read-string "(println 1) (println 2)"))
1
As you can see, load-string evaluated the entire string and read-string only returned the first form to eval. The last examples show printing values (and I removed the nil return values), but it's more likely that you'll be concerned with returning something from read-string or load-string. The following example shows what's returned by both functions.
user=> (load-string "1 2")                           
2
user=> (eval (read-string "1 2"))
1
Given our previous results, I'd say load-string and read-string are returning the values you'd expect. It seems like it's easy to default to load-string, but that's not necessarily the case if evaluation time is important to you. Here's a quick snippet to get the point across.
user=> (time (dotimes [_ 100] (eval (read-string "1 2"))))
"Elapsed time: 12.277 msecs"
nil
user=> (time (dotimes [_ 100] (load-string "1 2")))       
"Elapsed time: 33.024 msecs"
nil
One of the applications I previously worked on would write a large number of events to a log each day; the format used to log an event was a Clojure map. If the application was restarted the log would be read and each event would be replayed to get the internal state back to current. We originally started by using load-string; however, start-up time was becoming a problem, and a switch to read-string completely removed the issue.

Like so many examples in programming, there's a reason that two versions exist. It's worth taking the time to see which solution best fits your problem.

 

From http://blog.jayfields.com/2011/03/clojure-eval-ing-string-in-clojure.html

Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}