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_Lazy Evaluation - Fatal编程技术网

Clojure 进入与分割

Clojure 进入与分割,clojure,lazy-evaluation,Clojure,Lazy Evaluation,这是有道理的: user=> (into {} [[:a 1] [:b 2]]) {:a 1, :b 2} 但这为什么会产生错误呢 user=> (into {} (partition 2 [:a 1 :b 2])) ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44

这是有道理的:

user=> (into {} [[:a 1] [:b 2]])
{:a 1, :b 2}
但这为什么会产生错误呢

user=> (into {} (partition 2 [:a 1 :b 2]))

ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry  clojure.lang.ATransientMap.conj (ATransientMap.java:44)
可以肯定的是:

user=> (partition 2 [:a 1 :b 2])
((:a 1) (:b 2))
into
是否存在惰性序列问题?若然,原因为何


除了解释这不起作用的原因之外,建议使用什么方法将诸如
[:a1:b2]
之类的键值对序列连接到映射中?(
apply conj
似乎也不起作用。)

您可以
apply
将序列应用到
assoc

(apply assoc {:foo 1} [:a 1 :b 2])
=> {:foo 1, :a 1, :b 2}
into对惰性序列有问题吗?若然,原因为何

否,
into
通常用于延迟求值序列。这是惰性的,但每个键/值元组都是一个向量,这就是为什么当
into
减少映射中的对时,它会起作用:

(into {} (map vector (range 3) (repeat :x)))
=> {0 :x, 1 :x, 2 :x}
这不起作用,因为键/值对是列表:

(into {} (map list (range 3) (repeat :x)))
所以区别不在于懒惰;这是由于在地图上使用
conj
转换为
使用
reduce
造成的,它只适用于向量键/值对(或
MapEntry
s):

更新:
assoc
wrapper,用于应用注释中建议的空/nil序列:

(defn assoc*
  ([m] m)
  ([m k v & kvs]
   (apply assoc m k v kvs)))

您可以
将序列应用于
关联

(apply assoc {:foo 1} [:a 1 :b 2])
=> {:foo 1, :a 1, :b 2}
into对惰性序列有问题吗?若然,原因为何

否,
into
通常用于延迟求值序列。这是惰性的,但每个键/值元组都是一个向量,这就是为什么当
into
减少映射中的对时,它会起作用:

(into {} (map vector (range 3) (repeat :x)))
=> {0 :x, 1 :x, 2 :x}
这不起作用,因为键/值对是列表:

(into {} (map list (range 3) (repeat :x)))
所以区别不在于懒惰;这是由于在地图上使用
conj
转换为
使用
reduce
造成的,它只适用于向量键/值对(或
MapEntry
s):

更新:
assoc
wrapper,用于应用注释中建议的空/nil序列:

(defn assoc*
  ([m] m)
  ([m k v & kvs]
   (apply assoc m k v kvs)))
建议的方法是(假设seq arg为非空,正如OP所指出的那样)

Clojure 1.9.0
user=> (apply assoc {} [:a 1 :b 2])
{:a 1, :b 2}
带有
分区
的版本不起作用,因为
分区
返回的块是seqs,当
conj
以向量和实际地图条目的方式绘制地图时,这些块不被视为地图条目

