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 基于atom和map函数创建新值_Clojure - Fatal编程技术网

Clojure 基于atom和map函数创建新值

Clojure 基于atom和map函数创建新值,clojure,Clojure,我希望迭代atom中的值以创建新集合(但不更新atom)。 我有原子的下一个定义: 让[st(atom{})]现在我想做这样的事情: (-> (seq (keys @st)) (map (fn [key] [key (get @st key)])))) 提供的例子是简化的,但即使在这种情况下,我也有问题。 我收到下一个错误: java.lang.IllegalArgumentException: Don't know how to create ISeq from: exampl

我希望迭代atom中的值以创建新集合(但不更新
atom
)。 我有原子的下一个定义:
让[st(atom{})]
现在我想做这样的事情:

(-> (seq (keys @st))
    (map (fn [key] [key (get @st key)]))))
提供的例子是简化的,但即使在这种情况下,我也有问题。 我收到下一个错误:

java.lang.IllegalArgumentException: Don't know how to create ISeq from: example.test$init$reify__2273$fn__2275
        at clojure.lang.RT.seqFrom(RT.java:505)
        at clojure.lang.RT.seq(RT.java:486)
        at clojure.core$seq.invoke(core.clj:133)
        at clojure.core$map$fn__4245.invoke(core.clj:2551)
        at clojure.lang.LazySeq.sval(LazySeq.java:40)
        at clojure.lang.LazySeq.seq(LazySeq.java:49)
        at clojure.lang.RT.seq(RT.java:484)
        at clojure.core$seq.invoke(core.clj:133)
        at clojure.core$print_sequential.invoke(core_print.clj:46)
        at clojure.core$fn__5457.invoke(core_print.clj:147)
        at clojure.lang.MultiFn.invoke(MultiFn.java:231)
        at clojure.core$pr_on.invoke(core.clj:3392)
        at clojure.core$pr.invoke(core.clj:3404)
        at clojure.lang.AFn.applyToHelper(AFn.java:154)
        at clojure.lang.RestFn.applyTo(RestFn.java:132)
        at clojure.core$apply.invoke(core.clj:624)
        at clojure.core$print.doInvoke(core.clj:3449)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.core$apply.invoke(core.clj:624)
        at clojure.core$print_str.doInvoke(core.clj:4391)
        ...

实际上,只使用
@st
是可以的-原子的值是不可变的。如果要修改atom,则不会影响以前检索到的值(假设您使用的是Clojure数据结构)。举例说明:

(def a (atom {:a 1})) ; => #'user/a
(def b @a) ; => #'user/b
(reset! a {:a 2}) ; => {:a 2}
b ; => {:a 1}
“线程优先”宏(
->
)将上一个表达式返回的值插入下一个表达式的第二个位置,即函数之后。在您的示例中,这会导致
映射
函数调用的参数顺序错误(函数应该是第一个,集合应该是第二个)。这就是例外

在这种情况下,您应该使用“thread last”宏(
->
)将值插入下一个函数调用的最后一个位置:

(let [st (atom {:a 1 :b 2})]
  (->> (seq (keys @st))
       (map (fn [key] [key (get @st key)]))))
;; returns: ([:b 2] [:a 1])
但是,这可以简化为以下内容,因为映射可以作为seq直接遍历,每个元素都是键和值的向量,就像您尝试做的那样:

(let [st (atom {:a 1 :b 2})]
  (seq @st))
;; returns: ([:b 2] [:a 1])
如果希望在运行过程中转换这些值,还可以利用,例如通过调用
map

(let [st (atom {:a 1 :b 2})]
  (map (fn [[k v]] [k (+ v 1)]) @st))
;; returns: ([:b 3] [:a 2])

因此,使用该函数声明为您提取键和值。

使用->>而不是->(map希望序列作为最后一个参数,而不是第一个参数)您是对的!这是一个非常愚蠢的问题——今天的代码太多了。我知道这不是真正的代码,但你不应该对atom进行两次去引用。我没有为添加元素添加代码,因为我认为它不会改变anything@baju删除了第一部分-确实,将
->
替换为
->
可以修复示例中的异常。不过,不需要手动复制数据。