Почему это не повторяется в mapcat? - PullRequest
0 голосов
/ 30 сентября 2018

Почему это recur в mapcat не завершается, в то время как именованный fn эквивалент версии вызова завершается?

(def tree [1 [2 [3 5]] [6 [[1 2] [8 [9 10]]]]])

(defn leaves
  [node]
  (mapcat #(if (vector? %) (leaves %) [%]) node))

(leaves tree)
;; => (1 2 3 5 6 1 2 8 9 10)

(defn leaves-with-recur
  [node]
  (mapcat #(if (vector? %) (recur %) [%]) node))

(leaves-with-recur tree)
;; Never terminates

Если такое использование recur является простым нет-нет, есть ли какая-либо причина, по которой компилятор Clojure не должен перехватывать этот сценарий и предупреждать программиста или даже отказываться от его компиляции?Как, например, для вызовов без хвостовой позиции recur.

1 Ответ

0 голосов
/ 01 октября 2018
#(if (vector? %) (recur %) [%])

является сокращением для

(fn [%]
  (if (vector? %)
    (recur %)
    [%]))

То, что recur будет повторяться для этой анонимной функции, а не для какой-либо внешней, и, поскольку она ничего не меняет, это бесконечный цикл.

Что касается предупреждения - проблема остановки, как известно, является неразрешимой, и существует риск попадания в бесконечный цикл при времени компиляции , даже если просто пытаться поместить некоторые эвристики на место.

...