tolitius / mount

managing Clojure and ClojureScript app state since (reset)
Eclipse Public License 1.0
1.22k stars 88 forks source link

question about fun-with-values test/example #61

Closed jmarca closed 8 years ago

jmarca commented 8 years ago

Not really an issue; probably more a lack of understanding due to my newness to clojure.

I'm trying to understand your fun-with-value example.

lein test on your code repo works fine, so clearly there isn't a bug.

However, when I try to use the approach in my code, I get errors like:

... .mount_test$g cannot be cast to java.util.concurrent.Future

I copied the test file as is into my project. I'm using boot, not lein, but otherwise it should work the same.

My stripped down version of your test is:

(ns calvad.watcher.mount-test
  (:require [clojure.test :as t :refer [is are deftest testing use-fixtures]]
            [mount.core :as mount :refer [defstate]]))

(alter-meta! *ns* assoc ::load false)

(defn g [a b]
  (+ a b))

(defstate f-args :start g)

(defn start-states []
  (mount/start #'calvad.watcher.mount-test/f-args))

(use-fixtures :once #((start-states) (%) (mount/stop)))

(deftest fun-with-values
  (is (= (@f-args 41 1) 42)))

When run, I get

ERROR in (fun-with-values) (core.clj:2206)
expected: (= ((clojure.core/deref f-args) 41 1) 42)
  actual: java.lang.ClassCastException: calvad.watcher.mount_test$g cannot be cast to java.util.concurrent.Future

Any hints on what is missing would be appreciated.

tolitius commented 8 years ago

welcome to Clojure :)

notice that the test is not exactly a Clojure file, but a .cljc one (i.e. fun_with_values.cljc). Which means it is meant to be used/compiled/run by both: Clojure and ClojureScript.

take a look at the mount's ClojureScript notes, you'll see that when mount is (re)used in both Clojure and ClojureScript environments, its states are derefable, which means that in order to use them, they need to be`deref'fed or simply @.

This is exactly what you see in your example:

(deftest fun-with-values
  (is (= (@f-args 41 1) 42)))

the reason why this does not work for you is most likely caused by you using the default clj mode (which only support Clojure). In order to turn on support for both Clojure and ClojureScript do:

(mount/in-cljc-mode)

you can try it in the REPL before running these tests, or directly within the test file.

jmarca commented 8 years ago

That did the trick, both for my minimal copy of your test, and for my actual code.

I missed that note about mount/in-cljc-mode because I'm running clojure vanilla, not cljs (at least, not for this application). Thanks for pointing it out.

tolitius commented 8 years ago

sure. in case you are running it in Clojure only, you don't have to do mount/in-cljc-mode, just remove the @ from @f-args, and it will work.

jmarca commented 8 years ago

Oh. I never tried that! But I will also eventually be using this in cljs, so it is good to know.