#clojure log - Feb 23 2016

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:00 solatis: (declare ^:dynamic *queue*)


0:00 (defn fixture [f]

0:00 (binding [*queue* "foo"]

0:00 (f)))


0:00 would anyone say that's idiomatic clojure? or is it an anti-pattern?

0:01 to me it feels like side effects/leaking... but i cannot find another way

0:02 tolstoy: You could also use an atom and pass it in as a param to your tests.

0:02 solatis: can i pass atoms as params in tests?!

0:02 https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L635

0:02 tolstoy: Oh, well. Hm.

0:03 solatis: looks to me as if a test function is defined as a function that doesn't accept parameters..

0:03 tolstoy: Or make a macro and don't bother with the fixture.

0:03 solatis: yes, but i'll be damned this is a big limitation to fixtures

0:03 tolstoy: I think a dynamic var might be fine for tests, as long as there's no threading going on. Kinda depends.

0:03 solatis: yes you are correct

0:04 tolstoy: It's always dangerous to ask here on #pedantic. You can do whatever actually works, esp. if you're on a deadline. I mean, totally rethinking your entire architecture to avoid the problem is an option, too. ;)

0:05 solatis: well i'm strong in functional programming (haskell especially), but new to clojure/lisp

0:05 so i'm not sure what's most idiomatic in clojure

0:06 but i _do_ notice when something feels a bit off :)

0:06 tolstoy: Why do you need to pass around something to all the tests?

0:06 solatis: in this case, an ad-hoc message queue that is created and destroyed in the fixture

0:07 but it could also be a database connection, whatever

0:07 i think what i really want to write is a (with-queue [name]) function

0:07 tolstoy: Seems like I've solved that before. Hm.

0:07 Yeah, a macro is good for that, too.

0:08 solatis: that's what i figured

0:08 it would allow me to create and drop the queue within a macro

0:08 or rather, expose the dynamic var

0:08 ehr

0:08 hide

0:08 whatever

0:08 tolstoy: Oh, wait. There's a version of fixture that runs just once for all the tests in the namespace.

0:09 solatis: that would mean that tests will not be isolated

0:09 because they share the same message queue

0:09 tolstoy: So, (reset! queue-atom (set-up ...)) (f)) then just reference queue-atom everywhere you want it.

0:09 solatis: oh!

0:09 that's interesting

0:09 let me look it up

0:10 tolstoy: (use-fixtures :once fix1 ..) vs (use-fixtures :each f1 f2).

0:11 You could also run a single (deftest ...) which just calls a bunch of functions with assers in them.

0:11 asserts.

0:12 Maybe not so good if you need all that fine-grained junit stuff. You know, if you're testing for Mgmt or testing for actual dev. ;)

0:13 I think one test with 100 asserts means you're a slacker, but 100 tests with 1 assert each means you're super productive.

0:13 /join #bitter

0:18 I wonder if you could do a closure as well (let [queue (construct) (deftest a ...) (deftest b ...))).

0:18 Oh, no, nevermind. Bad idea.

0:19 solatis: tolstoy: well what i'm looking for is doing this the way it's "supposed to be done".

0:19 i mean, this really feels like it should be a solved problem

0:19 but dynamic vars feel a bit like magic

0:20 it's one of the major reasons i hate scala

0:20 tolstoy: I think the (use-fixtures :once ...) is the way it's solved.

0:20 solatis: i do that, and then i need to do the reset! thingie to pass around the queue ?

0:21 tolstoy: Yes.

0:21 solatis: my problem is not finding out how fixtures work, my problem is that i need to pass an argument to each test function -- so my only option appears to be to use a "hidden" argument

0:21 tolstoy: (def queue (atom nil))

0:22 (defn fixture [] (try (reset! queue (make)) (f) (finally (when @queue (.close @queue)))))

0:22 Something like that.

0:22 solatis: WAIT

0:22 i feel like an idiot

0:22 tolstoy: (deftest foo (is (= 42 (take @queue))))

0:22 solatis: i could just as well just def this, right?

0:22 oh

0:23 that seems more elegant

0:23 tolstoy: I've done that for testing a web service. Inject in a fake database component, then just start up the "real" web service and start calling APIs.

0:24 solatis: yes

0:25 tolstoy: Another "food for thought" is that you make your queue interface a protocol, then just implement a fake one for testing. Then it doesn't matter.

0:26 solatis: yes

0:26 that's the "best" solution

0:26 but too complicated for now

