Clojure Clojure.lang.LazySeq错误
我似乎对clojure I/O(或类型系统)有严重的问题。关键是这个函数,我希望它使用字符串和数字或字符串的集合,并返回与数字相关联的字符串字典,如Clojure Clojure.lang.LazySeq错误,clojure,lazy-sequences,Clojure,Lazy Sequences,我似乎对clojure I/O(或类型系统)有严重的问题。关键是这个函数,我希望它使用字符串和数字或字符串的集合,并返回与数字相关联的字符串字典,如 (costlist '( '("Milk" 4) '("Bread" 2) '("Milk"))) 给予 {“牛奶”4,“面包”2} 定义为 (defn costlist [lst] ;returns list of costs and appropriate names (let [snds (filter (fn
(costlist '( '("Milk" 4) '("Bread" 2) '("Milk")))
给予
{“牛奶”4,“面包”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
这只会让我感到困惑,因为它的任何论点在我看来都不是懒洋洋的。很难给你一个准确的答案,因为你也在使用自己的一些函数(秒和第一)。但是,你应该考虑你是否想把代码>成本清单> /代码>作为你上面给出的引用形式。 上述内容相当于:
((quote ("Milk" 4)) (quote ("Bread" 2)) (quote ("Milk")))
我想你想要的东西更像:
(list '("Milk" 4) '("Bread" 2) '("Milk"))
在您的示例中,最外层的引号导致内部引号被引用 问题在于
snds
是惰性seq,因此(snds lst)
会抛出一个错误<代码>过滤器总是返回一个延迟序列
你的功能也太复杂了。尽量简化:
(defn costlist [lst]
(zipmap (map first lst)
(remove nil? (map second lst))))
现在你可以做你想做的事了:
(costlist (list '("Milk" 4) '("Bread" 2) '("Milk")))
我使用list
是因为quote
阻止对表达式()求值:
因此,您应该避免在构建列表时使用quote
您的解决方案还建议nil
值只能出现在列表的末尾。您可以轻松修复它:
(defn costlist [lst]
(->> (filter (comp #{2} count) lst)
(map vec)
(into {})))
那么,现在
(costlist (list '("Milk" 4) '("Milk") '("Bread" 2)))
也可以。不要在
'(
中使用)。您不想通过引用
来获取引用
。
如果您将列表写为:
'(("Milk" 4)("Bread" 2)("Milk"))
最优雅的可能是:
(def costlist (comp (partial into {})
(partial map vec)
(partial filter second))
近似
(def costlist #(into {} (map vec (filter second %))))
不幸的是,这将创建两个懒惰的seq,其中一个性能更好。
您可以(使用“(clojure.core[reducers:as r])
并编写一个很酷的还原函数:
(def r-fn (comp (r/map vec) (r/filter second)))
(def costlist #(reduce (fn [acc [k v]]
(if v
(assoc acc k v)
acc)) {} %)
这让你不得不
(def costlist #(into {} (r-fn %)))
由于使用reduce conj
将转换为
,您的列表元素将只分配一次
由于散列映射的顺序并不重要,因此您还可以使用userr/fold
。然后,您的列表将被过滤,元素将并行转换为向量(如果您的列表包含512个以上的元素)
根据集合的大小,减缩器可能有点太重。对于示例中的小尺寸,我建议编写自己的减缩函数:
(def r-fn (comp (r/map vec) (r/filter second)))
(def costlist #(reduce (fn [acc [k v]]
(if v
(assoc acc k v)
acc)) {} %)