使用update和inc更新原子失败

时间:2019-05-03 08:27:15

标签: clojure clojurescript

我有一个原子(在ClojureScript中):

(def player
  (atom {:episode 0 ...}))

我想将:episode加1:

(swap! player update :episode inc)

这在Lein REPL上效果很好。

但是,运行时会抛出:

mfp.js:5808 Uncaught Error: No protocol method IDeref.-deref defined for type cljs.core/PersistentHashMap: ...

    at Object.cljs$core$missing_protocol [as missing_protocol] (mfp.js:5808)
    at Object.cljs$core$_deref [as _deref] (mfp.js:7268)
    at cljs$core$deref (mfp.js:9396)
    at mfp$update (mfp.js:36808)
    at mfp.js:18388
    at Function.cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$4 (mfp.js:18389)
    at cljs$core$swap_BANG_ (mfp.js:18341)
    at mfp$next_episode (mfp.js:36946)
    at HTMLAnchorElement.<anonymous> (mfp.js:36920)

我可以使用更长的格式来解决此问题:

(swap! player assoc :episode (+ 1 (@player :episode)))

但是,我想知道为什么第一种形式不起作用。谢谢。

2 个答案:

答案 0 :(得分:0)

您正在使用什么版本的Clojure / ClojureScript?我只是尝试以下方法:

project.clj

(defproject cljsdemo "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.0"]
                 [org.clojure/clojurescript "1.10.520"]]
  :main ^:skip-aot cljsdemo.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}}
  :plugins [[lein-cljsbuild "1.1.7"]]
  :cljsbuild {
              :builds [{
                        ;; The path to the top-level ClojureScript source directory:
                        :source-paths ["src-cljs"]
                        ;; The standard ClojureScript compiler options:
                        ;; (See the ClojureScript compiler documentation for details.)
                        :compiler {:output-to "public/js/main.js" ;; default: target/cljsbuild-main.js
                                   :optimizations :advanced
                                   :pretty-print false}}]}

src-cljs / foo / demo.cljs

(ns foo.demo)

(def player
  (atom {:episode 0 :hello "world"}))

(println
 (clj->js
  (swap! player update :episode inc)))

public / index.html

<html>
  <body>
    <h1>Testing...</h1>
    <script src="js/main.js"></script>
  </body>
</html>

目录结构:

$ tree
.
├── project.clj
├── public
│   └── index.html
└── src-cljs
    └── foo
        └── demo.cljs

要编译代码:lein cljsbuild once

然后,我使用cd public; python -m SimpleHTTPServer 3000启动Web服务器,并在Firefox上打开http://0.0.0.0:3000/,在JavaScript控制台上看到以下内容:

#js {:episode 1, :hello world}

答案 1 :(得分:0)

正如@ ez121sl在注释中指出的那样,函数update在代码的其他地方重新定义,从而导致错误。