Fork me on GitHub
#beginners
<
2020-11-17
>
st3fan00:11:47

Clojure doesn't have '' or strings right? Including some JSON fragments in a unit test and there is a lot of escaping like \"

st3fan00:11:33

Oops .. single quoted strings DO exist!

st3fan00:11:40

Glad that I am in #beginners 🙂

alexmiller00:11:40

no, they don't

st3fan00:11:50

Oh is that just a repl thing?

alexmiller00:11:01

single quoted forms exist (just single quote at the beginning) - that means to read, but not evaluate

alexmiller00:11:23

'(1 2 3) means read that as a list but don't evaluate (by invoking the 1 as a function)

alexmiller00:11:40

strings in Clojure are always double quotes

st3fan00:11:40

yeah ok so i evaluated 'hello' - that was confusing 🙂

alexmiller00:11:00

yeah that will give you the symbol hello'

st3fan00:11:46

need a brighter emacs theme at night 😕

practicalli10:11:00

I use Doom Solarized Light theme for Emacs, find it great for night and day, you can see it in action in my live broadcasts https://practicalli.github.io/

st3fan00:11:30

Is there a code (test) coverage story for Clojure?

seancorfield01:11:39

@st3fan cloverage (although I've never used it in a decade of production Clojure work so I can't speak to how good it is or how easy it is to use).

lread16:11:32

@st3fan I just recently added code coverage reporting to https://github.com/lread/rewrite-cljc-playground. I used the kaocha plugin for cloverage and send results to http://codecov.io.

st3fan17:11:44

That looks great on codecov. Sorry if this is a dumb question but what is the cljc extension?

seancorfield17:11:21

@st3fan .cljc means that it works in both Clojure and ClojureScript.

seancorfield17:11:34

.cljs is pure ClojureScript, .clj is pure Clojure.

seancorfield17:11:37

It was introduced in Clojure 1.7. Here's the section of the change log that talks about it: https://github.com/clojure/clojure/blob/master/changes.md#22-reader-conditionals

st3fan01:11:01

Thanks I'll take a peek. Is it not a Clojure thing to do code coverage? Like it is with Java/Kotlin?

hiredman01:11:59

My first reaction to that is "what makes you think java or kotlin are all doing code coverage?"

st3fan03:11:32

Well, we do for our projects 🙂

st3fan03:11:47

I know it is debatable

gregg01:11:27

@iulian.birlica Your latest code is good. I plugged it in and got...

Iulian09:11:16

Would you be willing to share how you run the code, or a small project that does just this? I trimmed down a project to only render this component, and it still runs fine all except for actually rendering this component.

gregg01:11:41

So the issue is somewhere else

st3fan03:11:26

Whoohoo - all the ring middleware for my github webhook handler is now 100% unit tested

st3fan03:11:20

</hack night>

st3fan03:11:41

Hmm lein test only runs one file from my project's test/ directory ... that is odd .. does not simply test $PROJECT_ROOT/test/**/_test.clj ?

st3fan03:11:21

Ok that is for tomorrow to find out

st3fan03:11:06

Looks like I copy/pasted some namespaces incorrectly 🙂

Daniel Östling08:11:14

What do people use to juggle environments like test, dev, production? I’ve looked at environ but it doesn’t seem to handle lein uberjar build well when it comes to processing environment vars. Should I be putting my config in .edn files and load them in main or something? Seems to work for non-uberjar scenario with environ, would be nice to have something consistent across the build scenarios.

agile_geek09:11:27

I’ve used aero with some success in the past. Have a look at profiles in aero for config across environments. https://github.com/juxt/aero#profile

dharrigan09:11:13

Yes, I use aero too (with juxt clip)

dharrigan09:11:43

Using profiles you can externalise things, also you can

dharrigan09:11:24

include other configurations, so for example, I have this

agile_geek09:11:28

BTW I’ve never had problems with environ and lein uberjar

dharrigan09:11:36