0:30 ode: I have a one vec of maps and another seperate map.

0:30 How do I update only one map in the vec which has the same value for a key as the the value in the seperate map?

0:34 tolstoy: Maybe use reduce?

0:35 Create a function that tests one map against another map. If there's no map, it returns the original. If there is a map, it returns the updated map.

0:35 Then just do (map #(xform % single-map) vector-of-maps).

0:36 Or loop/recur (so you can short-circuit once the match is applied), or reduce (so you can call reduced to short-circuit).

0:39 ode: thanks, I think I was overthinking it. I will use reduce.

1:29 amalloy: typically you want to not have a vector of maps with an id key. if you are doing lookups and modifications by id, that id should be the key in a map, so you can get fast lookups

1:41 Mendoza: Someone here does android programming?

1:43 lxsameer: Mendoza, using clojure?

1:43 Mendoza: Wanting to move from Common Lisp to Android

1:43 lxsameer: Mendoza, join #clojure-android

1:44 Mendoza: That's a good idea haha, thanks

1:45 tolstoy: amalloy: Ah, good call. I didn't realize that's what ode was doing.

1:56 sooheon: amalloy: This is off topic, but do you make videos on youtube for a certain roguelike game?

1:56 amalloy: i do. and a couple other games since i started

1:57 sooheon: wow that's pretty cool, I was persuing that channel the other day, didn't know you were into clojure as well :)

1:57 was almost confused which irc channel I was in for a second

1:57 amalloy: you hang out in ##crawl, i guess? i don't, these days, but i am usually in ##crawl-dev

1:58 sooheon: yeah off and on

2:01 I enjoy your stuff. It'd be cool if you had some clojure programming vids on there as well haha

2:06 kolt: kolt - Im using 4clojure and have no idea how to solve the third problem, any help?

2:17 sooheon: link?

2:18 kolt: Do you mean https://www.4clojure.com/problem/3?

2:18 kolt: I solved it, they are hard and they don't give any hints :(

6:33 dazlow: how do I compile clojure code in realtime? Like, from raw string?

6:34 zipper: dazlow: Clojure is automatically compiled. Everything you run in clojure is bytecode.

6:35 Uh what do you have in clojure to support complex types? Like the way haskell has typeclasses and OOP has objects?

6:35 dazlow: zipper: No, I mean, not like from leiningen, but I have gui app and text field, I'd like to compile what user types as code

6:35 zipper: dazlow: Is what the user types valid clojure?

6:36 Have you read about clojure

6:36 incomplete

6:36 clojure's eval model?

6:37 When everything is a tree? You can make your stuff into a list (tree) and call `eval` on it?

6:39 dazlow: zipper: oh, ok, I'll try that

6:40 zipper: dazlow: Have time to read? I can refer you to something.

6:40 dazlow: Does the user enter valid clojure?

7:57 TimMc: dazlow: I'm going to give you the footgun necessary for this: (eval (read-string ...))

7:58 dazlow: I assume you trust the user not to write anything malicious? Because sandboxing is very hard, and if you want to accept untrusted input, you've got a tough road ahead of you.

8:00 ridcully: you can shoot off any body part with that line ;)

8:01 MJB47_: what about your second trigger finger?

8:57 ddpigui: Hello

8:57 I am creating a project anyone good at art

8:58 recycle


8:59 ridcully: ddpigui: this channel is about the programming language clojure

9:03 ddpigui: ik

9:03 I am using clojure in my project

9:04 MJB47: yo ive used clojure before, is anyone here good at business planning?

9:04 ddpigui: Anyone Good at art

9:05 ridcully: ddpigui: if you are looking to hire clojure developers here, maybe you could structure your request better? what is "art"?

9:05 and what is "good"?

9:06 ddpigui: clear

9:06 So is anyone good at art!

9:06 So far this is the logo PS it looks bad https://github.com/alwaysontop617/PIgui/blob/master/logo.png

9:13 So far this is the logo PS it looks bad https://github.com/alwaysontop617/PIgui/blob/master/logo.png

9:14 TimMc: Agreed, but you're asking in the wrong place.

9:15 Empperi: even though clojure is kind of art I agree with TimMc :)

9:15 TimMc: Late one night, a man walks into a dentist's surgery and says, "Excuse me, can you help me? I think I'm a moth." Dentist: "You don't need a dentist. You need a psychiatrist." Man: "Yes, I know." Dentist: "So why did you come in here?" Man: "Well, the light was on."

