3

I would like to read the entire string into a list, but not evaluate it. wtf? is the function or mix of functions which I can not find to do this.

user=> (wtf?  " S  I I ( S I I)")
(S I I (S I I))

The function should also work as:

user=> (last (wtf?  " S  I I ( S I I)"))
(S I I)

read-string returns only the first object, while load-string returns them all, but tries to evaluate them.

2 Answers 2

2

This is what I use:

(defn safe-read
  "Evaluate the string in a safe way"
  [s]
  (binding [*read-eval* false]
    (read-string s)))

From the doc:

"When set to logical false, the EvalReader (#=(...)) is disabled in the read/load in the thread-local binding. Example:

(binding [*read-eval* false] (read-string \"#=(eval (def x 3))\"))

So what it does is read the string as usual, but disable the evaluation.

Thus you can use this function to read printed out maps, lists and vectors, without the fear to evaluate malicious code. (Ok I'm sure to what extend this is safe, but for day-to-day usage it does the job).

Sign up to request clarification or add additional context in comments.

1 Comment

Works perfectly, but it seems like magic. How does it make read-string read all of the objects?
2

I am such a noob. I am glad to find out about the safe read, but it seems that my original issue was solved by adding ()'s around the form, which I did inadvertently when trying the safe-read.

user=> (read-string  "( S  I I ( S I I))")
(S I I (S I I))

user=> (last (read-string  "( S  I I ( S I I))"))
(S I I)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.