Fork me on GitHub
#mount
<
2018-03-15
>
rustam.gilaztdinov09:03:23

@tolitius hello! Can you please clarify this thing for me In dev/user.my namespace I have this:

(ns 
  (:require [clojure.tools.namespace.repl :refer [refresh]]
            [mount.core :as mount]))

(defn start []
  (mount/in-cljc-mode)
  (mount/start))

(defn stop []
  (mount/stop))

(defn go []
  (start)
  :started)

(defn reset []
  (stop)
  (refresh :after ')
  :ok)

I want to to use a mount with cljs, more generally — sharing config on clj and cljs side So, in src/cljc I create namespace config.cljc, which look like this
(ns my-lib.config
  #?(:clj
     (:require [config.core :refer [load-env]] ;; this is yogthos/config
               [taoensso.timbre :as log]
               [mount.core :refer [defstate]]))
  #?(:cljs
     (:require-macros [mount.core :refer [defstate]])))

#?(:clj
   (defn load-config []
     (log/info "loading configuration")
     (load-env)))

#?(:clj
   (defstate ^{:on-reload :noop} config
     :start (load-config)))

#?(:cljs
   (defstate ^{:on-reload :noop} frontend-environment
     :start (:env @config)))
When I started repl, all states starting good, then I load namespase with config in repl and try to see what’s happening:
;; this is clj-repl
my-lib.config> (:env @config)
{:host "localhost", :port 3001, :database "data/dev"}

;; this is cljs-repl
my-lib.config> frontend-environment
nil

my-lib.config> @frontend-environment
#object[Error Error: No protocol method IDeref.-deref defined for type undefined: ]
[email protected]://localhost:3449/js/compiled/app.js:129:336
[email protected]://localhost:3449/js/compiled/app.js:223:435
[email protected]://localhost:3449/js/compiled/app.js:366:402
@http://localhost:3449/js/compiled/app.js line 3469 > eval:1:226
@http://localhost:3449/js/compiled/app.js line 3469 > eval:1:189
@http://localhost:3449/js/compiled/app.js line 3469 > eval:1:2
[email protected]://localhost:3449/js/compiled/app.js:3469:309
What I do wrong?

rustam.gilaztdinov09:03:15

Even in .cljs namespaces I can’t work with mount, for example

(ns my-lib.state
    (:require-macros [mount.core :refer [defstate]]))
In cljs-repl:
my-lib.state> (defstate a :start 12)
---- Compiler Warning on cljs form line:1 column:1 ----

Use of undeclared Var mount.core/running-noop?

1 (defstate a :start 12)
^---
---- Compiler Warning ----
---- Compiler Warning on cljs form line:1 column:1 ----

Use of undeclared Var mount.core/mount-it
1 (defstate a :start 12)
^---
---- Compiler Warning ----
---- Compiler Warning on cljs form line:1 column:1 ----

Use of undeclared Var mount.core/current-state
1 (defstate a :start 12)
^---
---- Compiler Warning ----
#object[ReferenceError ReferenceError: mount is not defined]
nil

tolitius19:03:53

@rustam.gilaztdinov you need to require mount as well so cljs understands how to evaluate defstate macro (i.e. since it is using mount functions):

tolitius19:03:15

