我刚刚开始学习clojure,并且已经阅读了一些简单的例子,然后尽力为rtfm提供概念。
但是我对val
在下面的示例中所做的事情感到有些困惑。这取自val的Clojure doc示例。
(first {:one :two}) ;; => [:one :two]
此处,密钥为hash-map
且值为:one
的{{1}}正在传递给:two
。在幕后,Clojure将此first
转换为hash-map
sequence
。由于此vectors
中只有一个vector
,因此会返回sequence
。
[:one :two]
如果我尝试拨打(val (first {:one :two})) ;; => :two
(val [:one :two]) ;; => ClassCastException clojure.lang.PersistentVector cannot be cast to java.util.Map$Entry
(val {:one :two}) ;; => ClassCastException clojure.lang.PersistentArrayMap cannot be cast to java.util.Map$Entry
一个(我认为)a val
(我意识到它实际上是一个"持久阵列地图"),我得到了例外情况如上所示。
我也对以下内容感到困惑:
hash-map
为什么我不能将(first {:one :two}) ;; # => [:one :two] (this is a vector right?)
(val [:one :two]) ;; # => ClassCastException (why doesn't this give back the same result as the example above?)
的结果插入(first {:one :two})
并得到相同的结果?
此外,页面上列出的另一个示例如下:
val
这是我如何阅读该行。选择(map val {:a 1 :b 2}) ;; => (1 2)
array-map
。对于每个键值对,请在对上调用{:a 1 :b 2}
以返回值。从结果调用val
返回sequence
。这是阅读问题的正确方法吗?
一如既往,感谢您的帮助。
答案 0 :(得分:7)
地图序列会产生MapEntry
值,如您所述,它们看起来像是可以与矢量进行比较
user=> (= (first {:a 1 :b 2}) [:a 1])
true
但不是同一个班级
user=> (= (class (first {:a 1 :b 2})) (class [:a 1]))
false
因此虽然(first {:a 1})
的repl上的输出看起来像一个向量,但它不是MapEntry
,所以它可以传递给val
,但是向量{ {1}}不能,因此类强制转换异常。
您对地图正在执行的操作在高级别上是正确的,更具体的可能是“对于来自{:a 1:b 2}的序列中的每个条目(这是MapEntry值),请调用函数val每个项目(一个MapEntry),并从结果“。
生成一个序列这将解释为什么像
[:a 1]
将导致与序列生成user=> (map val '([:a 1] [:b 2]))
元素相同的ClassCastException
s,而不是Vector
元素。
答案 1 :(得分:6)
val
返回地图条目的值,而不是地图。
(first {:one :two})
返回第一个地图条目(尽管它似乎只是一个vec)
(map val {:one :two})
返回每个条目的值,相当于(vals {:one :two})
答案 2 :(得分:3)
(first {:one :two}) ;; # => [:one :two] (this is a vector right? No, it's not.)
在这种情况下, [:one :two]
是MapEntry
,而不是矢量。