我在Clojure中有一个关于复发的问题.如果我在循环中有一个let语句,那么recur调用是否可以应用于let语句而不是循环的值?例如,在这种情况下:
(defn someFunction [listA listB] ("do something here...." [new-listA new-listB])) (defn anotherFunction [listA listB] ("do something here...." [new-listA new-listB])) (defn myFunction [firstList secondList] (loop [list1 (someMutation firstList) list2 (someMutation secondList)] (if (= "true" (someCondition)) (let [[newlist1 newlist2] (someFunction list1 list2)] (recur newlist1 newlist2)) (anotherFunction list1 list2) )))
是(recur newlist1 newlist2)应用于循环还是let?有没有一种方法可以跳过这个let语句并直接使用"someFunction"返回的两个值调用recur,假设我不能改变"someFunction"返回带有两个参数的向量这一事实?
recur
总是重复到最近的loop
或函数,无论哪个更靠近recur
表单.它通过编译本质上是一个循环/跳转语句来改变循环变量的值,然后跳回到循环/ fn点.这样它只使用一个堆栈帧并可以全速运行.这种设计有一些有意的权衡:
你不能交错嵌套循环
recur只能是表达式中的最后一件事.
必须有相同数量的args重复为loop/the-function
最后一个要求您保留let表达式或类似的东西,例如解构形式.循环确实允许像函数一样对参数进行解构:
(loop [[a b] [1 2]] (println a b) (if (< a 10) (recur [(inc a) (inc b)]))) 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11
所以你可以编写循环表达式来获取结果 someFunction
直接
(loop [[list1 list2] [(someMutation firstList) (someMutation secondList)]] ... (recur (someFunction ...))