我似乎对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)))
也会工作。