在返回错误中实现范围函数



我正在尝试在 clojure 中实现范围函数,但我的实现返回了一个我无法理解的错误。在这里:

(defn implement-range [a b] (
if (= a b)
(conj nil b)
((conj nil a) (implement-range (inc a) b))))

我正在尝试以递归的方式进行,它还没有完成,因为我遇到了这个错误:

ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn  user/implement-range

我认为这是一个我看不到的括号问题(我是 clojure :) 的新手)。有什么想法吗?

提前感谢您的任何帮助

编辑:

如果我像这样调用函数,我想返回类似 (1 2 3 4) 的东西:

(implement-range 1 5)

你很接近:

(defn implement-range [a b]
(if (>= a b)
'()
(conj (implement-range (inc a) b) a)))
(implement-range 0 5)
=> (0 1 2 3 4)

首先,主要问题是((conj nil a) (implement-range (inc a) b))))试图将(conj nil a)作为一个函数调用,(implement-range (inc a) b)作为参数。我不完全确定你在这里想做什么,但这绝对不是你想要的。

我做了三个更改:

  • 您需要将当前数字conj递归调用的结果。这是"不安全"的递归,因为递归调用不在尾部位置,但是在乱搞时,这没什么大不了的。不过,如果您打算真正使用它,则需要使用另一种方法。

  • 如果输入大于ab,它将爆炸。我通过更改基本情况条件来解决此问题。

  • 您的基本情况没有任何意义。递归停止后,您需要添加到空列表中。

只是旁注,任何时候你看到((,小警钟应该响起。这通常是问题的征兆,除非您变得花哨并写出类似((comp str inc) 1)的东西;其中,表达式中的第一个形式的计算结果为函数。

最简单(也是最经典的)是这样的:

(defn implement-range [a b]
(when (< a b)
(cons a (implement-range (inc a) b))))
user> (implement-range 1 20)
;;=> (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

我做了一些研究,发现以这种方式使用 conj 没有任何意义。所以我想出了这个:

(defn implement-range [a b] (
if (= a b)
b
(flatten (list a (implement-range (inc a) b)))))

因此,如果我使用 1 4 个参数调用函数,结果将是:

(1 2 3 4)

但是,由于我正在尝试实现诸如范围函数之类的函数,因此它需要删除最后一个元素。

编辑 1

我编写的最后一个函数如下所示:

(defn implement-range [a b] (
if (= a b)
nil
(remove nil? (flatten (list a (implement-range (inc a) b))))))

编辑 2经过更多的研究,我想出了另一种解决这个问题的方法,用更少的代码行:

(defn new-range [a b]
(take (- b a) (iterate inc a)))

最新更新