connected! >>
To quit, type: :cljs/quit
nil
cljs.user=> (require-macros '[mount.core :refer [defstate]])
nil
cljs.user=> (defstate a :start 12)
WARNING: Use of undeclared Var mount.core/running-noop? at line 1 <cljs repl>
WARNING: Use of undeclared Var mount.core/mount-it at line 1 <cljs repl>
WARNING: Use of undeclared Var mount.core/current-state at line 1 <cljs repl>
#'cljs.user/a
but:
cljs.user=> (require '[mount.core :as mount])
nil
cljs.user=> (defstate a :start 12)
#'cljs.user/a
cljs.user=> @a
12

rustam.gilaztdinov20:03:22

doesn't work for me 😞

rustam.gilaztdinov20:03:01

(ns my-lib.state
  (:require-macros [mount.core :refer [defstate]])
  (:require [mount.core :as mount]))

rustam.gilaztdinov20:03:17

my-lib.state> (defstate a :start 12)
#object[ReferenceError ReferenceError: mount is not defined]
nil

tolitius20:03:47

ok, one problem at a time

tolitius20:03:01

did it fix the warnings?

tolitius20:03:13

i.e.

Use of undeclared Var mount.core...

tolitius20:03:46

ok, good. which browser are you using to connect to the cljs repl?

tolitius20:03:50

how do you start the cljs repl?

rustam.gilaztdinov20:03:26

from cider in spacemacs

tolitius20:03:09

there is something off in a way cljs repl (in your case) evals the forms, in this case defstate

tolitius20:03:31

I use neither 🙂 so it is harder to debug, but could you start your cljs repl in a different way and try? for example I use "terminal" and "boot" to start the cljs repl.

tolitius20:03:49

do you know boot at all?

tolitius20:03:56

(i.e. use it)

rustam.gilaztdinov20:03:17

it's really dumb -- but after lein clean mount in cljs works now! 🎉

tolitius20:03:22

I remember this error on cljs side when the browser could not evaluate the forms, it was caused by the faulty repl connection. since I don't use emacs/figwheel it is harder for me to guess

tolitius20:03:37

ah.. ok. great 🙂

tolitius20:03:58

yea, that is one of the reasons I started using boot for everything

rustam.gilaztdinov20:03:15

thx, can you help me with .cljc files?

tolitius20:03:23

to avoid hours of debugging that is caused by stale state introduced by lein

rustam.gilaztdinov20:03:52

maybe tools.deps will help us in a future?

tolitius20:03:10

could be, have not used it yet (docs are interesting though)

tolitius20:03:58

> can you help me with .cljc files? do you still have an undefined type problem?

rustam.gilaztdinov20:03:54

no, another one, give me a minute, pls)

tolitius20:03:37

ok, I have to run, post it here. I'll look later on

rustam.gilaztdinov20:03:13

I have this cljc namespace

(ns my-lib.config
  (:require
   #[email protected](:clj
        [[config.core :refer [load-env]]
         [taoensso.timbre :as log]
         [mount.core :refer [defstate]]]
       :cljs
       [[mount.core :as mount]]))

  #?(:cljs
     (:require-macros
            [mount.core :refer [defstate]])))

#?(:clj
   (defn load-config []
     (log/info "loading configuration")
     (load-env)))

#?(:clj
   (defstate ^{:on-reload :noop} config
     :start (load-config)))

#?(:cljs
   (defstate ^{:on-reload :noop} frontend-environment
     :start (:env @config)))

rustam.gilaztdinov20:03:47

and on clj-repl config works well

rustam.gilaztdinov20:03:05

I want to share this config to cljs-side

rustam.gilaztdinov20:03:21

In cljs-repl, when I evaluate namespace -- I see this warning

WARNING: Use of undeclared Var my-lib.config/config at line 25 /Users/..../config.cljc

rustam.gilaztdinov20:03:27

and this error

my-lib.config> @frontend-environment
#object[Error Error: No protocol method IDeref.-deref defined for type undefined: ]
   cljs.core/missing-protocol (jar:file:/Users/../.m2/repository/org/clojure/clojurescript/1.9.908/clojurescript-1.9.908.jar!/cljs/core.cljs:304:4)
   cljs.core/-deref (jar:file:/Users/../.m2/repository/org/clojure/clojurescript/1.9.908/clojurescript-1.9.908.jar!/cljs/core.cljs:659:1)
   cljs$core$deref (jar:file:/Users/../.m2/repository/org/clojure/clojurescript/1.9.908/clojurescript-1.9.908.jar!/cljs/core.cljs:1437:4)
nil

rustam.gilaztdinov20:03:00

I think -- this is because defstate frontend-environment relies to @config, which is #?clj related

tolitius03:03:48

right:

#?(:clj
   (defstate ^{:on-reload :noop} config
     :start (load-config)))
cljs does not see that: i.e. cljs compiler does not compile this, hence config is not known on the cljs side