9:16 ddpigui: Kk anyone who wants to join the pigui project join #gopigui

9:40 TimMc: ,(with-redefs [dec inc, inc dec] (inc 5))

9:40 clojurebot: 6

9:40 TimMc: ,(with-redefs [inc dec, dec inc] (inc 5))

9:40 clojurebot: 6

9:43 hiredman: is that a question?

9:44 gfredericks: ,(with-redefs [dec inc, inc dec] (apply inc [5]))

9:44 clojurebot: 4

9:45 gfredericks: ,(with-redefs [inc dec, dec inc] (apply inc [5]))

9:45 clojurebot: 4

9:45 gfredericks: I guess that first one is a bit surprising?

9:45 ,(with-redefs [dec inc] (with-redefs [inc dec] (apply inc [5])))

9:45 clojurebot: 6

9:45 gfredericks: ,(doc with-redefs)

9:45 clojurebot: "([bindings & body]); binding => var-symbol temp-value-expr Temporarily redefines Vars while executing the body. The temp-value-exprs will be evaluated and each resulting value will replace in parallel the root value of its Var. After the body is executed, the root values of all the Vars will be set back to their old values. These temporary changes will be visible in all threads. Useful for mockin...

9:46 gfredericks: "in parallel" ⇑

9:47 hiredman: inc is inlined during compilation, the code generated by with-redefs doesn't effect vars until it is run, which happens at runtime, by which point your call to inc has been atleast replaced by a static method call

9:57 TimMc: there's that too

9:57 My point was the in-parallel bit, which I was mildly surprised by.

10:09 tangled_z: hi! I'm having trouble installing datomic. I downloaded datomic-pro from My Datomic and have run the repl at bin/repl from within the directory, but when I do "import datomic.Peer" it gives me a java.lang.runtimeexception: Can't take value of a macro: #;clojure.core/import'

10:10 any suggestions?

10:11 TimMc: (Note to self: with-redefs and midje do *not* play well together.)

10:14 hiredman: TimMc: I would say midje and clojure

10:15 tangled_z: bin/repl is a clojure repl, not a java repl

10:16 TimMc: In this case, a println I stuck in a with-redefs is demonstrating that the redefinition is sticking around outside of both the lexical and dynamic extent of the with-redefs...

10:16 hiredman: I know you would. :-)

10:17 tangled_z: hiredman: I'm following this tutorial: http://docs.datomic.com/getting-started.html#install

10:17 do I need to run a different command other than import.peer?

10:18 hiredman: tangled_z: that tutorial shows a groovy shell being used, not bin/repl

10:18 tangled_z: ooooh right

10:19 Ok, yeah, the command works in the groovy shell.

10:19 Thanks!

10:33 sdegutis: I'm back.

10:45 What's up?

10:50 tangled_z: I'm following a tutorial to use datomic from within a lein project, and when I run a function to create a database within the memory, it gives me a "java.lang.IllegalArgumentException : db.error/not-a-db-id Invalid db/id: #db.id[:d.part/user -1000011"

11:01 sdegutis: tangled_z: nice

11:01 tangled_z: also you have a typo in the keyword

11:04 hiredman: tangled_z: there is a #datomic channel

11:06 tangled_z: in general, the error messages you've typed in to the channel, and the fact that you tried to type groovy in to a clojure repl, have lead me to conclude you aren't approaching this in a very exact way

11:07 tangled_z: hiredman: That's probably true. What would it mean to approach it in an exact way?

11:08 hiredman: pay attention to the tutorial and do exactly as it says and double check that you are copying and pasting exactly

11:11 max3: can someone help me out here: http://www.braveclojure.com/do-things/#Symmetrizer . why is the recur variable remaining and not remaining-asym-parts

11:11 is it because both those names are bound to the same vector?

11:11 tangled_z: hiredman: hmm, okay. Yeah I just tried to do a git clone on the tutorial code ... and that compiled. so must be an error somewhere in my own code, sorry!

11:11 Yeah I should have tried that first. I was actually just worried that the error was due to me not having installed datomic correctly, but looks like that's not the case.

11:12 max3: ohhh i guess i should be thinking of loop as a recursive function and i'm just passing remaining and the (into as the two arguments

12:16 gfredericks: so test.check has this usability issue where when a property fails you don't get any information about *how*

12:16 which is normally only a problem for properties with more complex expectations

