1
resposta

Can only recur from tail position

Meu código está assim:

(def max-number-lifes 6)
(declare game)

(defn game-over [message]
  (do
    (println message)
    (System/exit 0)
    )
  )

(defn lost [] ((game-over "You were hang!")))
(defn won [] (game-over "Congrats, you discovered the word!"))

(defn missing-letters [word guesses]
  (remove (fn [letter] (contains? guesses (str letter))) word)
  )

(defn was-word-guessed? [word guesses]
  (empty? (missing-letters word guesses))
  )

(defn read-letter! [] (read-line))

(defn is-guess-right? [word guess] (.contains word guess))

(defn game [lifes word guesses] (
                                 (cond
                                   (= lifes 0) (lost)
                                   (was-word-guessed? word guesses) (won)
                                   :else
                                   (let [guess (read-letter!)]
                                     (if (is-guess-right? word guess)
                                       (do
                                         (println "You guessed right!!")
                                         (recur lifes word (conj guesses guess)))
                                       (do
                                         (println "You guessed was wrong. You lost one life")
                                         (recur (dec lifes) word guesses)))))))

O porblem é que quando executo ele recebo a excessão

#error {
 :cause Can only recur from tail position
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message Syntax error compiling recur at (hangman/core.clj:38:42).
   :data #:clojure.error{:phase :compile-syntax-check, :line 38, :column 42, :source hangman/core.clj, :symbol recur}
   :at [clojure.lang.Compiler analyzeSeq Compiler.java 7114]}
  {:type java.lang.UnsupportedOperationException
   :message Can only recur from tail position
   :at [clojure.lang.Compiler$RecurExpr$Parser parse Compiler.java 6662]}]
 :trace

Como meu código está exatamente com a causa dupla conforme o video, não consegui entender o porquê do erro.

1 resposta

Olá, Gabriel, tudo bem?

Peço desculpas pela demora no retorno a sua mensagem.

A mensagem de erro indica que você só pode utilizar o "recur" em posição de cauda (tail position).

A posição de cauda é quando a chamada recursiva é a última expressão a ser executada dentro do bloco de código. No seu caso, a chamada recursiva está dentro de um bloco "do", que não é uma posição de cauda.

Para corrigir esse erro, você pode mover a chamada recursiva para a posição de cauda, removendo o bloco "do" que envolve a chamada. Ficaria assim:

(if (is-guess-right? word guess)
  (do
    (println "You guessed right!!")
    (recur lifes word (conj guesses guess)))
  (do
    (println "You guessed was wrong. You lost one life")
    (recur (dec lifes) word guesses)))

Dessa forma, a chamada recursiva estará em posição de cauda e o erro não será mais lançado.

Aproveito para informar que o curso ganhou uma versão atualizada: Clojure: programação funcional.

Todavia, vale ressaltar que como você postou sua pergunta há algum tempo é possível que a constante evolução da tecnologia impacte na resolução da sua dúvida. Sendo assim, caso queira se aprofundar neste tema e com conteúdos atualizados, recomendo a formação abaixo:

Espero ter ajudado.

Abraços e bons estudos!