Clojure:只能从尾巴位置重现 [英] Clojure: Can only recur from tail position

查看:47
本文介绍了Clojure:只能从尾巴位置重现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试递归地反转列表,但得到的只能在运行时从尾巴位置重新出现.这到底是什么意思?我的代码如何进行改进才能正常工作?

I'm trying to recursively reverse a list, but am getting Can only recur from tail position upon run. What does this mean precisely and how can my code be improved so it works?

(defn recursive-reverse [coll]
  (loop [coll coll]
    (if (< (count coll) 2) '(coll)
      (conj (first coll) (recur (rest coll)))
      )))

编辑

Oscar解决方案的输出.它适用于列表,但不适用于矢量吗?

Output for Oscar's solution. It works for lists but not vectors?

user=> (= (recursive-reverse [1 2 3 4 5]) (recursive-reverse '(1 2 3 4 5)))
false
user=> (= '(1 2 3 4 5) [1 2 3 4 5])
true
user=> (recursive-reverse [1 2 3 4 5])
[1 2 3 4 5]
user=> (recursive-reverse '(1 2 3 4 5))
(5 4 3 2 1)

推荐答案

错误只能从尾部位置重复发生表示您没有在最后一次调用 recur 函数的递归部分中的表达式-实际上,在您的代码中, conj 是最后一个表达式.

The error Can only recur from tail position means that you're not calling recur as the last expression in the recursive part of the function - in fact, in your code conj is the last expression.

为使代码正常工作而进行的一些改进:

Some improvements to make your code work:

  • 询问集合是否为空作为基本案例,而不是比较其长度是否小于两个
  • conj 的第一个参数而非元素收到 collection
  • 使用 cons 而不是 conj (根据集合的具体类型,会在不同位置添加新元素)是一个更好的主意.="http://clojuredocs.org/clojure_core/clojure.core/conj" rel ="noreferrer">文档).这样,如果输入集合是列表或向量,则返回的集合将被反转(尽管返回的集合的类型始终为 clojure.lang.Cons ,无论输入的类型是输入集合)
  • 请注意,'(coll)是一个包含单个元素(符号 coll )和不是实际集合的列表
  • 要正确反转列表,您需要遍历输入列表,并将每个元素附加到输出列表的开头;为此使用一个累加器参数
  • 要利用尾部递归功能,请在函数的尾部位置调用 recur ;这样,每次递归调用都会占用一定数量的空间,并且堆栈不会无限制地增长
  • Ask if the collection is empty as the base case, instead of comparing if its length is less than two
  • conj receives a collection for its first parameter, not an element
  • It's a better idea to use cons instead of conj (which adds new elements at different places depending on the concrete type of the collection, according to the documentation). In this way the returned collection will be reversed if the input collection is either a list or a vector (although the type of the returned collection will always be clojure.lang.Cons, no matter the type of the input collection)
  • Be aware that '(coll) is a list with a single element (the symbol coll) and not the actual collection
  • For correctly reversing a list you need iterate over the input list and append each element to the beginning of an output list; use an accumulator parameter for this
  • For taking advantage of tail-recursion call recur at the tail position of the function; in this way each recursive invocation takes a constant amount of space and the stack won't grow unbounded

我相信这是您的目标:

(defn recursive-reverse [coll]
  (loop [coll coll
         acc  (empty coll)]
        (if (empty? coll)
            acc
            (recur (rest coll) (cons (first coll) acc)))))

这篇关于Clojure:只能从尾巴位置重现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