;;
;; Configuration
;;
{:secrets {:kafka  #include "/var/run/secrets/kafka-config.edn"
           :txi-higgins #include "/var/run/secrets/txi-higgins-config.edn"}

 :runtime-config #include "/config/txi-higgins-runtime-config.edn"

dharrigan09:11:30

the kafka-config.edn and the txi-higgins-runtime-config.edn are dynamically mounted as docker volumes in each environment, so naturally they contain different values depending upon the enviornment.

dharrigan09:11:56

of course, you could use any other mechanism for pulling in your environment specific config.

Daniel Östling09:11:36

Okay, thanks guys 🙂 @U05390U2P my issue may very well be user error on my part. What I was trying to do was use something like (`environ/env :database-url)` which worked well for dev and text but didn’t work when I did lein uberjar

Daniel Östling09:11:50

The environ github page says at the bottom “Important -- environ will not pick up configuration settings from the `project.clj` when called from a compiled uberjar. So for any compiled code you produce with `lein uberjar`, you will want to set your configuration values via shell environment and/or system properties.”

Daniel Östling09:11:17

So it may be that for my use case, a separate config .edn could be better.

Daniel Östling09:11:52

Eh, some other way to set context other than project.clj/profiles.clj, rather.

agile_geek09:11:06

environ reads system properties but uses the defaults in the lein profile if they’re not present. But as @U0BKWMG5B points out uberjar is compiling your code so it no longer has any access to the config in project.clj it can’t read defaults as they’re not there at runtime

agile_geek09:11:51

So environ works as designed and you could set system properties for the values required in your runtime environment

agile_geek09:11:23

e.g. export database-url=the/db/url

agile_geek09:11:21

If you want defaults for these values you need to put them in a resources file that will be packaged as part of the uberjar or is on the file system at runtime

agile_geek09:11:34

Typically this is an edn file

agile_geek09:11:52

This is what aero is designed for.

agile_geek10:11:16

Typically the :env settings in the profile.clj are just convenience default values for system properties that are expected to be set in the runtime environment e.g. using export. Any config that has defaults that either don’t vary from env to env OR you would prefer to default in your code and not set explicitly using export you would store in a .edn file and aero is useful for reading these files.

Daniel Östling10:11:22

@U05390U2P yes, I have no doubt environ works as intended. I’m not idiomatic enough with Clojure yet to understand what the “best” way forward could be. I’ll take a look at aero for sure, thanks :)

cdpjenkins11:11:34

Is there a standard function that will apply a function to each adjacent pair of elements in a sequence? e.g. if I have: (def xs '(a b c d e)) and I apply this function to it then I want the result to be ( (f a b) (f b c) (f c d) (f d e) ) I know I can do map f xs (rest xs) but I’m lazy and I’m hoping there’s a pre-existing function so I don’t have to implement it again.

peter hull12:11:23

You can use partition with a step of 1 but I don't think that's better than what you have...

cdpjenkins14:11:28

Cool thanks. I wasn’t quite aware that you could do that with partition and I like the way it looks.

peter hull12:11:26

(map #(apply f %) (partition 2 1 xs))

Joe12:11:30

I have a map where the keys are unqualified keywords, and I want to add the same namespace qualification to each key. Is there something a bit more elegant than (into {} (map (fn [[k v]] [(keyword "my-ns" (name k)) v]) {:hello 1 :world 2})) ?

vlaaad12:11:55

there is something a bit more elegant, but it’s a separate dependency, so there is some complexity introduced

vlaaad12:11:54

it’s introductory post describes exactly your use-case: http://nathanmarz.com/blog/clojures-missing-piece.html

vlaaad12:11:52

I would use something similar to your code just because it’s simpler, even though somewhat clunky. Maybe the transducer version (e.g. (into {} (map ...) {...}))

manutter5112:11:55

How about reduce-kv?

(reduce-kv (fn [a k v]
             (assoc a (keyword "my-ns" (name k)) v))
           {}
           {:hello 1
            :world 2})
=> #:my-ns{:hello 1, :world 2}

Joe12:11:12

Thanks both!

jkida20:11:45

Can this be written more idiomatic.

(true? (some my-pred-func my-coll))
Im creating a function that searches a collection of maps for a value and should return true/false if the value is found.

dpsutton20:11:34

that's fine. probably more common to see the use of the boolean function

dpsutton20:11:09

ah, let me say that's probably often not fine to use true? sorry

noisesmith20:11:30

most of the time you wouldn't even wrap it, since if / when etc. already treat values the same way boolean would

dpsutton20:11:24

and some returns the first logical true value which is not restricted to just true.

st3fan21:11:47

In a test is it possible to mock functions?

st3fan21:11:41

as an example, i want to test something that a few levels down calls (api/make-rest-call ...) and replace that with a function that simply records the invocation somewhere so that I can verify that the function I am testing eventually results in that API request.

st3fan21:11:27

In this specific case I could also re-bind (?) the API endpoint to a local server, but I still have the same question about replacing/mocking functions for the sake of testing.

Darin Douglass21:11:10

Yep, just with-redefs the fn you want to track

walterl22:11:04

If your code is separated into components, you can use https://github.com/bguthrie/shrubbery for more "traditional" mocking

noisesmith22:11:22

also note that with-redefs is not thread safe - using it in threaded code can cause the original function definition to be lost

dpsutton22:11:50

ohh. i knew it was (edit: NOT) thread safe but i always assumed it was you might accidentally fire missels not lose the key lol

noisesmith22:11:22

yeah, the specific issue is that if two threads a/b call with redefs, you can have the following: 1. a replaces f with g 2. b replaces g with h 3. a replaces h with f 4. b replaces f with g

noisesmith22:11:56

now f is gone, and g has replaced it outside with-redefs

noisesmith23:11:20

also, as a smaller but still significant concern, b uses the original f for some span of time, where the caller intended to be using h

noisesmith23:11:45

(which I think counts as the "fire-the-missiles" case @dpsutton was concerned with)

dpsutton23:11:48

ok with multiple redefs i see. there's no way to know who has the "original"

noisesmith23:11:14

right - and this only comes up if the calls overlap in two or more threads

alexmiller23:11:59

if you want more gory details

didibus23:11:08

I wonder then, would you be better of to redef the var as dynamic, and then kickoff your threads each one with their own binding?

noisesmith23:11:58

@didibus that would avoid the issue, yes

noisesmith23:11:42

I don't think I'd ever accept a PR using with-redefs other than a single threaded test, and even then I'd encourage an alternative