11

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!

jkndrkn
  • 4,012
  • 4
  • 36
  • 41

2 Answers2

8

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
  • 83,634
  • 13
  • 201
  • 212
  • Hi, what is the advantage, if any, of this approach over (read-string (slurp "foo.txt")) – jkndrkn May 18 '10 at 01:31
  • 2
    `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 May 18 '10 at 01:42
6

I found a solution here: How do you evaluate a string as a clojure expression?

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

Sorry to bother you, folks ^_^

Community
  • 1
  • 1
jkndrkn
  • 4,012
  • 4
  • 36
  • 41