例如,
(转换为{}(map-vec)(分区2[:a1:b2])
会起作用,因为在这里,对在
连接之前被转换为向量

尽管如此,使用
assoc
的方法还是比较可取的,除非有一些特殊情况使得
变成
很方便(比如,如果你有一堆传感器,你想用来预处理你的
分区
生成的对等)。

推荐的方法——(假设seq arg非空,如OP所指出的)–将

Clojure 1.9.0
user=> (apply assoc {} [:a 1 :b 2])
{:a 1, :b 2}
带有
分区
的版本不起作用,因为
分区
返回的块是seqs,当
conj
以向量和实际地图条目的方式绘制地图时,这些块不被视为地图条目

例如,
(转换为{}(map-vec)(分区2[:a1:b2])
会起作用,因为在这里,对在
连接之前被转换为向量


尽管如此,使用
assoc
的方法还是比较可取的,除非有一些特殊情况使得
变成
方便(比如,如果你有一堆传感器,你想用来预处理你的
分区
生成的对等)。

Clojure处理一个2-vec,比如
[:a1]
相当于一个
MapEntry
,执行相当于“自动类型转换”的操作。我尽量避免这种情况,并始终保持显式

(first {:a 1})        => <#clojure.lang.MapEntry [:a 1]>
(conj {:a 1} [:b 2])  => <#clojure.lang.PersistentArrayMap {:a 1, :b 2}>
into
也有同样的问题
(reduce conj)

其他答案已经有3种可行的方法:

(assoc {}   :b 2)             => {:b 2}
(conj  {}  [:b 2])            => {:b 2}
(into  {} [[:a 1] [:b 2]])    => {:a 1, :b 2}
但是,我会避免这些,并坚持使用
哈希映射
排序映射
,这两种方法都避免了空输入序列的问题:

(apply hash-map [])           => {}            ; works for empty input seq
(apply hash-map [:a 1 :b 2])  => {:b 2, :a 1}
如果您的输入序列是成对的列表,
flatte
有时很有用:

(apply sorted-map (flatten  [[:a 1] [:b 2]])) => {:a 1, :b 2}
(apply   hash-map (flatten '((:a 1) (:b 2)))) => {:a 1, :b 2}

附笔。 请注意,这些是不同的:

  • java.util.Map$Entry(在jdk文档中列为“Map.Entry”)
  • clojure.lang.MapEntry
P.P.S 如果您已经有一个映射,并且希望合并成一个键值对序列(可能是空的),只需将
合并到
哈希映射中即可:

(into {:a 1} (apply hash-map []))       => {:a 1}
(into {:a 1} (apply hash-map [:b 2]))   => {:a 1, :b 2}

Clojure将2-vec(如
[:a1]
)视为等同于
MapEntry
,执行相当于“自动类型转换”的操作。我试图避免这种情况,并始终明确表示

(first {:a 1})        => <#clojure.lang.MapEntry [:a 1]>
(conj {:a 1} [:b 2])  => <#clojure.lang.PersistentArrayMap {:a 1, :b 2}>
into
也有同样的问题
(reduce conj)

其他答案已经有3种可行的方法:

(assoc {}   :b 2)             => {:b 2}
(conj  {}  [:b 2])            => {:b 2}
(into  {} [[:a 1] [:b 2]])    => {:a 1, :b 2}
但是,我会避免这些,并坚持使用
哈希映射
排序映射
,这两种方法都避免了空输入序列的问题:

(apply hash-map [])           => {}            ; works for empty input seq
(apply hash-map [:a 1 :b 2])  => {:b 2, :a 1}
如果您的输入序列是成对的列表,
flatte
有时很有用:

(apply sorted-map (flatten  [[:a 1] [:b 2]])) => {:a 1, :b 2}
(apply   hash-map (flatten '((:a 1) (:b 2)))) => {:a 1, :b 2}

附笔。 请注意,这些是不同的:

  • java.util.Map$Entry(在jdk文档中列为“Map.Entry”)
  • clojure.lang.MapEntry
P.P.S 如果您已经有一个映射,并且希望合并成一个键值对序列(可能是空的),只需将
合并到
哈希映射中即可:

(into {:a 1} (apply hash-map []))       => {:a 1}
(into {:a 1} (apply hash-map [:b 2]))   => {:a 1, :b 2}

成功了!谢谢。我很想看到一个解释,解释为什么
into
失败和
assoc
工作。通常Clojure的行为和预期的一样;我想知道我需要知道什么才能“预期”这个。我刚刚发现
(应用assoc{}序列)如果
序列
为空,则
失败。在这种情况下,您可以在另一个答案中使用传感器版本:
(进入{}(映射向量)(分区2[]))
或者如果你发现自己经常这样做,你可以引入一个附加一元重载的助手包装
assoc
,返回地图。如果只是一个或两个地方,那么
if
可能是最简单的方法。这很有效!谢谢。我很乐意看到