Fork me on GitHub
#clojure
<
2017-07-24
>
hmaurer00:07:15

Hey, what is the go-to Ring logger? https://github.com/nberger/ring-logger ?

leira03:07:26

noob question: ((fn [a b] [a b]) 1 2) eval to [1 2], (#(vector %1 %2) 1 2) eval to [1 2] too, why (#([%1 %2]) 1 2) got clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector

leira03:07:47

and what does (#(-> [%1 %2]) 1 2) mean?

noisesmith03:07:58

just like #(+ %1 %2) expands to (fn [x y] (+ x y)) #([%1 %2]) expands to (fn [x y] ([x y])) - #() keeps the outer parens

noisesmith03:07:36

-> is a macro also known as thread-first and it's being abused here to be able to use a vector literal where it would otherwise not work

leira03:07:40

I got it~ so (#(do [%1 %2]) 1 2) works too

noisesmith03:07:00

yes - do is better than -> here (in this context do and -> are the same)

leira03:07:26

so the [%1 %2] was evaled in place and used as the initial value of ->, but there is no further functions, so it got returned

noisesmith03:07:30

with more forms,-> would be writing each form into the one after it

leira04:07:20

hmmm I thought about this, but was not very sure I thought it was kinda an abuse too~

tjscollins06:07:48

Is there any sane way of handling repeated date conversions between java.sql.date and java.util.Date or should I give up and use timestamps instead (if that would be better)? Every sql update query rotates the date back a full day because of the time zone getting chopped off and re-added.

seancorfield06:07:07

@tjscollins The only sane solution is to have all your servers set to UTC and your database set to UTC, and work entirely in UTC date/times -- and only convert to/from local date/times on the fringe.

tjscollins06:07:36

I was afraid it would be something like that.

seancorfield06:07:46

Our data center is East Coast and we have everything set to UTC across the board.

seancorfield06:07:56

What database are you using?

tjscollins06:07:12

Postgres. Wanted to use datomic, but my organization's purchasing rules wouldn't allow it without too many headaches.

seancorfield06:07:00

I don't know about Postgres but with MySQL you have to explicitly set the DB to UTC separately from the O/S. Just FYI.

tjscollins06:07:31

Thanks, I'm digging into the docs now to figure it out.

qqq07:07:13

I'm not a big fan of how the javadoc UI works for browing java functions.

qqq07:07:26

Is there a clojure library for parsing javadocs into clojure data (so I can build my own search system) ?

mpenet07:07:47

dont think so, that'd be a useful library tho šŸ™‚

misha09:07:34

greetings, [finite state machines] can anyone describe the difference between "composite state" and "(sub) machine"? UML spec says those are basically the same thing, however, there are 2 names, which is suspicious:

A submachine State implies a macro-like insertion of the specification of the corresponding submachine StateMachine. It is, therefore, semantically equivalent to a composite State. The Regions of the submachine StateMachine are the Regions of the composite State.

apbleonard10:07:03

I'm trying to "live at the REPL" more. One common debugging issue is how to quickly evaluate forms within functions or let bindings, where the symbols are not defined. ProtoREPL has a whole feature around this, and it looks like Cider does too.... (We use Cursive as we've come from a Java shop and deal with lots of Java code still.) Is this something people use a lot? Is there a repl independent approach to this?

cfleming10:07:49

@apbleonard You should be able to do this in Cursive - if thereā€™s something missing (or if you have a link to some doc about ProtoREPLā€™s approach to this) Iā€™d be very interested to see it.

cfleming10:07:26

You can select any form and that will be sent, or thereā€™s the ā€œSend form before caretā€ action. Cursive doesnā€™t do anything clever with missing symbols though, is that what youā€™re referring to?

cfleming10:07:28

@apbleonard So thatā€™s sort of what I had in mind. If you send a form for evaluation, I can check if any of its bindings are not defined in that form. I had envisioned a popup dialog when you evaluate the form which would allow you to enter a value for each one. Does that sound like what you had in mind?

apbleonard10:07:00

That sounds nice šŸ™‚

cfleming10:07:22

Definitely. Could you file an issue for that and Iā€™ll see what I can do?

apbleonard10:07:54

I think this is related to tracing though. In protorepl (sorry to mention the competition!) you stick a (save) form in your code and it can remember values flowing through code as a test runs say, and then you can def these values so you can evaluate forms and debug as you go.

cfleming10:07:45

No problem at all, ProtoREPL is awesome, itā€™s by far my second favourite Clojure environment šŸ™‚

cfleming10:07:37

Ok, I see - I think that should be possible. One issue with that is that IntelliJā€™s ability to paint things over the editor isnā€™t as slick as Atomā€™s yet.

cfleming10:07:53

But thatā€™s just a UI issue that can be worked around.

tianshu11:07:09

Hi, how to do optimistic locking in java.jdbc, write a sql that update by id and version field?

apbleonard11:07:09

@cfleming I think tools like this would really help the team debug efficiently. Experienced Java developers used to debuggers balk at the debugging approaches we resort to - still generally sprinkling printlns in the code. We know evaluating forms in the REPL is the way, but it feels like it's hard work to be efficient. Not sure if Sayid's approach to tracing, where every function call's arguments is saved is too "omniscient" or could be drawn upon? https://github.com/jasongilman/proto-repl-sayid

cfleming11:07:53

Sure, I think Sayid is great too - there are lots of different ways to skin the cat.

cfleming11:07:07

Cursive does offer a traditional Java-style debugger, FWIW

cfleming11:07:22

It works very well, with some caveats.

apbleonard11:07:27

Yes - perhaps I should stop being so purist and get better at using it!

cfleming11:07:09

Itā€™s essential to my work, definitely. Fortunately we donā€™t have to choose, we can have both!

qle-guen11:07:21

hey, I have a function f that calls g, and g calls f, how to order defn's so the compiler knows about all definitions?

featalion11:07:38

declare I mean

qle-guen11:07:44

@featalion that's it, thanks

sbrg11:07:33

Hello. I'm trying to set up a project for both client and server development, using compojure and http-kit. Since I already had a project going, I decided to modify my own project.clj to match the the one I would get using lein new compojure .., but I'm getting some errors from ring regarding jetty. Here is my project.clj: https://gist.github.com/dea054c015658d4ed3295b40b12c8fd5 Here are the errors: https://gist.github.com/f3f62cb6633979ebbfb849a8b6b20861

sbrg11:07:42

This is upon running lein ring server

sbrg11:07:42

I also just noticed that lein deps :tree seems to output a good deal of warnings regarding my dependencies. I'm honestly not sure what the best way to fix that would be, so I'll post that as well: https://gist.github.com/87f04f1805c2cc20e1dee2a9defe0462

sbrg12:07:59

Hmm. This seems to have something to do with datomic. I added exclusions like this: [com.datomic/clj-client "0.8.606" :exclusions [org.eclipse.jetty/jetty-http]] and eventually got it to run. Now the lein ring server starts but attempting to connect to it just results in a connection reset

hmaurer12:07:02

Why does (if-let [x y] ...) expands to

(let*
 [temp__4655__auto__ y]
 (if temp__4655__auto__ (clojure.core/let [x temp__4655__auto__] ...) nil))
and not to
(let [x y]
  (if x ...))
?

pesterhazy12:07:47

so that x doesn't have to be re-evaluated multiple times

pesterhazy12:07:31

Different question: Is this an ok way to access both the first arg and all args? (fn [& [head :as all]])

hmaurer12:07:28

how would x be re-evaluated multiple times in that scenario?

pesterhazy12:07:33

user=> (macroexpand-1 '(if-let [x (do (prn :foo) true)] [x x] (prn :no)))
(clojure.core/let [temp__6751__auto__ (do (prn :foo) true)] (if temp__6751__auto__ (clojure.core/let [x temp__6751__auto__] [x x]) (prn :no)))

pesterhazy13:07:18

i.e. in cases where x is used in the body of the if-let

hmaurer13:07:45

@pesterhazy it still wouldnā€™t get evaluated multiple times with

(let [x (do (prn :foo) true)] (if x [x x]))

pesterhazy13:07:09

isn't that pretty much what the actual implementation does?

bronsa13:07:37

@hmaurer that binds x in the else branch

bronsa13:07:41

if-let doesn't

bronsa13:07:52

that's what the extra local binding is for

hmaurer13:07:00

@bronsa oh, I see. that makes sense; thanks!

hmaurer14:07:23

I am getting a StackOverflow error when trying to use log4j with Leiningen, could someone please take a look at the stacktrace? https://gist.github.com/hmaurer/40c1bc6d08550222f65e06a6366f0eb9

hmaurer14:07:37

fixed it by removing a few dependenciesā€¦ still strange though, I would like to understand why simply adding dependencies to project.clj could cause a stackoverflow error when launching the repl

jpmonettas14:07:05

Hi everyone, I've been doing some experiments on visualizing clojure.spec fails and ended up wrapping them in a library

jpmonettas14:07:55

maybe it's useful to someone else

sbrg15:07:53

Given that I have figwheel set up to use a ring handler via :ring-handler, and that handler is also set to auto reload via ring.middlware.reload/reload, is there some way I can make it reload everything? Basically restart the whole deal. I'm working with a library called sente which is for websocket communications, and it doesn't look like the code that initializes everything related to that is being re-run, so it's kind of painful to iterate.

jpmonettas15:07:49

what I do is put all the code that has a lifecycle into https://github.com/stuartsierra/component so I have a way to restart the entire thing

sbrg15:07:02

@jpmonettas Hmm, alright. I'll see if I can whip something up that works. Thanks šŸ™‚

jpmonettas15:07:54

don't know if you are currently using something like components or mount

jpmonettas15:07:07

but I've done that with sente

jpmonettas15:07:29

you create something like a web-server component, and in the start/stop of that component you start/stop http-kit server, sente channels etc

sbrg15:07:04

Nah, not using anything like that. I'm pretty new to all of this, so still trying to figure out best practices and what people are doing etc. Okay, I see. Is it possible to get that to play well with figwheel using :ring-handler?

jpmonettas15:07:18

I mean, if you move all the stuff that deals with state into components, and then create a system(a bunch of components) you end up with a restart fn you can use wherever you want

jpmonettas15:07:56

I never fired it from that reload middleware but can't see any issues with that

sbrg15:07:36

I see. I guess I just don't quite grok how all these things work together. But I'm sure I can come up with something from what you've told me. Thanks!

scaturr18:07:35

does anyone have a pro-tip/link to an example of using core.async with ring? or some other http server? like how does one wait for input on a channel and flush said result to a response?

noisesmith18:07:37

aleph actually has an async request handler infrastructure - and it uses manifold that is designed to integrate easily with core.async

noisesmith18:07:03

if you use eg. jetty your async code will run but there will still be a blocking thread per request until you respond

noisesmith18:07:51

the real question I guess is why you are using async, then you can use that answer to guide how you integrate that with a ring server

noisesmith18:07:13

for the go-loop as you show it, you end up with a single block of code that can only deal with one request at a time - thereā€™s valid reasons to do this sometimes but itā€™s a pretty severe bottleneck

scaturr18:07:19

awesome - I will look into aleph. I was thinking of using core.async as a general abstraction on input/output

scaturr18:07:55

something like that

noisesmith18:07:12

when I say ā€œone request at a time in the blockā€ I mean globally, only one of your requests can be in that block - so if you have five concurrent clients, it takes 5x as long to complete

noisesmith18:07:37

which usually isnā€™t the kind of behavior you want in a web server at all

scaturr18:07:44

yeah šŸ˜•

scaturr18:07:13

trying to figure out how to use the results of (>! out) in that example

noisesmith18:07:31

with manifold, you can set up a function that gets called with an input channel and an output channel, and it is instantiated as many times as you get requests, which is a more reasonable pattern of behavior

scaturr18:07:58

aleph + manifold seems to be the ticket. many thanks for pointing me in that direction šŸ™‚

hmaurer18:07:27

Is there a way to quickly run tests when a file changes? Manually running lein test takes about 10s to boot for me, and using https://github.com/weavejester/lein-auto take the same time

hmaurer18:07:46

I assume the delay is coming from the jvm boot time, but I donā€™t know how to avoid it

noisesmith18:07:12

@hmaurer fyi lein test just uses clojure.test, and you can require that and run (clojure.test/run-all-tests) in your repl (after requiring your test namespaces of course)

bfabry18:07:28

@hmaurer I'd recommend running tests from a persistent repl, and using something like clojure.tools.namespace to ensure code is reloaded and up to date

hmaurer18:07:22

thanks! hadnā€™t thought of that

bfabry18:07:11

fwiw, I always have something like this in user.clj

(defn run-unit-tests []
  (repl/refresh)
  (test/run-all-tests #"^project-ns.*$"))

bfabry18:07:28

I also use Cursive to run single test files a lot

hmaurer18:07:58

@U050MP39D I am trying to avoid Cursive for now to get a first-hand experience on clojure, and not have too much hidden behind IDE magic

hmaurer18:07:03

but Iā€™ll definitely try it out at some point

bfabry18:07:41

that's fair, and to do what cursive does without cursive it's basically just (do (repl/refresh) (test/run-test ...))

bfabry18:07:20

repl in this case is clojure.tools.namespace.repl and test is clojure.test

hmaurer18:07:07

@U050MP39D yep, right now I have a function ā€œreloadā€ which calls clojure.tools.namespace.repl/refresh, as well as restarts my system

hmaurer18:07:11

I guess I can just run the tests there

noisesmith18:07:41

you could hook up the run-all-tests to run as part of your system refresh if you have such defined

hmaurer18:07:00

@noisesmith ah, good point. Thanks!

hmaurer18:07:12

are there any ā€œgood practiceā€ I should be aware of regarding testing clojure? (either tools/libs or approaches). Or should I just get started with clojure.test?

hmaurer18:07:24

Also, is it advisable to place pre/post conditions on every ā€œcoreā€ functions of an app? Including spec checks on arguments.

noisesmith18:07:05

one thing to keep in mind is that testing functional code is easier than what you are probably used to

noisesmith18:07:34

good functional design in general separates the mutable / side effecting source and sink of your data from the immutable guts

noisesmith18:07:59

if you do that right, you can unit test the immutable guts easily, and separately verify that the mutable input and output logic works

noisesmith18:07:26

where the input and output would likely be integration tests, or even better they can be verified by the tests on the separate code implementing the i/o

noisesmith18:07:39

@hmaurer what that looks like in the big picture is a bunch of immutable code that does no io or side effects, and a top level ā€œdriverā€ that connects that to data - which can easily be subbed out by a lambda or direct function argument in your test

hmaurer18:07:09

@noisesmith Ok, Iā€™ll try to follow that idea. I have done some FP before so itā€™s not completely unfamiliar. The app I am currently working on is very much CRUD, so I donā€™t think there will be that much distinction to make betwen i/o code and pure functions (almost everything does i/o)

hmaurer18:07:21

Last but not least, is Midje worth looking into?

noisesmith18:07:35

I donā€™t like midje at all

hmaurer18:07:31

so according to you, clojure.test is all I need to get going?

noisesmith18:07:54

yeah - but there are some nice additions to it, like difftest

noisesmith18:07:24

expectations is decent too

hmaurer18:07:00

Alright, thanks! Also, whatā€™s your stand on using pre/post conditions on functions. Is that something that should be done?

tbaldridge18:07:22

I'd stick with spec for that sort of thing, it's pretty much pre/post v 2.0

noisesmith18:07:54

I found problems where they were being missed at dev time and caught things at run time, and they throw AssertionError which our try/catch blocks werenā€™t catching which led to annoying hard to debug failures

noisesmith18:07:14

(especially inside futures and go blocks)

tbaldridge18:07:54

on the subject of testing though, what I like in a testing lib is utter simplicity. A testing framework really only needs to be about 100 lines of Clojure code. Clojure.test is about 500 but that's mostly cruft that could be stripped out (by breaking backwards compatibility).

noisesmith18:07:47

yeah, I find if something is hard to test with clojure.test thatā€™s a sign my code is too ā€œfancyā€ for its own good and the easier to test code is better

tbaldridge18:07:39

Also, if you find code that re-defs vars for testing/mocking that's a bit of a code-smell, imo. It's not always avoidable, but the cases when you need with-redefs or the like should be really rare.

hmaurer18:07:13

@tbaldridge good point, when I read about with-redefs it did seem to be like a ā€œbetter avoid if possibleā€ construct

tbaldridge18:07:00

@hmaurer what editor are you using?

hmaurer18:07:05

regarding the short test lib I just wanted to make sure. Some other languages tend to have rather large ā€œtesting frameworksā€, and while clojure.test seemed enough it felt a bit like cheating

hmaurer18:07:11

@tbaldridge Atom at the moment

tbaldridge18:07:18

Some like Cursive (and I think Cider as well) have keybindings for running tests via a IDE command

hmaurer18:07:24

Intentionally avoiding deep editor integrations (Cursive and Cider) for now

tbaldridge18:07:03

fair enough, so yeah, you can send across run-all-tests or write some sort of editor macro that dumps that into a repl for you

tbaldridge18:07:23

Something like that could be coded with emacs+inferior lisp with about 10 lines of code, so I assume Atom would be close to the same.

tbaldridge18:07:52

I also bind CTRL+` to "send the sexpr under the cursor to the repl". That's also a big time saver.

bfabry19:07:54

simplicity is great but it kind of sucks that midje had better tooling baked in 2 years ago than exists for clojure.test at all today

tbaldridge19:07:32

what sort of tooling?

bfabry19:07:50

the midje repl tools, autotest for one

tbaldridge19:07:14

As mentioned things like auto-runners are a bit pointless in Clojure because there shouldn't be a reason to restart the repl

tbaldridge19:07:32

it's more of a design difference than a lack of tooling.

bfabry19:07:35

the midje autotest ran at the repl

tbaldridge19:07:18

interesting, I never had it running that way, but honestly I'd be a bit nervous of something auto-running my code whenever I change it.

bfabry19:07:27

midje: at repl (midje.repl/autotest) clojure.test: ? need some leiningen plugin thing which is bound to break with other lein plugins

tbaldridge19:07:40

Woudln't want to accidentally type (sh/sh "rm -rf foo") then accidentally delete 3 characters from that string ^^

bfabry19:07:41

... I mean. test autorunners have been around since junit and I've literally never heard of someone managing that (not saying it's not possible, but sheesh)

tbaldridge19:07:29

So to make it a bit more concrete, my workflow is this: * Edit some code * Send it to the repl with either "send form" or "reload current namespace in repl" * Test the code I just sent by hand, normally with a few bits of code I keep in a (comments ...) block * Once it appears to work, I switch to the test namespace and re-run all the tests, or maybe just the tests I care about (keybindings for that)

tbaldridge19:07:15

But with a REPL you end up doing a lot lest test-driven development. It's not "write test", "write code". It's more like "write spec", "write code", "play in repl", "fix code", "write a test if it needs to exist".

bfabry19:07:46

that is also my workflow, but having worked with good autorunners before I can say from experience a good autorunner is still an improvement to that workflow

tbaldridge19:07:23

But how much time does that save? Like 3 sec every 10 min?

bfabry19:07:27

I mean, that would add up to quite a lot over a year programming

bfabry19:07:39

honestly if it worked well it would probably add up to more though. my test suite takes longer than a 3s difference between the full suite and the "tests affected" set for most things

tbaldridge19:07:58

That's kindof my point though, when I'm trying to fix a specific bug, I run all the tests, then pick one failing one, and make that work. Whenever I make a code change I rerun only that single test.

bfabry19:07:16

which is what an autorunner does for you. I'm not sure I understand the objection to having the computer do it instead of doing it yourself

tbaldridge19:07:27

Because the computer won't do it right

tbaldridge19:07:14

And if there's one thing that utterly kills my productivity, it's making a change and then seeing that a test didn't pass due to stale code.

bfabry19:07:51

when I used these things back in ruby days, the vast majority of the time it did. when it didn't there was nothing stopping me manually intervening

tbaldridge19:07:10

Stuff like Java imports of deftypes, global state, multimethod dispatch functions, etc. All those things break most autorunners (even Midje in some cases)

bfabry19:07:30

those things break everything. tools.namespace, the repl, etc etc

tbaldridge19:07:41

not the repl though

tbaldridge19:07:02

the repl only does what I tell it to, so whenever I change a form I reload it. or the entire namespace.

bfabry19:07:26

that's not going to help you with any state referring to the old protocol. this is a well documented annoyance. whatever, fine, it all works perfectly for you. I'm just saying I've done the clojure workflow both with a good autotester and without and it was better with one

noisesmith18:07:03

some people like it, especially if they are used to that kind of dsl for testing

bfabry18:07:30

I like midje. but it wasn't widely embraced and the lead developer is done with clojure. I would not start a new project with it

hmaurer18:07:14

where is he gone to?

bellp18:07:34

Iā€™ve been using Midje lately but have found some bad issues. One being dependency errors get swallowed and are a pain to fix.

tbaldridge18:07:03

For better or worse, Midje is a DSL, your tests aren't written in Clojure they're written in a Midje testing language. And yes, that can be the source of a lot of confusing errors.

bellp19:07:29

What do you use?

hcarvalhoaves19:07:59

There are more people maintaining Midje after Marick (we are big users of it where I work at).

hcarvalhoaves19:07:50

While I can't speak for the future, in the short term it should be up-to-date.

tbaldridge20:07:24

@U69US8BKQ clojure.test. And I wish it was simpler šŸ™‚

tbaldridge20:07:53

All a testing lib really needs is deftest (that generates a tagged function), some sort of smart assert, and a run-all-tests

seancorfield20:07:46

@U69US8BKQ I'll put in Expectations which is more BDD in style than clojure.test's assertion-based format -- and now supports all the clojure.test tooling.

seancorfield20:07:13

There's an #expectations channel if you have any questions.

devn19:07:25

lazy question: @seancorfield is there any notion of "business time" in clj-time?

seancorfield20:07:55

Using that with https://github.com/dm3/clojure.java-time ought to get you what you need, fairly cleanly.

seancorfield20:07:26

FYI, at World Singles, we're slowly migrating away from clj-time to clojure.java-time (or just using Java Time directly).

dominicm20:07:21

That's interesting. We've been making a similar move too.

seancorfield20:07:42

See this https://github.com/clj-time/clj-time/issues/196#issuecomment-294067755 -- and read the whole thread for background. It is a discussion around moving clj-time to JSR-310 and the pros and cons... and why, ultimately, I came out against the switch of implementation and why I would encourage folks to use clojure.java-time instead of clj-time if they want to switch from Joda Time to Java Time.

avi20:07:14

<deleted>

avi20:07:34

Ah, sorry, I guess Iā€™ll delete that and post it to #clojure-spec

schmee20:07:51

I have a Clojure design problem which Iā€™d love some feedback on. I have a SeriesStore record and corresponding SeriesStore protocol. There are different stores for different accounts etc, so I need some way to create these stores. Iā€™m considering two options: 1. Have a regular fn that is a closure around all dependencies of the store, and then pass that fn around 2. Create another record which contains all the dependencies, e.g SeriesStoreFactory, and then pass an instance of that record around. i.e regular fn closure vs. record, which is preferable and why?

tbaldridge20:07:53

Records almost always win @schmee for the simple reason that functions are opaque. Once you close over something with a function there's no way to introspect the closure to see what you closed over.

tbaldridge20:07:25

Sometimes you need that for debugging, other times just to do keys or to otherwise get the state out inside some function.

plins20:07:53

hello everyone while using clojure.test its possible to share data between tests? something like

(def data (atom :none))
(deftest t1 ... (reset! data 10))
(deftest t2 ... (do-stuff 10))

plins20:07:27

(do-stuff data) *

hmaurer20:07:16

If I wish to set up some data that should be accessible to all tests (either set up once before all tests or set up and tear down before and after each test), how can I do it with clojure.test? with-fixtures doesnā€™t appear to let me pass data down to the test. I could use a global atom but that seems nasty

hmaurer20:07:29

@plins oh wow, haha, I hadnā€™t read your message before posting

hmaurer20:07:34

looks like we have the exact same question

schmee21:07:12

@tbaldridge sounds reasonable. but sometimes you want it opaque though? my main concern with records is that I want to keep it as functional as possible, and I worry that my code will start to look like OO if there are too many records all over the place. whatā€™s your experience on striking the right balance between records and fns?

bfabry21:07:29

@schmee records are still immutable. they're still functional

owen21:07:55

@schmee in clojure Ive never been like, I wish I had less information at my disposal

tbaldridge21:07:03

Right, you got to separate out "is a protocol" from "looks like OOP"

bfabry21:07:24

polymorphism is orthogonal from "functional" imo

owen21:07:26

also I would recommend checking out stuart sierra's component or weavejesters integrant

tbaldridge21:07:49

OOP = information hiding, local mutation, and inheritence

tbaldridge21:07:58

records and protocols don't do any of that.

schmee21:07:41

true, true. and I actually have polymorphism in this case, so Iā€™ll go with records. thanks for the input!

schmee21:07:13

@owen Iā€™ve tried the whole gamut of state management libs in clojure, Iā€™m currently experimenting with https://github.com/vspinu/commix which I think is fantastic so far!

owen21:07:31

šŸ™‚ there are alot, I havent even heard of this option

schmee21:07:45

Itā€™s less than a week old šŸ˜„

owen21:07:52

sounds ready for production to me

schmee21:07:23

I wouldnā€™t, but hey, I wonā€™t judge you šŸ˜‰

tbaldridge21:07:47

Better than most node libraries! #burn

owen21:07:55

> Commix was built as a response to a range of limitations in Integrant which in turn was designed to overcome limitations in Component.

owen21:07:23

turns out dependencies are hard?

hmaurer21:07:31

Iā€™ve been using integrant for a couple of days, it has been great so far

owen21:07:51

I liked it as well when I compared it with component

schmee21:07:18

I tried using Integrant but I immediately found myself working around it instead of with it, then I stumbled over commix here: https://github.com/weavejester/integrant/issues/21

schmee21:07:54

I recognized some of the problems I encountered in the ā€œdifferences from Integrantā€ section

schmee21:07:20

anyways, more options on the table, more innovation = win for everyone

hmaurer21:07:40

Does anyone have a recommendation for me on how to share some stuff between tests? e.g. a database connection

plins21:07:02

well if is something static i think you can just

(def db-spec (..))

(deftest test
   (jdbc/query db-spec ..))
i really would like to know how i can share data that is produced by one test in another test

hmaurer21:07:28

@plins why would you want to do that?

plins21:07:36

im trying to do some sort of all-or-nothing integration api integration test imagine that i do a request to create an user, and it returns me an id afterwards in another test id like to user this id to create a bank account for this user (or something like that)

hmaurer21:07:02

@plins ah, I was planning on doing the same thing. It seems to me this should be done within one test block? I donā€™t think there are much guarantees as to in which order tests will run

hmaurer21:07:06

and you would rely on order there

plins21:07:23

im trying to avoid a giant let with tons of implicit tests, but i seems that i got no other option

hmaurer21:07:45

@plins I am a newb, but what do you think would be the issue? You can nest testing calls to create context

bfabry21:07:58

dynamic vars and a fixture would be another option but probably not a very good one

hmaurer21:07:26

do you have a better option? dynamic vars is all I can think of

bfabry21:07:00

unless there's a serious desire to split the tests across multiple files I would go the huge let block over the dynamic vars

hmaurer21:07:00

@U050MP39D huge let blocks canā€™t be shared across tests though

bfabry21:07:41

if they can't I wasn't aware of it

bfabry21:07:23

well they can't be shared across deftests I guess, but they can be shared across assertions

hmaurer21:07:24

@U050MP39D would you mind showing me a quick example?

hmaurer21:07:42

is it common to have a lot of testing blocks under a single deftest?

bfabry21:07:47

I guess I'm generally a bit ambivalent about the difference between "tests" and "assertions". I don't really care about the granularity

bfabry21:07:51

I don't know about common, but I would prefer it over fixtures populating dynamic vars

hmaurer21:07:11

+1. I agree, the granularity is a bit confusing

hmaurer21:07:02

and from what I just inferred from the source of testing, it returns its last expression

hmaurer21:07:09

so you could use that to pass values around

hmaurer21:07:11

not sure thoughā€¦

plins21:07:39

the last line of deftest is returned?

hmaurer21:07:21

(defn- create-user-account []
  (testing "Create a user account"
    (let [user-account (app/create-user-account)]
      (is (= ....))
      user-account)))

(defn- create-bank-account [user-account]
  (testing "Create bank account"))

(deftest scenario-1
  (let [user-account (create-user-account)
        bank-account (create-bank-account user-account)]))

hmaurer21:07:39

I donā€™t know if you can use testing outside a deftest though

hmaurer21:07:47

if you canā€™t, just move it to within the deftest

hmaurer21:07:08

I havenā€™t tried it though, and completely new to clojure.test, so donā€™t take my word on it

plins21:07:45

i wanst aware of the testing function / macro

plins21:07:55

will check it out thanks šŸ˜„

hmaurer21:07:43

@plins I just tried to use testing inside a defn- function called from a deftest and it worked, but the doc says `May be nested, but must occur inside a test function (deftest).`, so I am not sure how to take it

hmaurer21:07:02

maybe it means it will work so long as itā€™s called within the callstack of a deftest function

hmaurer21:07:08

or maybe I am doing something very wrong šŸ˜„

seancorfield21:07:25

@hmaurer I just did a macroexpand of (testing "foo" body) and it looks like it relies on dynamic calls for context so I think you're OK -- but it's definitely a bit unorthodox.

seancorfield21:07:52

(macroexpand '(clojure.test/testing "foo" (something)))
=>
(let* 
 [] 
 (clojure.core/push-thread-bindings 
  (clojure.core/hash-map 
   (var clojure.test/*testing-contexts*) 
   (clojure.core/conj clojure.test/*testing-contexts* "foo"))) 
 (try (something) (finally (clojure.core/pop-thread-bindings)))) 

hmaurer21:07:26

@seancorfield so deftest sets a dynamic var which is available anywhere within the callstack during its execution?

hmaurer21:07:33

thanks for checking it!

hmaurer21:07:57

do you have a better suggestion to do what I was trying to do? (split a test in this way)

hmaurer21:07:18

is it ā€œnot okā€ for some reason to split a test in multiple functions that way?

hmaurer21:07:36

it seems that it improves composability

seancorfield22:07:24

I haven't seen it done that way before -- so it looks unfamiliar -- but if clojure.test manages all of its testing context dynamically, I guess it's fine. I guess I would have a specific test for each creation function that asserted whatever behavior I expected (and cleaned up after itself), and then in the main test I'd just call the creation functions without worrying about testing or is...

seancorfield22:07:56

In other words, I'd only have "one" test for those common things, rather than repeating the tests every time they are called.

hmaurer22:07:16

Ah, I see.

dominicm22:07:57

How should a regex look for the :aot option in leiningen?

dominicm22:07:19

The way I used it seems to have no effect

hiredman22:07:59

are you sure you want to aot compile?

hiredman22:07:24

if you don't have :gen-class in a ns form, compile is a nop, and if you don't have gen-class I doubt you really want to aot compile

dominicm22:07:25

@hiredman I'm sure. I'm trying to minimize startup time in resulting jar.

dominicm22:07:09

I noticed that most ns don't necessarily get aot'd, when I stripped out clj files jar started to fail

mattly23:07:22

does anyone know of a library for doing set-like operations (`intersect`, union) on possibly infinite sets?

mattly23:07:36

f.e. (set/union inf/all #{1}) => inf/all or (set/intersect inf/all #{1}) => #{1}

mattly23:07:10

I'm crawling through a clojars search but figured I'd ask

hiredman23:07:39

I suspect what you want is a symbolic logic library

mattly23:07:18

I didn't find anything in my quick searching, but rolling my own shouldn't be too hard

mattly23:07:33

just gotta figure out what infinity looks like

hiredman23:07:20

oh, just because that is a more logic based representation of a set vs. a datastructure

mattly23:07:18

for my use case, 95% of the time it'll fall back to regular set ops

mattly23:07:45

can you recommend a good primer on the topic of symbolic logic programming?

mattly23:07:00

the core.logic readme mentions The Reasoned Schemer

hiredman23:07:36

core.logic isn't really that, the little prover (which shares an author) would be more like it

mattly23:07:58

I actually have enough time to read this before I have to tackle this problem for real