【问题标题】:Clojure - recur applies to loop or let statement?Clojure - recur 适用于循环或 let 语句?
【发布时间】:2017-06-04 14:14:50
【问题描述】:

我在 Clojure 中有一个关于 recur 的问题。如果我在循环中有一个 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”返回一个带有两个参数的向量的事实?

【问题讨论】:

    标签: loops recursion clojure let


    【解决方案1】:

    recur 总是递归到最接近的loop 或函数,以更接近recur 的形式为准。它通过编译本质上是一个循环/跳转语句来完成此操作,该语句更改循环变量的值,然后跳回到循环/fn 点。这样它只使用一个堆栈帧并且可以全速运行。这种设计有一些有意的取舍:

    • 不能交错嵌套循环
    • recur 只能是表达式中的最后一项。
    • 必须有与循环/函数相同数量的参数才能重复

    最后一个要求您保留 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 ...))
    

    【讨论】:

      【解决方案2】:

      let 不是有效的重复目标。

      您也许可以在 let 中进行设置以解构向量,因此也可以跳过 let。

      另外,引用 true 有点奇怪。这在你的控制之下吗?如果是这样,应该只寻找布尔值 true 然后可以说(if (somecondition)...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多