This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-17
Channels
- # announcements (17)
- # aws (2)
- # babashka (21)
- # beginners (67)
- # calva (19)
- # cider (29)
- # clara (3)
- # clj-kondo (6)
- # cljsrn (10)
- # clojure (140)
- # clojure-europe (164)
- # clojure-nl (3)
- # clojure-uk (8)
- # clojurescript (62)
- # conjure (7)
- # core-async (24)
- # cursive (21)
- # datomic (5)
- # docker (40)
- # emacs (14)
- # fulcro (25)
- # gratitude (1)
- # honeysql (6)
- # introduce-yourself (1)
- # jobs (1)
- # jobs-discuss (32)
- # juxt (7)
- # lsp (13)
- # minecraft (2)
- # off-topic (49)
- # pathom (24)
- # practicalli (8)
- # re-frame (18)
- # react (23)
- # remote-jobs (6)
- # reveal (2)
- # shadow-cljs (75)
- # tools-deps (7)
What are you folks using to handle environment variables, specifically in a project using deps.edn
?
I was using https://github.com/weavejester/environ and also found https://github.com/yogthos/config but they are both geared around lein
and using your project.clj
file or .lein-env
files.
I would like to have a .env
file myself but am also scared about doing something stupid, security wise.
I'm pretty sure both should work with deps.edn
. have you tried them and run across a problem?
As a side note, I have a local postgres db right for development, but I'm also setting up a db through heroku to use on the same project in production. I'm overwhelmed trying to think of how I keep such things in sync. Are they going to have different db urls and such, right? Where am I storing all these environmental variables?
Well, for example, the environ
entire readme is describing how to set up your profile.clj
to use it and access your .lein-env
file. I have no clue how to translate all that into deps.edn
workflow
The example it is using talks about a dev and prod db access which sounds like exactly what I am going to need.
Should I just set global environment variables for such things? I've done that for api access things in the past and it worked out fine. Accessing it with (System/getenv "my_variable")
You can use environ
and config
, but you can also use what you suggest above directly, without using those libraries.
I don't know anything about Heroku, but I presume there is some way of setting the global environment variables as well.
And the settings of the dev and prod variables will probably need to be different - obviously.
Some sort of configuration management library will be useful as you work on more complicated projects, but for your current purposes, direct is probably best. FWIW, I tend to prefer the juxt/aero
library for config management.
So at work my co-workers came upon a solution: have a configuration.edn
in the project root with default (non-secret) values
Then have a file in your home directory or someplace outside the purview of version control that overrides them if it exists.
So you can never accidentally commit your secrets to forever-version-control
and it kinda dummy-proofs the idea of forgetting to update your .gitignore
juxt/aero
uses a similar approach. The secrets are stored in a file in the home dir and are included into the project config file using a reader macro.
Putting passwords in a file within a project increases the chance someone is going to commit it my mistake. This is why there are bots continually running against GitHub because people so easily make this mistake. Its never a good idea to put passwords in a file within a project.
For Heroku, you can https://practical.li/clojure-web-services/projects/banking-on-clojure/deployment-via-ci.html#heroku-pipeline-configuration for a project or via the Heroku CLI tool. Creating addons such as a database will automatically add a config var, which you can then view the value in the dashboard of via the Heroku cli.
Environ is a convenience library over System/getenv
which allows you to use keywords rather than strings for the environment variable names. It can be used with Clojure CLI (deps.end) projects by adding it as a main dependency, :deps
in deps.edn and then refereing the namespace where ever its needed.
If you have multiple environments (test, stage, prod) then juxt/aero uses a hash-map wiith #profile
to define values for each environment
Aero can also be used with Integrant and other component services , e.g. https://practical.li/clojure-web-services/repl-driven-development/integrant-repl/#aero-tag-literals
Awesome, thanks so much folks! Aero looks perfect for my needs as I progress past simply using calls to System/getenv
for *nix systems, you can use a file with entries like
FOO_BAR=baz
QUUX=some-secret
and then start clojure using env $(< env-file) clj ...
to use those varsHey everyone, I am trying to figure out how I can access a local jar in my project using deps.edn
.
:extra-deps {foobar {:local/root "./test.jar"}
How would I go about accessing its classes in any namespace?
(:import (foobar MyImportedClass))
This does not seem to work. I couldn't find examples of accessing classes in local jars..@krishanvj you'll need to provide a bit more detail about what test.jar
is/contains but https://clojure.org/guides/deps_and_cli#local_jar shows how you depend on JAR files locally so your example "should" work.
Are you sure there's a foobar.MyImportedClass
in test.jar
?
Did you use the appropriate alias when you started your REPL/project? :extra-deps
has to be in an alias.
hoe can i run inc
for the collection (def a [ [1 3] [ 5 6]])
? I tried with (apply map inc a)
but this work only for (def a [[1 3]])
do I need to do doseq here?
what do you expect as a result?
Another way would be
Another way to do it is
(def a [ [1 3] [ 5 6]])
(mapv #(mapv inc %) a)
you can use clojure.walk/postwalk for that
(clojure.walk/postwalk
(fn [x]
(if (number? x)
(inc x)
x))
a) ;; => [[2 4] [6 7]]
clojure.walk namespace provided by clojure. but you can do the same using map
(partition 2 (map inc (flatten a))) ;; => ((2 4) (6 7))
as you can see it won’t preserve original data structure(doto pres
;; not like this because doto expands to
;; (when <thing> color .. )
(when color
(.setItemTextForeground color))
(.setItemText text)
(.setTypeText type-name))
how would you express this doto
but with condition?
(#(when color (.setItemTextForeground % color)))
like this?(doto pres
;; not like this because doto expands to
;; (when <thing> color .. )
(cond->
color (doto (.setItemTextForeground color)))
(.setItemText text)
(.setTypeText type-name))
should workyou could look at juxt
as in
(map (juxt inc dec) (range 5)) ;; => ([1 -1] [2 0] [3 1] [4 2] [5 3])
is there a function like
(defn single [lst]
(if (sequential? lst) (first lst) lst))
should return the single elm, or the firstNeeding this is almost always a bad sign. You should go find the case that returns a single thing and make into a coll

Every time I've been down this road, I regretted it
if it can ever be a coll, then it should probably always be a coll. Clojure is great for working and thinking in collection operations.
Fair. I guess if you assume it’s always a collection you can thread it in other functions manipulating the data
Stuart Sierra had a blog post about something like this that might be worth a quick read : https://stuartsierra.com/2015/06/10/clojure-donts-heisenparameter
I have a map, m1
, and a vector of maps, vector-of-maps
. I want to write a predicate that checks whether m1
shares at least one key value pair with any of the maps in vector-of-maps
(defn common-keyvals-with-any? [m1 vector-of-maps]
(some #(not-empty (set/intersection
(set m1)
(set %))) vector-of-maps)
I've come up with the above but it doesn't pass my readability test. Is there a more idiomatic way to express the same thing?Hmm, I think what irks me the most is that the data is nested, even though it doesn't have to be. I suppose I could mapcat over the vector-of-maps to end up with flat key-value pairs, maybe even convert it to set to remove duplicates and then just compute the intersection :thinking_face:
(let [m1 {:a 1 :b 2}
vector-of-maps [{:c 3} {:d 4} {:a 2}]]
(->> vector-of-maps
(mapcat keys)
(some (partial contains? m1))
boolean))
maybe?I agree about turning the vector of maps into a sequence of the things that you care about, and mapcat can help there 😉
That works with some slight modifications; I need to compare key value pairs, not just keys. Sorry, I should have given an example. But yeah, that approach looks much better than my original one, thanks! What I ended up with:
(defn common-keyvals-with-any? [m1 vector-of-maps]
(-> (mapcat set vector-of-maps)
set
(set/intersection (set m1))
not-empty))
You could also do something like
(defn common-keyvals
[m coll-of-maps]
(some (set m) (apply concat coll-of-maps)))
Oh damn, you're right, that works
Another way to do it is
(def a [ [1 3] [ 5 6]])
(mapv #(mapv inc %) a)