2012-07-25 17 views
5

ユーザーから対話的にy/n(はい/いいえ)の回答を得ようとする関数を書いた。それは答えが有効であるかどうかをテストしていない場合は、もう一度ユーザーを勧誘:onループリークを改善する

(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)))))) 

ループRECURと上記のバージョンは仕事をしていませんが、私はより良い(より機能的)な方法がなければならないというしつこい感じを持っていますこれを行う。私は一度だけread-line呼び出しをすることを好むだろう。誰もこのシナリオではループリカバリを使用せず、おそらくいくつかの(Clojure組み込み)マクロを代わりに使用する代替バージョンを提案できますか?

答えて

7

小さな子供が、満足のいく返事を得るまで、同じ質問を無限に繰り返すことを考えて、コード内で同じことをしてください。つまり、無限の質問のストリームから最初の有効な答えを取ることです。

未テストですが、これはすべきことです。

(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))) 

また、2つの関数はあなたを気にすれば、結合letに「尋ねる」を定義できます。

+0

これはきちんとしています。私はそれが動作することをテストしました。しかし、私はあなたのアプローチに関する質問があります。「繰り返し」は頼むように怠惰な呼び出しを行い、遅延関数は一度に32のチャンクを評価し、32の呼び出しがあってもよいと考えました。私のテストでは、私はそれが起こらないことがわかります。 '最初の'はClojureに32(サンクサイズ)をオーバーライドし、1回だけ呼び出すように指示しますか? – Don

+0

LazySeq(https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LazySeq.java)のソースを読んでいる場合は、項目が1つで評価されていることがわかります時間。あなたが言及している投稿を見たことがありますが、それがいつ真実であったかはわかりません。 – Ben

+0

フォローアップありがとう。 – Don

関連する問題