2015-06-11 64 views
5

我刚刚开始学习clojure,并一直在阅读一些简单的例子,然后尽我所能去理解概念。clojure'val'返回这个值是什么?

但是我对val在下面的例子中做了什么感到困惑。这已从Clojure doc示例中获得,用于val

(first {:one :two}) ;; => [:one :two] 

在这里,与hash-map:one一个键和的:two的值被传递给first。在幕后,Clojure将hash-map转换为sequencevectors。由于此sequence中只有一个vector,因此它返回[: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 

如果我尝试致电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返回map。这是解决问题的正确方法吗?

一如既往,感谢您的任何帮助。

+3

地图条目是一个向量,但并非所有向量都是地图条目。 'val'只适用于地图条目。 – noisesmith

+1

... to wit,'(type(first {:one:two}))'=>'clojure.lang.MapEntry' – Thumbnail

回答

6

地图的序列产生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,但矢量[:a 1]不能,因此类转换异常。

您对图所做的操作在高层次上是正确的,更具体一点可能是“对于序列中来自{:a 1:b 2}(即MapEntry值)的每个条目,调用函数val对每个项目(一个MapEntry),并从结果中生成一个序列“。

这将解释为什么像

user=> (map val '([:a 1] [:b 2])) 

同样会引起ClassCastException S作为序列生成Vector元素,不MapEntry元素。

5

val返回地图条目的值,而不是地图。

(first {:one :two})返回所述第一映射条目(尽管它似乎只是一个VEC)

(map val {:one :two})返回的每个条目的值,并且等同于(vals {:one :two})

2
(first {:one :two}) ;; # => [:one :two] (this is a vector right? No, it's not.) 

[:one :two]在这种情况下是一个MapEntry,不是矢量。

相关问题