我似乎对Clojure I / O(或类型系统)有讨厌的问题。关键是这个函数,我希望它消耗字符串和数字或字符串集合的集合,并返回与数字关联的字符串字典,例如

(costlist '( '("Milk" 4) '("Bread" 2) '("Milk")))


给予

{"Milk" 4, "Bread" 2 }

被定义为

(defn costlist [lst]
    ;returns list of costs and appropriate names
          (let  [snds (filter (fn [x] (not (identical? nil x))) (seconds lst))]
          (zipmap
                   (firsts (take (count snds) (firsts lst)))
                   (snds  lst))))


消费clojure.lang.PersistentList类型的列表(我从clojure.lang.LazySeq转换后)时抛出错误消息

clojure.lang.LazySeq cannot be cast to clojure.lang.IFn


这只是让我感到困惑,因为它的任何参数对我来说似乎都不是LazySeq。

最佳答案

问题在于snds是延迟序列,因此(snds lst)引发错误。 filter始终返回惰性序列。

您的功能也太复杂了。尝试使其更简单:

(defn costlist [lst]
  (zipmap (map first lst)
          (remove nil? (map second lst))))


现在,您可以执行想要的操作:

(costlist (list '("Milk" 4) '("Bread" 2) '("Milk")))


我正在使用list,因为quote阻止对表达式(see ToBeReplaced's answer)求值:

=> '( '("Milk" 4) '("Bread" 2) '("Milk"))
((quote ("Milk" 4)) (quote ("Bread" 2)) (quote ("Milk")))


因此,您应该避免使用quote来构建列表。

您的解决方案还建议nil值只能出现在列表的末尾。您可以轻松修复它:

(defn costlist [lst]
  (->>  (filter (comp #{2} count) lst)
        (map vec)
        (into {})))


所以,现在

(costlist (list '("Milk" 4) '("Milk") '("Bread" 2)))


也会工作。

10-05 18:50