首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure和html form - clojure.lang.LazySeq不能转换为clojure.lang.IFn

Clojure和html form - clojure.lang.LazySeq不能转换为clojure.lang.IFn
EN

Stack Overflow用户
提问于 2015-05-30 22:57:27
回答 2查看 194关注 0票数 1

我有以下问题:当我在REPL中输入函数时,一切正常,我没有得到任何异常,但是当我从html的输入域中获取clojure函数的输入值时,我得到的clojure.lang.LazySeq不能被强制转换为clojure.lang.IFn exception:

代码语言:javascript
复制
(apply map + 
       (for [i (range (count frequencies-of-words-reviews))]
         (for [j (range (count tokens))]
           (if (= ((nth frequencies-of-words-reviews i)
                     (nth tokens j))
                  nil)
             0
             1)))

输入值已从输入字段中正确获取,因此这不是问题所在……有谁知道问题出在哪里吗?感谢您的建议,我对clojure和clojure中的web编程非常陌生。

EN

回答 2

Stack Overflow用户

发布于 2015-05-31 01:42:56

缩进代码有助于揭示问题的一部分。不幸的是,您还没有说明您试图实现的目标,因此很难提供完整的答案。我要做一些猜测,我认为即使我猜错了,我说的话也会帮助你解决问题。

@bsvingen是对的,有一个漏掉的括号。然而,我猜测问题是在第一个nth之前有一个额外的括号。您不希望将=应用于包含nth的两个表达式吗?取而代之的是,第一个函数被求值,Clojure期望它产生一个函数,因为它出现在列表的开头。如果我们解决这个问题,结果是:

代码语言:javascript
复制
(apply map + 
       (for [i (range (count frequencies-of-words-reviews))]
         (for [j (range (count tokens))]
           (if (= (nth frequencies-of-words-reviews i)
                  (nth tokens j))
             nil)
             0
             1)))

但是,这不是您想要的结果,因为在本例中,如果条件为真,if表达式将返回nil,如果条件为假,if将对"else“执行其默认值,即返回nil。因此,无论发生什么,if表达式都会返回nil。但是,无论如何都会忽略该值,就像0一样。我重写的代码是为每个元素返回1。所以这也不是你想要的。

接下来,你不需要两个for,你可以使用

代码语言:javascript
复制
(for [i ...
      j ...]
  ...)

我的猜测是,您尝试使用=测试的是frequencies-of-words-reviews的键是否等于tokens中的字符串,并且您正在尝试计算获得相等的情况。在这种情况下,代码可能如下所示,在第四行中添加了keys

代码语言:javascript
复制
(apply map + 
       (for [i (range (count frequencies-of-words-reviews))
             j (range (count tokens))]
         (if (= (nth (keys frequencies-of-words-reviews) i)
                (nth tokens j))
           0
           1)))

(请注意,我能够跟踪所有括号并确保它们正确的唯一方法是让我的编辑器格式化代码。当产生的缩进不正确时,我知道我做错了什么。)

然而,仍然有一个问题。您可以将frequencies-of-words-reviews定义为第一个元素是散列映射的列表。这通常会产生错误,因为Clojure假设列表的第一个元素是一个函数。但是,事实证明,散列映射也被视为函数,所以没有错误,但结果是frequencies-of-words-reviews的值为nil。解决方案是引用列表:

代码语言:javascript
复制
(def frequencies-of-words-reviews
  '({"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}))

或者使用向量:

代码语言:javascript
复制
(def frequencies-of-words-reviews 
  [{"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}])

您需要对tokens执行相同的操作

代码语言:javascript
复制
(def tokens ["charging" "excellent" "bit" "great" "bought" "daughter"])

但是,根据我的猜测,我认为您需要合并这两个散列映射。这将需要一些注意,如果他们有一些相同的密钥。merge-with可能对此很有用。我将简单地合并这两个映射:

代码语言:javascript
复制
(def frequencies-of-words-reviews
  (merge {"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}))

最后,如果您尝试对结果值求和,则不需要apply map +,而需要apply +reduce +。结果是:

代码语言:javascript
复制
(apply + 
       (for [i (range (count frequencies-of-words-reviews))
             j (range (count tokens))]
         (if (= (nth (keys frequencies-of-words-reviews) i)
                (nth tokens j))
           0
           1))

这将对一堆0和1求和,并产生结果30。

其他提示:

更习惯的做法是完全避免索引到序列中。看看filtersomeset等等。

票数 0
EN

Stack Overflow用户

发布于 2015-05-31 01:45:08

最直接的问题是这一部分:

代码语言:javascript
复制
((nth frequencies-of-words-reviews i)...

调用函数"nth“将返回一个值,我将调用X。然后你会得到如下结果:

代码语言:javascript
复制
(X (nth tokens j))

在这里,clojure试图将X解释为一个函数(在JVM中作为接口clojure.lang.IFn实现)。

第一次通过循环时,索引i将是映射{"charging“1,"excellent”2,"bit“1,"great”1}。虽然这可能是您想要的,也可能不是您想要的,但它似乎与异常不匹配。

如果你能把一个5行代码的例子粘贴到这里,我们可能很快就能解决这个问题。现在,我怀疑您的编辑器中的内容与粘贴到REPL或此处的内容略有不同。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30547610

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档