@tolitius: Boot App Version: 2.0.0 Boot Lib Version: 2.1.2 Clojure Version: 1.6.0 But it's okay, I've been using mount on my own project successfully so far :simple_smile:
@bbss: great, thanks for the feedback. This is probably minor then, but whenever you have a chance, could you try to upgrade boot (`2.0.0` is a bit old):
$ boot -u
Retrieving boot-2.5.5.jar from <https://clojars.org/repo/>
#<http://boot-clj.com>
#Thu Jan 21 09:18:36 EST 2016
BOOT_CLOJURE_NAME=org.clojure/clojure
BOOT_VERSION=2.5.5
BOOT_CLOJURE_VERSION=1.7.0
and do boot cljs-example
?I'm transitioning to mount and slowly getting the hang of it. But I'd like to ask for some guidance. I have a namespace app.config
where normally I used to keep a config atom. This gets initialized with config data read from a file. Problem is, the filename is normally supplied from the command line, in my app.main
namespace's main function. What is a reasonable way of passing that filename to app.config
defstate
functions?
@jrychter: welcome! :simple_smile: would something like this work for you: https://github.com/tolitius/mount/blob/master/doc/runtime-arguments.md#passing-runtime-arguments ?
Also, is the :refer [config]
magical in some way, or will mount work just as well with (:require [my.namespace])
and calling my.namespace/accessor
?
@tolitius: I don't know how I missed that when reading the docs…
:refer [config]
is same as Clojure: i.e. my.namespace/accessor
would also work
@jrychter: it's the last thing.. I might need to reorganize the docs a bit
Ok, the mount/start-with-args
approach could work. I don't yet see how to make this elegant (e.g. only pass a limited number of well-behaved arguments to mount), but I just need to think about it.
Yes, in general I think the docs could be improved. I found them difficult to follow and understand and I think this is preventing people from using mount. Please take this as an observation, rather than critisism, I don't want to sound rude or ungrateful.
are all the config values in the external config file, or you are looking to overwrite some of the values in config with something like -D
?
@jrychter: not at all, great feedback. what (re)organization would you feel help the most?
No, the idea is that I just pass the filename. The config ns deals with everything else, such as creating the file if it doesn't exist, or reading configuration from an existing file. So it's just one string-or-nil value.
As for docs, when I was reading them, I thought: that's a strange way to begin. For example, they begin by outlining differences from component, which I don't really care about unless I'm comparing the two. But to compare, I have to learn how mount works anyway, so…
I think I expected a short outline of the mount approach and then a meaningful reasonably complete example.
I write a lot of documentation, so perhaps if I learn to use mount, I could contribute a gentle introduction.
Also the 'Value of values' section seems superfluous — I found the behavior obvious. Am I missing something? This is exactly what I expected, so I couldn't understand why there was a section on it.
:simple_smile: great. I agree with "a short outline and reasonably complete example", feels more effective. I did include component there because a lot of the people use component, and would be questioning why they need mount. I think it is logical to remove it a bit later, when mount is as familiar (which is slowly happening) "value of values" this was not possible in earlier versions of mount ( https://github.com/tolitius/mount/issues/20 ), and a couple of people asked this would be documented
I think in general the documentation is complete, it's just the structure and ordering which can be confusing to newbies like me.
the example is there: https://github.com/tolitius/mount/tree/0.1.9-SNAPSHOT#mount-and-develop a ""a short effective outline" would definitely help
So, do I understand correctly that mount/start-with-args
can take any value, such as a map with options that I want to pass to my components?
Yes, the example is actually how I figured out how to use mount.
there is also a cljs one, in case you need it in the future: https://github.com/tolitius/mount/blob/0.1.9-SNAPSHOT/doc/clojurescript.md#mounting-that-clojurescript
yes, mount/start-with-args
can take any value.
Though I think it could immediately be enhanced by adding my use case to this https://github.com/tolitius/mount/blob/0.1.9-SNAPSHOT/dev/clj/app/conf.clj (passing the config file name through mount/start-with-args
I actually need the ClojureScript one immediately :simple_smile: All my apps are Clojure + ClojureScript. And the one I'm migrating is fairly large on both sides — it's https://partsbox.io/
I began on the Clojure side, because it's slightly easier and there are better debugging tools.
right, so this file name (i.e. "dev/resources/config.edn") maybe the only thing you pass via -D
, and then something like:
(defstate config
:start (load-config (:config-path (mount/args))))
would workwhere it would be pass as (for example) -Dconfig-path=xyz/resources/config.edn
I'm reworking my configuration and trying things out as we speak.
<http://partsbox.io|partsbox.io>
looks cool :simple_smile:
thanks
BTW, I clicked on the ClojureScript docs immediately, read about derefing, then jumped into Clojure and was surprised that derefing doesn't work :simple_smile:
yea, if you need to use mount in both Clojure and ClojureScript I would recommend reading: https://github.com/tolitius/mount/blob/master/doc/clojurescript.md#managing-state-in-clojurescript
This is exactly what I started with.
Oh, a practical observation: it was (and still is) unclear to me where the (mount/in-cljc-mode)
form needs to be placed.
oh.. ok. yes, (mount/in-cljc-mode)
will switch mount into a mode of derefing. All APIs are going to work consistently between clj and cljs.
anywhere before (mount/start)
So where does it go? In both Clojure and ClojureScript code (my code isn't cljc)
sure, cljc
is just a name to indicate that it supports both.. I guess it might be too geeky of me :simple_smile:
…and (I think this is what the docs say) does this mean that I will be using @ to access Clojure state as well?
So I should call (mount/in-cljc-mode)
both in my server-side app and in ClojureScript code, anywhere before (mount/start)
to get the same API in both worlds.
yes, in case you need to work in both modes, I would recommend to call (mount/in-cljc-mode)
at the app entry point, and use @
to access your states (there is a cljs
app example).
(!) you don't have to do that at all, and work without @
in both clj and cljs, but you might have problems with cljs :advanced
optimization mode. this was the sole driver for this mode
Actually, I really prefer that mode. Even for aesthetic reasons, I find @
logical to use in case of state.
And I do need :advanced
very much :simple_smile:
right.. this is from docs (with one of the points you agree with already): While initially it may sound strange, this approach has very nice properties: * Mentally something that you deref (@) is associated with a state behind it * The whole system may start lazily without an explicit call (mount/start) * States may have watchers which is just an idea at this point, but it could be quite useful
I fully agree and I don't think this sounds strange at all. I always had state encapsulated in atoms, and always used @ to access it.
Sigh. I regularly break things completely by making an error in the :stop
function, which means I can't stop the system, which means I can't reload the namespace :simple_smile:
in the REPL, you could get a reference to the sate var, and stop it manually
for example, say you have a web server as a state:
(defstate web-server :start (...) :stop (.. with error ...))
when you call (mount/stop)
, the :stop
of the web server would error out / or won't stop the server
from the REPL you can do:
(require '[myns :refer [web-server]])
(.shutdown web-server)
i.e. if .shutdown
is a correct way, of course
answering your previous question: on the cljs
side you don't need to call (mount/in-cljc-mode)
Oh, ok. See, this is what is missing in the docs :simple_smile: I think they should simply say: in Clojure code, call (mount/in-cljc-mode)
before (mount/start)
, which will change the API so that you will need to deref (`@`) state.
Thank you for all your help, and thank you for writing mount, which I really like so far. Once I get comfortable using it, I will try to contribute to the documentation.
sure, that'd be great, thank you :simple_smile: