This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-08-27
Channels
- # admin-announcements (1)
- # announcements (11)
- # babashka (17)
- # beginners (26)
- # calva (6)
- # cider (2)
- # circleci (1)
- # clojure (41)
- # clojure-dev (1)
- # clojure-europe (31)
- # clojure-france (2)
- # clojure-italy (10)
- # clojure-nl (7)
- # clojure-norway (5)
- # clojure-spec (15)
- # clojure-uk (42)
- # clojurescript (4)
- # code-reviews (12)
- # conjure (10)
- # datalog (2)
- # datascript (15)
- # datomic (37)
- # emacs (1)
- # events (5)
- # fulcro (19)
- # jobs (1)
- # jobs-discuss (9)
- # kaocha (2)
- # luminus (14)
- # meander (4)
- # membrane (39)
- # off-topic (26)
- # other-languages (2)
- # re-frame (13)
- # reitit (6)
- # rewrite-clj (39)
- # sci (6)
- # shadow-cljs (33)
- # test-check (15)
- # vrac (17)
- # xtdb (7)
Hi! What’s the trick to using the config created as <myproject>.config/env by the Luminus template? If I use it as a map directly it might not be ready yet and cause nil values. If I defer it I see a message that it is not started and that mount/start should have been called for that to happen. Since the Luminus code doesn’t do the latter I guess there’s something I’m missing. Help for reliable use would be appreciated.
@ramblurr I don’t see how that will help. What about code that is already evaluated before that, eg. a (def foo (:bar env))
in another ns (effectively assigning nil
to foo
as env is not ready). In addition I start it with lein run
and would like it to get into a fully working state without any repl interaction. Sorry if I’m missing something obvious here, but I don’t see how having required repl steps is attractive. Sound like something that is easy to forget from time to time.
Feels like I’m missing the idea behind this design.
The luminus documentation on this pattern is described here https://luminusweb.com/docs/components.html
The intention is that any use of env
will occur after the config component is mounted (which is done as part of (start)
) . If you are def
ing something that needs a value from the config, then whatever you're defing should probably become a component itself, and managed via mount's start and stop.
Thanks, I will have to sit down and read that doc more closely. My previous skimming through it did not give me the answers I was looking for.
I’ve previously attempted to only access env
from inside defstate
but that just propagated the problem in the sense that whatever uses what I define will also have to be inside a defstate
… That issue told me that it was something I had not really grasped.
My underlying “problem” is that that Luminus template has been serving me very well, so I haven’t really spent the required time on getting to know all the libraries well enough.
The simplest advice I can give on this topic, is to realize that when you are (def foo (:bar env))
you are declaring state that depends on something external (as opposed to a constant like (def foo 3.14)
). Anytime you have state that depends on something external, declare it with defstate.
In your example, foo is just a config key from env. Presumably this foo will be used in some other piece of state, like a database connection. You do not need to (defstate foo :start (:bar env))
but rather defstate the thing that will consume :bar, (defstate a-thing :start (fn [] (let [foo (:bar env)] (do-thing-with foo))))
then whatever (do-thing-with) returns can be accessed via a-thing.. or in other words that defstate is similar to (def a-thing (do-thing-with (:bar env)))
for more background: luminus uses the mount
library to manage stateful components (that's what (start) is calling). mount is an adaption of stuart sierra's https://github.com/stuartsierra/component . I recommend watching stuart's talk that explains (in 45 minutes of detail) what this is all about