12:17 the main contrast is with clojure.test, where A) having "more complex expectations" usually means having multiple `is` calls, and you always know which one failed; B) it uses some offensive macromagic to dig a bit farther into the exact assertion you're making so it can report the failure a bit nicer

12:19 the main idea I'm thinking of for attacking this is having a protocol for test results; currently the result of a property is considered passing if it's truthy and not an Exception object (which is a bit messy)

12:19 you could have a protocol that includes the above behavior, but allows libs/users to make new implementations

12:20 so that a failing test can include data about the failure

12:20 TimMc: I wonder if there are other testing libs that have solved this well.

12:21 gfredericks: from a user perspective though, getting that to work means either A) users have to explicitly construct these objects B) they'd have a library of alternate predicate functions to use, like =, <, instance?, and, or, etc.; C) we'd use macromagic like clojure.test does to accomplish an equivalent to B)

12:21 TimMc: probably depends on your critera for "well" :)

12:21 test.check has until now followed the design philosophy that "well" includes "not super complicated"

12:23 TimMc: It's almost like you'd want assert statements that carry context.

12:23 gfredericks: yep :/

12:23 which could be its own library

12:23 TimMc: "Now I'm going into the first item of the vector, so any assertions in here should append that to their path."

12:24 xitrium: Hey, I'm getting a NoSuchMethodError: clojure.java.jdbc$query.invokeStatic trying to use Clojure 1.8. Any ideas why that might be happening?

12:24 gfredericks: I wrote a lib for debugging differences between data structures once

12:24 but since this is test.check any hypothetical libs would have to be contribs

12:25 TimMc: gfredericks: I've been pondering making an extension to prismatic/schema that produces user-friendly descriptions of schema failures.

12:25 hiredman: xitrium: are you sure you using clojure 1.8?

12:25 xitrium: all my projects dependencies list Clojure 1.8

12:25 gfredericks: TimMc: don't they already aim at user-friendliness?

12:25 hiredman: xitrium: are any of your dependencies aot compiled?

12:25 xitrium: yes

12:25 hiredman: xitrium: hard to say exactly, but that is almost certainly the problem

12:26 gfredericks: ~aot is almost certainly the problem

12:26 xitrium: the bottom-most project (that depends on the rest) uses :aot :all

12:26 clojurebot: 'Sea, mhuise.

12:26 hiredman: xitrium: is that a dependency, or your project?

12:26 xitrium: So I just can't AOT? I have a gen-class in there I need to export, doesn't that need aot?

12:27 it is the last Clojure project and becomes a dependency for a Scala project

12:28 hiredman: you might be able to swing it, but it will involve a much more digging around to figure it out

12:28 aot is very problematic so if you can avoid it you should

12:29 TimMc: xitrium: Does `lein deps :tree` show the right clojure version?

12:30 xitrium: TimMc: yep

12:30 hiredman: instead of using gen-class, you could write a java stub that calls clojure functions, and avoid aot that way

12:31 clojure has an api namespace meant to make it easier to call clojure from java now, and you might be able to just call that from scala too

12:31 https://clojure.github.io/clojure/javadoc/clojure/java/api/Clojure.html

12:32 xitrium: interesting

12:36 hiredman: ~aot

12:36 clojurebot: aot is almost certainly the problem

12:36 hiredman: close enough

12:37 xitrium: haha

12:38 hiredman: http://dev.clojure.org/jira/browse/CLJ-1886 aot leads to suffering

