Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure Clojure.lang.LazySeq错误_Clojure_Lazy Sequences - Fatal编程技术网

Clojure Clojure.lang.LazySeq错误

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

我似乎对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 [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
转换为
,您的列表元素将只分配一次

由于散列映射的顺序并不重要,因此您还可以使用user
r/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)) {} %)