Как закончить dotimes clojure - PullRequest
       1

Как закончить dotimes clojure

0 голосов
/ 02 декабря 2018

Я пытаюсь угадать числовую игру в clojure, но все время получаю сообщение об ошибке: Я могу вернуться только из хвостовой позиции

(def n (rand-int 100))

(prn n)

(println "You have 10 guesses :D")
(println "HINT: My number is between 1 and 100")

(dotimes [i 10]
  (def guess (read-line))
  (if (= guess str(n))
    (recur (println "Correct!") (println "Incorrect"))))

(Я новичок в clojure)

Ответы [ 3 ]

0 голосов
/ 02 декабря 2018

dotimes используется для выполнения тела для побочных эффектов, которые дают точное количество;нет никаких средств для break - кроме броска

loop (или функций) являются recur целями.Затем вам нужно будет отсчитать количество попыток, чтобы вы могли остановиться, если пользователь не угадал:

(loop [attempts 10]
  ; ...
  (recur (dec attempts)))

Есть и другие проблемные вещи:

  • Неdef внутри других форм.Вместо этого используйте let.
  • str(n) сгенерирует бросок, поскольку попытается вызвать n (ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn)
  • recur, используя println, выглядит подозрительно, посколькуprintln всегда возвращает ноль
0 голосов
/ 03 декабря 2018

, хотя это не рекомендуется и противоречит закону даже думать о коротком замыкании исполнения таким образом, это все еще вполне возможно с макросами (исключительно для образования и развлечения)

(defmacro return [& x]
  `(list '~'return (do ~@x)))

(defmacro dotimes+ [[i n] & body]
  `(loop [~i 0 res# nil]
     (cond (and (list? res#) (= '~'return (first res#))) (second res#)
           (< ~i ~n) (recur (inc ~i) (do ~@body))
           :else res#)))

можно использовать так:

user> (dotimes+ [i 10]
        (println i)
        (if (== i 5) (return :short-circuited)))
;; 0
;; 1
;; 2
;; 3
;; 4
;; 5
:short-circuited

user> (dotimes+ [i 10]
        (println i)
        (if (== i 5) (return)))
;; 0
;; 1
;; 2
;; 3
;; 4
;; 5
nil

user> (dotimes+ [i 10]
        (println i))
;; 0
;; 1
;; 2
;; 3
;; 4
;; 5
;; 6
;; 7
;; 8
;; 9
nil

обратите внимание, что он по-прежнему ожидает, что макрос return будет вызываться в хвостовой позиции (аналогично recur в loop макросе)

(dotimes+ [x 4]
  (println "attempt" (inc x))
  (let [answer (read-line)]
    (println "answer is:" answer)
      (if (= answer "yes")
        (return "YEAH!!!")
        (println "WRONG!"))))
0 голосов
/ 02 декабря 2018

Как вы заканчиваете dotimes?Вы неПопробуйте использовать loop вместо этого.С вашим кодом много проблем, но это только начало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...