clojure: как использовать recur в операторе if

Отказ от ответственности: я изучаю clojure.

Вот простой пример, который я пытаюсь запустить:

(ns ClojureTest.core)

(let [input (read-line)]
  ;if user input = "x"
  (if (= "x" input)
    ;stop accepting input
    (println "Exit")
    ;else output the input and continue accepting input
    (
      (println input)
      (recur)
    )
  )
)

Теперь я получаю эту ошибку, которая, я думаю, имеет смысл, потому что я не знаком с синтаксисом:

Exception in thread "main" java.lang.UnsupportedOperationException: Can only recur from tail position, compiling:(ClojureTest/core.clj:8:7)

Как это исправить?

Дополнительные вопросы:

  1. Когда я нажимаю "запустить" в Eclipse (как я сделал бы с Java), я открываю не только консоль, но и это окно "REPL". Зачем это нужно и для чего это нужно?
  2. Когда я нажимаю "запустить", запуск приложения занимает довольно много секунд. Есть ли способ сделать это быстрее?
  3. Когда мне нужно отредактировать код и перезапустить приложение, я получаю это сообщение: "Выбор не может быть запущен, и недавние запуски отсутствуют". Что это такое и почему это не позволило мне перезапустить мой код? Если я подожду некоторое время, я смогу запустить его снова.

1 ответ

Решение

В данном конкретном случае вам не хватает do в "остальном" предложении if:

(do
  (println input)
  (recur))

Без do, у тебя есть ((println input) (recur)), который выглядит как вызов функции с возвращаемым значением (println input) будучи функцией для вызова и (recur) будучи выражением аргумента и так, а не в хвостовой позиции.

(Очевидно, (println input) вернется nil и попытка вызвать это как функцию будет бросать NullPointerException, но это не имеет значения здесь - это будет ошибка времени выполнения, тогда как recurпроблема "не в хвосте" обнаруживается во время компиляции.)

Другие вопросы по тегам