beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
st3fan 2020-11-17T00:33:47.355500Z

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

st3fan 2020-11-17T00:35:33.355900Z

Oops .. single quoted strings DO exist!

st3fan 2020-11-17T00:35:40.356200Z

Glad that I am in #beginners šŸ™‚

alexmiller 2020-11-17T00:35:40.356300Z

no, they don't

st3fan 2020-11-17T00:35:50.356700Z

Oh is that just a repl thing?

alexmiller 2020-11-17T00:36:01.357Z

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

alexmiller 2020-11-17T00:36:23.357500Z

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

alexmiller 2020-11-17T00:36:40.358100Z

strings in Clojure are always double quotes

st3fan 2020-11-17T00:36:40.358200Z

yeah ok so i evaluated 'hello' - that was confusing šŸ™‚

alexmiller 2020-11-17T00:37:00.358500Z

yeah that will give you the symbol hello'

st3fan 2020-11-17T00:37:46.359Z

need a brighter emacs theme at night šŸ˜•

practicalli-john 2020-11-17T10:13:00.378100Z

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/

st3fan 2020-11-17T00:57:30.359400Z

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

seancorfield 2020-11-17T01:01:39.359900Z

@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).

seancorfield 2020-11-17T01:02:37.360300Z

Seems well-maintained https://github.com/cloverage/cloverage

lread 2020-11-17T16:34:32.393500Z

@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.

st3fan 2020-11-17T17:45:44.395Z

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

seancorfield 2020-11-17T17:58:21.395200Z

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

seancorfield 2020-11-17T17:58:34.395400Z

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

st3fan 2020-11-17T17:58:50.395600Z

:thumbsup:

seancorfield 2020-11-17T17:59:37.395800Z

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

st3fan 2020-11-17T01:05:01.361100Z

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

2020-11-17T01:42:59.365100Z

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

gregg 2020-11-17T01:52:27.366300Z

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

Iulian 2020-11-17T09:39:16.375Z

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.

gregg 2020-11-17T01:52:41.366800Z

So the issue is somewhere else

st3fan 2020-11-17T03:19:32.366900Z

Well, we do for our projects šŸ™‚

st3fan 2020-11-17T03:19:47.367100Z

I know it is debatable

st3fan 2020-11-17T03:20:26.367900Z

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

st3fan 2020-11-17T03:21:20.368100Z

</hack night>

st3fan 2020-11-17T03:24:41.368900Z

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 ?

st3fan 2020-11-17T03:26:21.369200Z

Ok that is for tomorrow to find out

st3fan 2020-11-17T03:28:06.369500Z

Looks like I copy/pasted some namespaces incorrectly šŸ™‚

Daniel Ɩstling 2020-11-17T08:50:14.372800Z

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_geek 2020-11-17T09:02:27.372900Z

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

šŸ‘ 1
dharrigan 2020-11-17T09:03:13.373200Z

Yes, I use aero too (with juxt clip)

dharrigan 2020-11-17T09:03:43.373600Z

Using profiles you can externalise things, also you can

dharrigan 2020-11-17T09:04:24.373800Z

include other configurations, so for example, I have this

agile_geek 2020-11-17T09:04:28.374Z

BTW Iā€™ve never had problems with environ and lein uberjar

dharrigan 2020-11-17T09:04:36.374200Z

;;
;; 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"

dharrigan 2020-11-17T09:05:30.374400Z

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.

dharrigan 2020-11-17T09:05:56.374600Z

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

dharrigan 2020-11-17T09:05:57.374800Z

.

Daniel Ɩstling 2020-11-17T09:51:36.375200Z

Okay, thanks guys šŸ™‚ @agile_geek 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 Ɩstling 2020-11-17T09:52:50.375400Z

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 Ɩstling 2020-11-17T09:53:17.375600Z

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

Daniel Ɩstling 2020-11-17T09:53:52.375800Z

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

agile_geek 2020-11-17T09:56:06.376Z

environ reads system properties but uses the defaults in the lein profile if theyā€™re not present. But as @weavejester 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_geek 2020-11-17T09:56:51.376200Z

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

agile_geek 2020-11-17T09:57:23.376400Z

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

agile_geek 2020-11-17T09:58:21.376700Z

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_geek 2020-11-17T09:58:34.376900Z

Typically this is an edn file

agile_geek 2020-11-17T09:58:52.377100Z

This is what aero is designed for.

agile_geek 2020-11-17T10:06:16.377600Z

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 Ɩstling 2020-11-17T10:09:22.377900Z

@agile_geek 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 :)

2020-11-17T11:46:34.384300Z

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.

2020-11-17T12:05:23.384800Z

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

šŸ˜ŗ 1
2020-11-17T12:05:26.385Z

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

Joe 2020-11-17T12:26:30.386700Z

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})) ?

vlaaad 2020-11-17T12:44:55.387500Z

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

vlaaad 2020-11-17T12:45:04.387700Z

https://github.com/redplanetlabs/specter

vlaaad 2020-11-17T12:45:54.388Z

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

šŸ‘ 1
vlaaad 2020-11-17T12:47:52.388300Z

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 ...) {...}))

2020-11-17T12:50:55.388600Z

How about reduce-kv?

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

Joe 2020-11-17T12:52:12.389Z

Thanks both!

2020-11-17T14:20:28.389300Z

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

jkida 2020-11-17T20:54:45.400800Z

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.

dpsutton 2020-11-17T20:55:34.401200Z

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

jkida 2020-11-17T20:55:41.401400Z

ok

dpsutton 2020-11-17T20:56:09.402200Z

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

2020-11-17T20:56:30.402700Z

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

dpsutton 2020-11-17T20:57:24.404100Z

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

jkida 2020-11-17T20:57:48.404500Z

ahh, ok

st3fan 2020-11-17T21:35:47.406Z

In a test is it possible to mock functions?

st3fan 2020-11-17T21:37:41.408Z

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.

st3fan 2020-11-17T21:38:27.408800Z

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 Douglass 2020-11-17T21:51:10.409400Z

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

walterl 2020-11-17T22:06:04.410Z

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

2020-11-17T22:33:22.411Z

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

dpsutton 2020-11-17T22:46:50.411800Z

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

2020-11-17T22:57:22.414Z

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

2020-11-17T22:57:56.414400Z

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

2020-11-17T23:04:20.415300Z

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

2020-11-17T23:05:45.415900Z

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

dpsutton 2020-11-17T23:07:48.416300Z

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

2020-11-17T23:08:14.416800Z

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

alexmiller 2020-11-17T23:08:40.417500Z

old blog about with-redefs https://www.cognitect.com/blog/2016/9/15/works-on-my-machine-understanding-var-bindings-and-roots

alexmiller 2020-11-17T23:08:59.417700Z

if you want more gory details

2020-11-17T23:27:08.419Z

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?

2020-11-17T23:40:58.419300Z

@didibus that would avoid the issue, yes

2020-11-17T23:41:42.420Z

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