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. Когда мне нужно отредактировать код и перезапустить приложение, я получаю это сообщение: «Выделение не может быть запущено, а последних запусков нет». Что это такое и почему это не позволяет мне перезапустить мой код? Если я подожду некоторое время, я могу запустить его снова.

person Caballero    schedule 15.09.2013    source источник


Ответы (1)


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

(do
  (println input)
  (recur))

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

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

person Michał Marczyk    schedule 15.09.2013