clojure.lang.Cons无法强制转换为Clojure.lang.Ifn

时间:2018-04-05 22:02:14

标签: clojure

大家好,我最近一直试图学习一门新语言,而且我碰到了Clojure,它看起来像一个真正有趣的语言,因为我从来没有听说过函数式编程,即使我曾经使用过在那之前使用JavaScript之类的JavaScript,我会停止谈论并解决问题。

我一直致力于解决https://github.com/gigasquid/wonderland-clojure-katas问题,更具体地解决双重问题。我想我已经找到了一个解决方案,但它发送给我这篇文章标题的错误。我已经阅读了这个错误,似乎它会在您希望编译器需要一个函数时触发,但它没有。以下是我的解决方案的完整代码,看看你是否可以帮我解决这个问题:

(ns doublets.solver
  (:require [clojure.java.io :as io]
            [clojure.edn :as edn]
            [clojure.set :as set]))

(def words (-> "words.edn"
               (io/resource)
               (slurp)
               (read-string)))

(defn linked-word [word word-list]
  (some #(when (= (count (set/difference (into #{} (seq %))
                                         (into #{} (seq word)))) 1) %)
        word-list))

(defn doublets [word1 word2]
  (let [n (count word1) v (cons word1 (filter #(= (count %) n)
                              (remove #{word1} words)))]
    (tree-seq #(and (linked-word (% 0) %) (not= (% 0) word2))
              #(cons (linked-word (% 0) (rest %))
                (remove #{(% 0)} (rest %))) v)))

正如您所看到的,cons是一个函数,因此错误似乎是上述情况。

任何帮助将不胜感激。 谢谢你提前!!!!

1 个答案:

答案 0 :(得分:3)

我可以在下载words.edn文件并使用(doublets "bank" "loan")运行后重现错误。我认为问题在于这些表达方式:

 (% 0)

你在几个地方。我看到你是cons-ing一些东西,所以这可能是一个线索。什么是(% 0)应该做的? 如果你想要第一个字符,只需说出(first xyz)或其他内容。

我还会打破匿名函数#(...)并给它们真实姓名。

更新

我的猜测似乎是正确的,因为这个实验显示:

(cons 1 [2 3]) => (1 2 3)
(class (cons 1 [2 3])) => clojure.lang.Cons

(vec (cons 1 [2 3])) => [1 2 3]
(class (vec (cons 1 [2 3]))) => clojure.lang.PersistentVector

好的,重写如下:

(defn doublets [word1 word2]
  (let [n (count word1)
        v (vec (cons word1 (filter #(= (count %) n)
                             (remove #{word1} words))))]
    (tree-seq
      #(and
         (linked-word (% 0) %)
         (not= (% 0) word2))
      #(vec (cons (linked-word (% 0) (rest %)))
         (remove #{(% 0)} (rest %)))
      v)))

新错误:java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

我们需要的是线索!

我们正在评估符号,而不是字符串!问题是read-string,这是您阅读 源代码 的方式,而不是字符串之类的数据。删除read-string

(def words (-> "words.edn"
             (io/resource)
             (slurp)))

我们现在在这一行上收到一个新错误:

    v (vec (cons word1 (filter #(= (count %) n)
                         (remove #{word1} words))))]

ERROR in (dotest-line-40) (RT.java:664)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.UnsupportedOperationException: 
             count not supported on this type: Character

因此,您的seq创建了类似“foo”=>的内容[\ f \ o \ o],然后你试着说(count \f)。您不能计算单个字符,只能计算字符串。

我会让你从那里调试它。