clojure recur vs imperative loop

前端 未结 2 1641
面向向阳花
面向向阳花 2021-02-04 13:18

Learning Clojure and trying to understand the implementation:

What\'s the difference from:

(def factorial
  (fn [n]
    (loop [cnt n acc 1]
       (if (z         


        
2条回答
  •  一整个雨季
    2021-02-04 13:40

    One way to look at loop/recur is that it lets you write code that is functional, but where the underlying implementation ends up essentially being an imperative loop.

    To see that it is functional, take your example

    (def factorial
      (fn [n]
        (loop [cnt n acc 1]
          (if (zero? cnt)
            acc
            (recur (dec cnt) (* acc cnt))))))
    

    and rewrite it so that the loop form is broken out to a separate helper function:

    (def factorial-helper
      (fn [cnt acc]
        (if (zero? cnt)
          acc
          (recur (dec cnt) (* acc cnt)))))
    
    (def factorial'
      (fn [n]
        (factorial-helper n 1)))
    

    Now you can see that the helper function is simply calling itself; you can replace recur with the function name:

    (def factorial-helper
      (fn [cnt acc]
        (if (zero? cnt)
          acc
          (factorial-helper (dec cnt) (* acc cnt)))))
    

    You can look at recur, when used in factorial-helper as simply making a recursive call, which is optimized by the underlying implementation.

    I think an important idea is that it allows the underlying implementation to be an imperative loop, but your Clojure code still remains functional. In other words, it is not a construct that allows you to write imperative loops that involve arbitrary assignment. But, if you structure your functional code in this way, you can gain the performance benefit associated with an imperative loop.

    One way to successfully transform an imperative loop to this form is to change the imperative assignments into expressions that are "assigned to" the argument parameters of the recursive call. But, of course, if you encounter an imperative loop that makes arbitrary assignments, you may not be able to translate it into this form. In this view, loop/recur is a much more constrained construct.

提交回复
热议问题