views:

194

answers:

2

Hi there.

When I want to read in an S-expression stored in a file into a running Common Lisp program, I do the following:

(defun load-file (filename)
  "Loads data corresponding to a s-expression in file with name FILENAME."
  (with-open-file (stream filename)
    (read stream)))

If, for example, I have a file named foo.txt that contains the S-expression (1 2 3), the above function will return that S-expression if called as follows: (load-file "foo.txt").

I've been searching and searching and have not found an equally elegant solution in Clojure. Any ideas?

Thanks!

+6  A: 

You can do e.g.

(require '[clojure.contrib.io :as io])

(io/with-in-reader (io/file "foo.txt") (read))
; => (1 2 3)

Note that you'll likely want to rebind *read-eval* to false first. Also note that the above works with current contrib HEAD (and will almost certainly work in 1.2 when it's released); for Clojure 1.1, the same functionality is available in the clojure.contrib.duck-streams and clojure.contrib.java-utils namespaces.

Michał Marczyk
Hi, what is the advantage, if any, of this approach over (read-string (slurp "foo.txt"))
jkndrkn
`slurp` / `io/slurp*` slurp the whole contents of the file in, even though `read-string` will only read one whole form and discard the rest. The `with-in-reader` approach will read only a little bit past the first form (due to buffering). Also, you can have more forms in the body of `with-in-reader`; in particular, subsequent invocations of `read` within the same `with-in-reader` form would return further forms from the file. (Try using `[(read) (read)]` as the body to get the initial two forms.) I'd have posted your answer alongside this one had I thought about it, though. :-)
Michał Marczyk
+4  A: 

I found a solution here: http://stackoverflow.com/questions/1885448/how-do-you-evaluate-a-string-as-a-clojure-expression

(read-string (slurp "foo.txt"))

Sorry to bother you, folks ^_^

jkndrkn