Обновление атома с помощью update и inc завершается неудачно - PullRequest
0 голосов
/ 03 мая 2019

У меня есть атом (в ClojureScript):

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

И я хочу увеличить :episode на единицу:

(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 голосов
/ 06 мая 2019

Как указал @ ez121sl в комментариях, функция update переопределена где-то еще в коде, что вызвало ошибку.

0 голосов
/ 04 мая 2019

Какие версии 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 и открываю http://0.0.0.0:3000/ в Firefox, на консоли JavaScript я вижу следующее:

#js {:episode 1, :hello world}
...