在clojure返回错误中实现范围函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在clojure返回错误中实现范围函数相关的知识,希望对你有一定的参考价值。
我试图在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
当前的数字到递归调用的结果。这是“不安全”的递归,因为递归调用不在尾部位置,但在乱搞时,这不是什么大问题。如果您打算将其用于实际,则需要使用替代方法。 - 如果输入大于
b
的a
,它将会爆炸。我通过改变基本情况来解决这个问题。 - 你的基础案例没有任何意义。递归停止后,您将要添加到空列表。
只是一个旁注,任何时候你看到((
,小闹铃应该会消失。这往往是一个问题的迹象,除非你得到幻想并写一些像((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)
但是,因为我试图实现像range函数这样的函数,所以它还需要删除最后一个元素。
编辑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)))
以上是关于在clojure返回错误中实现范围函数的主要内容,如果未能解决你的问题,请参考以下文章
在 Laravel 4 中实现 Remember Me 函数会返回错误