【问题标题】:Clojure and html form - clojure.lang.LazySeq cannot be cast to clojure.lang.IFnClojure 和 html 表单 - clojure.lang.LazySeq 无法转换为 clojure.lang.IFn
【发布时间】:2015-05-30 14:57:26
【问题描述】:

我有以下问题:当我在 REPL 中输入函数时,一切工作正常并且我没有得到任何异常,但是当我从 html 的输入字段中获取我的 clojure 函数的输入值时,我得到了 clojure.lang对于我的这部分代码,.LazySeq 无法转换为 clojure.lang.IFn 异常:

(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 中的网络编程很陌生。

【问题讨论】:

  • 您能否提供词频评论和标记的示例值? (此外,如果您在多行中使用适当的缩进编写代码,这将更容易阅读。)
  • (deffrequency-of-words-reviews ({"charging" 1, "excellent" 2, "bit" 1, "great" 1} , {"bought" 1, "daughter" 1 }) (def tokens (“收费”“优秀”“位”“伟大”“买”“女儿”))
  • 我很抱歉缩进不好。 ://
  • 您在此处缺少括号。如果我在最后添加它,频率的单词评论评估为零 - 我假设这不是你想要的值?
  • 这里有几个列表。评估列表的方式是将列表的第一个值作为函数,其余的都是该函数的参数。这似乎不是你想要的?比如“充电”不是函数?

标签: exception casting clojure


【解决方案1】:

缩进代码有助于揭示部分错误。不幸的是,您还没有说明您要完成的工作,因此很难提供完整的答案。我会做一些猜测,我想即使我猜错了,我所说的也会帮助你解决问题。

@bsvingen 是正确的,缺少括号。但是,我的猜测是问题在于第一个 nth 之前有一个额外的括号。你不希望= 应用于包含nth 的两个表达式吗?它没有。相反,第一个被求值,Clojure 期望它产生一个函数,因为它出现在列表的开头。如果我们解决这个问题,结果是:

(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。你可以使用

(for [i ...
      j ...]
  ...)

我的猜测是你试图用= 测试的是frequencies-of-words-reviews 的键是否等于tokens 中的字符串,并且你试图计算你得到的情况平等。在这种情况下,代码可能如下所示,在第 4 行添加 keys

(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。解决方法是引用列表:

(def frequencies-of-words-reviews
  '({"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}))

或使用向量:

(def frequencies-of-words-reviews 
  [{"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}])

你需要对tokens做同样的事情:

(def tokens ["charging" "excellent" "bit" "great" "bought" "daughter"])

但是,根据我的猜测,我认为您需要合并两个哈希映射。如果他们有一些相同的键,这将需要一些小心。 merge-with 可能对此有用。我只是将两张地图合并:

(def frequencies-of-words-reviews
  (merge {"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}))

最后,如果你想对结果求和,你不需要apply map +,你需要apply +reduce +。结果是:

(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

【讨论】:

    【解决方案2】:

    最直接的问题是这部分:

    ((nth frequencies-of-words-reviews i)...
    

    调用函数“nth”将返回一个值,我将调用 X。然后你有类似的东西:

    (X (nth tokens j))
    

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

    第一次通过循环,索引i将是地图{“充电”1,“优秀”2,“位”1,“伟大”1}。虽然这可能是也可能不是您想要的,但它似乎与例外情况不符。

    如果您可以将一个有效的 5 行示例粘贴在一起并将其粘贴到此处,我们可能会很快解决问题。现在,我怀疑您在编辑器中的内容与您粘贴到 REPL 或此处的内容略有不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      • 2023-03-15
      • 1970-01-01
      相关资源
      最近更新 更多