Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Improving on loop-recur

Tags:

clojure

I wrote a function that tries to get a y/n (yes/no) answer from a user interactively. It tests if the answer is valid and if not, solicits the user again:

(defn get-valid-answer [question]
   (println  question)
   (loop []
     (let [ans (.trim (read-line))]
        (if (#{"y" "n"} ans)
            ans
            (do (println "Please answer \"y\"[yes] or \"n\"[no] only!")
                (recur) )))))

The above version with loop-recur does the job but I have nagging feeling that there must be a better (more functional) way to do this. I would prefer to have the read-line call made just once. Could anyone suggest an alternative version not using loop-recur in this scenario but possibly using some (Clojure builtin) macro instead?

like image 960
Don Avatar asked Jul 25 '12 20:07

Don


1 Answers

Think of a small child asking the same question endlessly until it gets a satisfactory reply, then do the same thing in code. That is to say, take the first valid answer from an endless stream of questions.

Untested, but this should do the trick.

(defn ask []
  (println "Please answer \"y\"[yes] or \"n\"[no]:")
  (.trim (read-line)))

(defn get-valid-answer [question]
  (println question)
  (->> (repeatedly ask)
       (filter #{"y" "n"})
       (first)))

You could also define 'ask' in a let binding, if two functions bothers you.

like image 102
Ben Avatar answered Nov 15 '22 07:11

Ben