10

I am writing a function for my Clojure program that reads user input from the keyboard. If the user enters invalid input, the user is warned and then prompted again. When using a procedural style in a language like Python, I would do something like this:

while 1:
    value = input("What is your decision?")
    if validated(value):
        break
    else:
        print "That is not valid."

The best I can come up with in Clojure is this:

(loop [value (do
               (println "What is your decision?")
               (read-line))]
  (if (validated value)
    value
    (recur (do
             (println "That is not valid.")
             (println "What is your decision?")
             (read-line)))))

This works, but it is redundant and seems verbose. Is there a more Lispy/Clojurey way to do this?

2 Answers 2

21
(defn input []
   (println "What is your decision?")
   (if-let [v (valid? (read-line))]
      v
      (do
         (println "That is not valid")
         (recur)))
Sign up to request clarification or add additional context in comments.

Comments

8

Factor out the println/read-line combo into a get-line function:

(defn get-input [prompt]
  (println prompt)
  (read-line))

(defn get-validated-input []
  (loop [input (get-input "What is your decision?")]
    (if (valid? input)
      value
      (recur (get-input "That is not valid.\nWhat is your decision?")))))

This is basically what your Python version does; the difference is that get-input is built-in for Python.

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.