Clojure:正在评估的返回值

Clojure:正在评估的返回值,clojure,classcastexception,Clojure,Classcastexception,*简单问题:为什么此函数在求值时抛出异常?* 如果字符串中存在重复项,则在查找重复项时会引发类强制转换异常 在字符串没有重复项的情况下,将抛出NullPointerException *代码* 您的问题是(=0(count str in))从未更改,因此您最终尝试在nil上首先调用。[EDIT:我错了,您的代码实际上是按原样工作的——if语句只是一个不可操作的语句。我希望您喜欢这个答案的其余部分。] 相反,您应该在recur中的list Rem上调用next(而不是rest),并在if测试中

*简单问题:为什么此函数在求值时抛出异常?*

  • 如果字符串中存在重复项,则在查找重复项时会引发类强制转换异常

  • 在字符串没有重复项的情况下,将抛出NullPointerException

*代码*


您的问题是
(=0(count str in))
从未更改,因此您最终尝试在
nil
上首先调用
。[EDIT:我错了,您的代码实际上是按原样工作的——if语句只是一个不可操作的语句。我希望您喜欢这个答案的其余部分。]

相反,您应该在
recur
中的
list Rem
上调用
next
(而不是
rest
),并在
if
测试中直接使用
list Rem
,使用
next
的属性为空序列返回nil。下面是我将如何重写您的代码:

(defn first-duplicate [in]
  (loop [seen #{}
         remain (seq in)]
    (when-let [[head & tail] remain]
      (if (contains? seen head)
        head
        (recur (conj seen head) tail)))))
变化:

  • 小写名称
  • 无需在
    next
    rest的输出上调用
    seq
  • 对于集合,
    包含?
    (检查键是否存在)比
    某些快(对元素运行谓词,直到某个元素生成真实值)
  • 集合文字
  • 在测试失败时使用
    when
    返回
    nil
  • 当让
解构并绑定第一个字符和其余字符时,使用


风格变化:

  • 名称更改为不太具体(例如,不限于字符串)
  • 更改循环局部变量的顺序,使递归看起来更像结构递归
  • 将循环局部变量放在单独的行上

这是一个有点奇怪的问题的最佳答案。最终的问题是,由于其他一些问题,我将函数调用封装在repl的另一个闭包中。我同意使用when-let构造显然更好。我喜欢这里编写的最终函数,但是关于rest/next的建议是你能给出的最糟糕的建议,所以幸运的是,该函数既不使用rest也不使用next。接下来是返回nil的函数;rest将返回一个空的seq(这是真实的)。我不应该被允许在不首先通过REPL运行示例的情况下谈论rest和next。我有一半的时间会把它们颠倒过来。。。
(defn first-duplicate [in]
  (loop [seen #{}
         remain (seq in)]
    (when-let [[head & tail] remain]
      (if (contains? seen head)
        head
        (recur (conj seen head) tail)))))