12:43 xitrium: :( so I'll try removing aot from a few projects and eventually migrating to the clojure java api

12:43 TimMc: http://i.qkme.me/3vb225.jpg <-

12:44 I actually have a back-burner story at work to remove AOT from some stuff.

12:45 hiredman: xitrium: aot is even worse if you aot compile a project and depend on it from a another project (which is what I meant by aot'ed dependencies)

12:45 gfredericks: ~TODO is remove AOT from some stuff

12:45 clojurebot: Ik begrijp

12:45 xitrium: ah

12:45 hiredman: that is almost guaranteed to result in what are more or less abi conflicts

12:46 and, actually, all kinds of other weird errors

12:48 because a. clojure's abi isn't stable, the way code is linked together can and does change (the direct linkage stuff was added in 1.8) so code built with different versions of clojure will have ahard time linking together and b. clojure's compiler operates by loading clojure code and writing the class files generate to disk

12:49 TimMc: We have a lib that's used by both Java and Clojure projects. It needs to export some Java interfaces, but AOT'ing th ewhole lib means it can't always be used from Clojure projects.

12:49 hiredman: which includes all the code in all the namespaces loaded durring compliation

12:50 TimMc: Clojure 1.7 or so introduces a change in how code is loaded that makes this intolerable, so I'm going to see about using the lein-otf approach on it.

12:50 hiredman: so if you aot a library, the jar contains, not only the class files from compiling your library, but the class files from compiling its dependencies

12:51 generally you can get away with some slop in versions, if a dependency has a dependency on version 1.0.0 of library L and you want to use version 1.1.0 or maybe even 2.0.0 or whatever, that can often work

12:53 but if your dependency has the class files for version 1.0.0 in its jar, you will often get version 1.0.0 even when you specify 2.0.0, or even some mix of 2.0.0 and 1.0.0

12:54 my old boss actually wrote a post to the clojure mailing list begging people to stop aot compiling libraries back in 2009

12:54 https://groups.google.com/forum/#!topic/clojure/Bs70_PUj-TY

12:56 so all that above is what you get from clojure's compiler

12:57 then you throw lein in to the mix, which at one time or another had various hacks and work arounds for b. (transitive compilation) but left a. (unstable abi) in place

12:59 the best work around lein could have would be to popup clippy if you try to aot compile a project with the message "No"

13:01 gfredericks: export LEIN_DONT_PREVENT_AOT_COMPILATION=1


13:03 TimMc: you know, the clojure repl has a -m option these days, even without lein-otf

13:03 java -jar your-uber-jar clojure.main -m your.main



13:38 justin_smith: TimMc: my approach is to make a rump namespace that has no explicit deps on any other ns (so it's only using clojure.core) and then inside it's -main or init it does a require and a resolve at runtime. That way I get one aot'd thing (that rump namespace) that can be called from the java infrastructure, without the pain of aot of any actual code that matters.

13:39 maybe lein-otf does that better/simpler though

14:17 TimMc: justin_smith: That's exactly what lein-otf does. It broke due to leiningen changes and I didn't bother fixing it because seriously, it's hardly worth the plugin.

14:19 justin_smith: aha

14:19 gfredericks: cfleming: let me know if you have any time this week to discuss details of test.check↔cursive stuff

14:39 sdegutis: Hi.

14:42 We would like all who are present to please respond with the number of distinct consonants in your own username. Thank you.

14:49 TimMc: justin_smith: Really, I need to just change the readme on lein-otf to give instructions on how to imitate what it would do. :-)

14:50 rcassidy: ,(count (clojure.set/difference (set "rcassidy") (set "aeiou")))

14:50 clojurebot: #error {\n :cause "clojure.set"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: clojure.set, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.ClassNotFoundException\n :message "clojure.set"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[ja...

14:50 rcassidy: whoops

14:52 ,(require '[clojure.set])

14:52 clojurebot: nil

14:52 rcassidy: ,(count (clojure.set/difference (set "rcassidy") (set "aeiou")))

14:52 clojurebot: 5

14:57 amalloy: TimMc: "lein-otf is a brain plugin masquerading as a lein plugin. Cut your load times in half with one simple trick! Sysadmins hate him!"

15:00 TimMc: amalloy: Ooh... on first run, it could use cowsay to explain how to do the thing.

15:02 or do the changes, then delete itself from the plugins list

15:03 sdegutis: rcassidy: I had similar solution

15:03 ,(->> "sdegutis" (distinct) (remove #{\a \e \i \o \u}) (count))

15:04 clojurebot: 4

15:04 sdegutis: Haha I'm in the 4 club alright go fourrrrs!

15:09 rhg135: I'm in the 0 club and 0 > 4

15:09 wait...

15:29 sdegutis: Haha yeah

15:56 CStorm: ive added auto-complete and ac-clojure, c/p the snippet from github to init.el and works when i in cider and run auto-complete-mode. however i cant get it to autoload it– annoys me a bit i have to run it my self. (auto-complete-mode 1) seems not to fix it in init.el

15:56 (emacs+clojure problem ^)

16:23 justin_smith: CStorm: you either need global-autocomplete-mode or auto-complete-mode 1 needs to happen in the context of each individual clojure buffer (perhaps on a clojure file load hook)

16:23 because right now you are just turning on auto-complete-mode on for the current buffer (probably scratch) at emacs load-time

16:27 ruph: /join emacs

16:42 gfredericks: /join linum-mode

16:43 * justin_smith is a /quitter

16:49 CStorm: just updated Cider.. shoudnt have done that haha

16:58 amalloy: classic cider

16:59 gfredericks: ~cider

16:59 clojurebot: cider is Try #clojure-emacs for more help with Cider

17:01 sdegutis: welp

17:02 TimMc: /join #clojure

17:03 CStorm: I hope you version your dotfiles.

17:05 gfredericks: I stopped checking in my emacs libs a long time ago, but I can't remember why

17:07 sdegutis: checking in?

17:07 like, into source?

17:07 controlv ersion?

17:07 (git)

17:07 gfredericks: yeah

17:09 sdegutis: gfredericks: my solution is to keep ~/.emacs.d/ in a git repo that's pushed to a bare-repo somewhere in ~/dropbox

17:09 clojurebot: 'Sea, mhuise.

17:09 sdegutis: gfredericks: i mainly only push to it when i plan to do a little work on my laptop, which these days is never

17:09 so i commit to it probably twice a year

17:10 also dont get me started on apple battery life, piece of cr

17:11 gfredericks: yep

17:18 TimMc: clojurebot: gfredericks: my solution?

17:18 clojurebot: gfredericks: my solution is to keep ~/.emacs.d/ in a git repo that's pushed to a bare-repo somewhere in ~/dropbox

17:18 TimMc: that bot

17:18 gfredericks: niice

17:19 TimMc: I version my dotfiles at work better than I do at home, even including my .bash_history.

17:19 gfredericks: I have a hybrid dotfiles system so I can share with work

17:24 TimMc: How does that work?

17:24 Some files are versioned in each repo, or you have branches?

17:25 I don't think I'd ever run fetch or pull in a dotfiles repo, since the risk of pulling something down *into my PATH* is a little too high for my tastes.

17:25 maybe if I signed the commits...

17:26 gfredericks: https://github.com/gfredericks/dotfiles/blob/master/bootstrap

17:26 we all have our own personal paranoia levels

17:27 TimMc: actually a better explanation is probably the README of that repo

17:38 I end up combining 3 or 4 different dotfiles sources depending on whether it's personal vs work, whether it's a local machine or a server, etc.

17:43 TimMc: haha: alias .....='.. 4'

17:45 gfredericks: I use those all the time

18:02 sdegutis: tomaw: ok thanks

19:09 gfredericks: macros and cljc never fail to confuse the hell out of me

19:11 also, I think I may have run into an unsolveable problem

19:12 currently test.check's clojure.test integration consists of a macro (defspec) that expands to code that calls a function (assert-check)

19:12 the clojure.test/is expression is inside the assert-check function, which leads to file/line reporting from clojure.test always pointing to the assert-check function rather than the user's defspec use

19:12 so I said "I know, I'll convert assert-check to a macro!", and then I had two problems

19:13 hiredman: how so?

19:13 gfredericks: actually, now that I've rubberducked this far I'm not sure anymore

19:13 the clojure version works just fine but cljs fails saying "java" is not defined

19:14 my theory was that this was somehow tied to clojure.test and cljs.test having different namespace names

19:14 but now I'm entirely confused and have no idea

19:14 hiredman: well, like, if you just inlined the body of assert check in to the defspec macro, does it work?

19:15 gfredericks: GOOD QUESTION

19:15 hiredman: the stubstitution model says it should, and while that is the best, and is not always the correct model

19:20 gfredericks: hiredman: I'm hitting an even weirder error inlined, and don't have time to investigate right now, so will have to give up; but thanks for the hints

19:32 hiredman: I bet it is around making ct/is resolve to the correct thing on the correct platform, the defspec macro only exists on clojure, but the same macro expanded output will be used in both places

19:33 running the cljs tests for test.check seems like I would have to install node :(

19:43 WorldsEndless: What is the reason that I would want to deploy to wildfly inside a docker instance? Just if you would have a sticky (non-default) Wildfly setup?

21:10 WickedShell: why does (/ (float 10) (float 2)) yield a double? It seems like an excessive promotoion if it was given all floats?

21:11 hiredman: clojure generally will turn ints into longs and floats into doubles

21:13 WickedShell: Yeah I was aware of that, something I came across about boxing once lead me to the conclusion that if it was given equivelent primitve input types it would use the primitive without promotiing it...

21:13 I guess that's not the case, but its causing a huge flaw for me that is going to require writing java code to fix...

21:14 (I have to match the math that a microprossor is doing which calls for doing a floating point mul, then convert to int32, then undo it. And i don't see anyway to do that in clojure at all(

21:29 justin_smith: WickedShell: this sounds like a case where some java code, or maybe judicious use of no.disassemble, would be helpful

21:43 solatis: ok, so, i come from a Haskell background, where everything is lazy

21:44 however, i think in Clojure, this is not the preferred style

21:44 justin_smith: solatis: it isn't even a question of style, the only lazy thing is lazy-seq

21:44 solatis: right

21:44 justin_smith: you can use delays, but that's clumsy

21:45 solatis: so, if i write an interface to a message queue, the best thing would be to have a poll function that returns a sequence of messages available, right? rather than representing the message queue as an (infinite) sequence itself?

21:45 because the latter is what you would do in haskell, and then apply map/seq/whatever on the message queue

21:45 justin_smith: I wouldn't represent a queue as a sequence at all

21:45 solatis: right

21:46 justin_smith: solatis: usually when I need a queue I can just use an agent

21:46 or maybe a core.async channel

21:46 solatis: aha, that sounds interesting

21:46 justin_smith: agents are basically some decent default behaviors wrapped around a queue

21:46 solatis: right, is it in clojure core?

21:46 justin_smith: yes

21:46 solatis: awesome

21:46 WickedShell: justin_smith, right, java is the only path forward which seems ridiculous to write a java function that is 3 operations, its such a simple equation to be done

21:46 solatis: let me google that

21:46 justin_smith: ,(doc clojure.core/agent)

21:46 clojurebot: "([state & options]); Creates and returns an agent with an initial value of state and zero or more options (in any order): :meta metadata-map :validator validate-fn :error-handler handler-fn :error-mode mode-keyword If metadata-map is supplied, it will become the metadata on the agent. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on ...

21:50 solatis: justin_smith: thanks a lot, this gives me a clue about the "right" thing to model this

21:50 it's annoying that every language/ecosystem has its own best practices of doing things

21:50 but i really like how Clojure just gets "out of the way", i'm a lot more productive than with Haskell

21:51 justin_smith: solatis: it's true, but pervasive lazy evaluation on top of the jvm would be weird...

21:51 solatis: yeah, that's my experience too (though I have much less haskell experience - I'd make the same comparison with OCaml though)

21:52 solatis: yes i agree, it took me a few days before i got out of the Haskell-lazy-all-the-things kind of thinking.. "why is this function called, *i am not even using its return value!!!* ... oh wait)

21:53 but clojure has the main advantage of the java ecosystem

22:15 amalloy: i'd be interested to try out the way frege does laziness on the jvm. i think it basically requires you to define a shim haskelly type wrapper around any java type you want to interop with, and interop with that thing lives in something like IO

22:15 justin_smith: amalloy: fascinating

22:15 amalloy: so that pervasive laziness works out okay for everything else, and it is obvious that it doesn't apply to java interop

22:16 justin_smith: amalloy: I would totally have used frege by now if it played well with interfaces

22:16 amalloy: what does it do wrong with interfaces?

22:16 justin_smith: amalloy: you can only use them via interop with a java class that uses them

22:16 it doesn't allow definition or implementation directly in frege at all

22:17 that was a deal-breaker for me

22:17 amalloy: there's no reify?

22:17 solatis: amalloy: does that include lazy I/O ?

22:17 justin_smith: amalloy: exactly, no reify, not equivalent to our protocols, etc.

22:17 amalloy: well, i bet you a trillion dollars there's an equivalent to protocols, ie typeclasses

22:18 justin_smith: amalloy: I mean equivalent as in "creates a usable interface"

22:18 amalloy: or maybe not

22:18 solatis: what are the '->' and '->>' operators called in Clojure?

22:18 i need something to type into google

22:18 justin_smith: solatis: thread-first thread-last

22:19 solatis: in fact emacs adopted them with those names http://endlessparentheses.com/new-in-emacs-25-1-more-flow-control-macros.html?source=rss&utm_source=dlvr.it&utm_medium=facebook

22:19 solatis: ah nice

22:22 is there any way to rewrite this function to omit the function declaration? is there a macro for that?

22:22 (fn [msg] (-> msg

22:22 :body

22:22 read-string))

22:23 justin_smith: please don't do multi-line pastes, but anyway I do't think that's any better than #(read-string (:body %))

22:23 inf fact it is probably worse

22:23 solatis: sorry

22:24 i think you are correct

22:27 Kamuela: What does ! denote at the end of the function name?

22:27 solatis: impure

22:27 http://stackoverflow.com/questions/20606249/when-to-use-exclamation-mark-in-clojure-or-lisp

22:28 justin_smith: Kamuela: in clojure.core it denotes things that are not safe in transactions, in other code typically it means "has side effects or mutates something"

22:28 haha I corrected the accepted answer for that SO

22:28 lol

22:30 Kamuela: Thank you

22:31 solatis: it's always great to see yourself being referenced online

22:31 Kamuela: Damn what a totally different way to look at code

22:31 This function DOES something, flag as unsafe!

22:31 solatis: nah

22:31 it just means it has side effects

22:31 justin_smith: the only people who show up to my funeral will be irc denziens, people who read my SO answers, and twitter followers

22:31 Kamuela: I know and it makes sense

22:32 solatis: that's a big thing, because it means it might not be repeatable

22:32 Kamuela: Yeah. I'm just saying it's amazing how that has become what coders flag. Not handling memory or anything. Just that a function mutates state

22:33 What a leap forward in paradigm

22:33 justin_smith: Kamuela: handling memory is a subset of mutating state

22:33 solatis: Kamuela: i have written a blog post that might be relevant to you: http://www.leonmergen.com/code/2015/12/04/on-stateless-software-design-what-is-state.html

22:33 Kamuela: You'd better make sure you know what you're doing. State changed ahead

22:33 solatis: basically, the ! means, "beware, this function leaks state"

22:33 justin_smith: a more concrete way to look at it: unsafe in something that retries

22:34 TEttinger: choo choo all aboard the accident express! I swear it's safe

22:34 justin_smith: once you have the concept of restarts / retries, things have different consequences

22:34 Kamuela: I'm not at all saying its wrong or silly. I'm saying its just really interesting to think about code this way

22:34 It's like a forward shift in design

22:35 solatis: Kamuela: in Haskell, you cannot even get away with it _without_ explicitly "flagging" things... the compiler doesn't allow you to do that

22:35 and yes, it's an immense forward shift

22:35 it makes it a lot easier to reason about code

22:36 when you think about it, the state of OOP being so dominant is really painful

22:36 it does exactly the thing that FP tries to avoid: tightly coupling data with code

22:37 TEttinger: it is interesting yeah

22:37 solatis: to me it doesn't make sense to say "person.moveTo(foo)", which mutates an internal state you are completely unaware of

22:38 and don't even get me started about the code bloat for all the interfaces, useless abstractions, etc

22:38 /rant

22:38 Kamuela: True. Little black boxes that you have to pander to

22:38 TEttinger: we are seeing more of a shift toward immutability in mainstream OOP languages though. the CoreFX standard library of CoreCLR (open source .NET) includes a rather decent immutable collections lib, and it should be in the next .NET framework release judging by that

22:38 justin_smith: solatis: but don't you see we need 1000 different containers, and each has it's own special version of "look up the value"

22:40 TEttinger: justin_smith: bro, you don't even, nuh uh. I'm working with fastutil right now, which is 16MB as a no-source, no-doc jar, all code

22:40 there are separate jars for docs and code

22:40 there are... hundreds of specialized classes, mostly per primitive

22:41 solatis: justin_smith: aha, but then you forget about c++'s STL!

22:41 TEttinger: it's kinda amazing

22:41 solatis: don't you see that we can use templates for that!

22:42 TEttinger: hehe

22:42 solatis: and then have beautiful, elegant code like std::transform(foo.begin(), foo.end(), std::bind(&Class::bar, this, _1)) !

22:42 TEttinger: I was just about to link this, solatis; they generate java using the C preprocessor on special files that are between C and Java https://github.com/vigna/fastutil

22:42 the java it makes is totally fine though

22:42 the build process is tricky

22:43 solatis: :i

22:43 :o

22:43 justin_smith: bonus points if they call it CaCa

22:43 solatis: that sounds almost like bringing the C-era of bison, flex, lookup tables, etc to java

22:44 TEttinger: ohhhhh this looks like that's the problem

22:44 I think this needs actual non-windows symlinks

22:45 rhg135: Why would you do such a thing?!

22:49 TEttinger: rhg135: because writing the amount of type-specialized java it generates would drive men to the mountains of madness

22:50 igotsegv: TEttinger: I bet, but so can cpp macros

22:50 TEttinger: no template macros at least

22:51 Compiling 1878 source files...

22:52 rhg135: <10000 files, pfft

Logging service provided by n01se.net