2016-02-23
| 00:00 | solatis | (declare ^:dynamic *queue*) |
| 00:00 | solatis | |
| 00:00 | solatis | (defn fixture [f] |
| 00:00 | solatis | (binding [*queue* "foo"] |
| 00:00 | solatis | (f))) |
| 00:00 | solatis | |
| 00:00 | solatis | would anyone say that's idiomatic clojure? or is it an anti-pattern? |
| 00:01 | solatis | to me it feels like side effects/leaking... but i cannot find another way |
| 00:02 | tolstoy | You could also use an atom and pass it in as a param to your tests. |
| 00:02 | solatis | can i pass atoms as params in tests?! |
| 00:02 | solatis | https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L635 |
| 00:02 | tolstoy | Oh, well. Hm. |
| 00:03 | solatis | looks to me as if a test function is defined as a function that doesn't accept parameters.. |
| 00:03 | tolstoy | Or make a macro and don't bother with the fixture. |
| 00:03 | solatis | yes, but i'll be damned this is a big limitation to fixtures |
| 00:03 | tolstoy | I think a dynamic var might be fine for tests, as long as there's no threading going on. Kinda depends. |
| 00:03 | solatis | yes you are correct |
| 00: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. ;) |
| 00:05 | solatis | well i'm strong in functional programming (haskell especially), but new to clojure/lisp |
| 00:05 | solatis | so i'm not sure what's most idiomatic in clojure |
| 00:06 | solatis | but i _do_ notice when something feels a bit off :) |
| 00:06 | tolstoy | Why do you need to pass around something to all the tests? |
| 00:06 | solatis | in this case, an ad-hoc message queue that is created and destroyed in the fixture |
| 00:07 | solatis | but it could also be a database connection, whatever |
| 00:07 | solatis | i think what i really want to write is a (with-queue [name]) function |
| 00:07 | tolstoy | Seems like I've solved that before. Hm. |
| 00:07 | tolstoy | Yeah, a macro is good for that, too. |
| 00:08 | solatis | that's what i figured |
| 00:08 | solatis | it would allow me to create and drop the queue within a macro |
| 00:08 | solatis | or rather, expose the dynamic var |
| 00:08 | solatis | ehr |
| 00:08 | solatis | hide |
| 00:08 | solatis | whatever |
| 00:08 | tolstoy | Oh, wait. There's a version of fixture that runs just once for all the tests in the namespace. |
| 00:09 | solatis | that would mean that tests will not be isolated |
| 00:09 | solatis | because they share the same message queue |
| 00:09 | tolstoy | So, (reset! queue-atom (set-up ...)) (f)) then just reference queue-atom everywhere you want it. |
| 00:09 | solatis | oh! |
| 00:09 | solatis | that's interesting |
| 00:09 | solatis | let me look it up |
| 00:10 | tolstoy | (use-fixtures :once fix1 ..) vs (use-fixtures :each f1 f2). |
| 00:11 | tolstoy | You could also run a single (deftest ...) which just calls a bunch of functions with assers in them. |
| 00:11 | tolstoy | asserts. |
| 00:12 | tolstoy | 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. ;) |
| 00:13 | tolstoy | I think one test with 100 asserts means you're a slacker, but 100 tests with 1 assert each means you're super productive. |
| 00:13 | tolstoy | /join #bitter |
| 00:18 | tolstoy | I wonder if you could do a closure as well (let [queue (construct) (deftest a ...) (deftest b ...))). |
| 00:18 | tolstoy | Oh, no, nevermind. Bad idea. |
| 00:19 | solatis | tolstoy: well what i'm looking for is doing this the way it's "supposed to be done". |
| 00:19 | solatis | i mean, this really feels like it should be a solved problem |
| 00:19 | solatis | but dynamic vars feel a bit like magic |
| 00:20 | solatis | it's one of the major reasons i hate scala |
| 00:20 | tolstoy | I think the (use-fixtures :once ...) is the way it's solved. |
| 00:20 | solatis | i do that, and then i need to do the reset! thingie to pass around the queue ? |
| 00:21 | tolstoy | Yes. |
| 00: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 |
| 00:21 | tolstoy | (def queue (atom nil)) |
| 00:22 | tolstoy | (defn fixture [] (try (reset! queue (make)) (f) (finally (when @queue (.close @queue))))) |
| 00:22 | tolstoy | Something like that. |
| 00:22 | solatis | WAIT |
| 00:22 | solatis | i feel like an idiot |
| 00:22 | tolstoy | (deftest foo (is (= 42 (take @queue)))) |
| 00:22 | solatis | i could just as well just def this, right? |
| 00:22 | solatis | oh |
| 00:23 | solatis | that seems more elegant |
| 00: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. |
| 00:24 | solatis | yes |
| 00: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. |
| 00:26 | solatis | yes |
| 00:26 | solatis | that's the "best" solution |
| 00:26 | solatis | but too complicated for now |
| 00:30 | ode | I have a one vec of maps and another seperate map. |
| 00:30 | ode | 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? |
| 00:34 | tolstoy | Maybe use reduce? |
| 00:35 | tolstoy | 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. |
| 00:35 | tolstoy | Then just do (map #(xform % single-map) vector-of-maps). |
| 00:36 | tolstoy | Or loop/recur (so you can short-circuit once the match is applied), or reduce (so you can call reduced to short-circuit). |
| 00:39 | ode | thanks, I think I was overthinking it. I will use reduce. |
| 01: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 |
| 01:41 | Mendoza | Someone here does android programming? |
| 01:43 | lxsameer | Mendoza, using clojure? |
| 01:43 | Mendoza | Wanting to move from Common Lisp to Android |
| 01:43 | lxsameer | Mendoza, join #clojure-android |
| 01:44 | Mendoza | That's a good idea haha, thanks |
| 01:45 | tolstoy | amalloy: Ah, good call. I didn't realize that's what ode was doing. |
| 01:56 | sooheon | amalloy: This is off topic, but do you make videos on youtube for a certain roguelike game? |
| 01:56 | amalloy | i do. and a couple other games since i started |
| 01:57 | sooheon | wow that's pretty cool, I was persuing that channel the other day, didn't know you were into clojure as well :) |
| 01:57 | sooheon | was almost confused which irc channel I was in for a second |
| 01:57 | amalloy | you hang out in ##crawl, i guess? i don't, these days, but i am usually in ##crawl-dev |
| 01:58 | sooheon | yeah off and on |
| 02:01 | sooheon | I enjoy your stuff. It'd be cool if you had some clojure programming vids on there as well haha |
| 02:06 | kolt | kolt - Im using 4clojure and have no idea how to solve the third problem, any help? |
| 02:17 | sooheon | link? |
| 02:18 | sooheon | kolt: Do you mean https://www.4clojure.com/problem/3? |
| 02:18 | kolt | I solved it, they are hard and they don't give any hints :( |
| 06:33 | dazlow | how do I compile clojure code in realtime? Like, from raw string? |
| 06:34 | zipper | dazlow: Clojure is automatically compiled. Everything you run in clojure is bytecode. |
| 06:35 | zipper | Uh what do you have in clojure to support complex types? Like the way haskell has typeclasses and OOP has objects? |
| 06: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 |
| 06:35 | zipper | dazlow: Is what the user types valid clojure? |
| 06:36 | zipper | Have you read about clojure |
| 06:36 | zipper | incomplete |
| 06:36 | zipper | clojure's eval model? |
| 06:37 | zipper | When everything is a tree? You can make your stuff into a list (tree) and call `eval` on it? |
| 06:39 | dazlow | zipper: oh, ok, I'll try that |
| 06:40 | zipper | dazlow: Have time to read? I can refer you to something. |
| 06:40 | zipper | dazlow: Does the user enter valid clojure? |
| 07:57 | TimMc | dazlow: I'm going to give you the footgun necessary for this: (eval (read-string ...)) |
| 07:58 | TimMc | 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. |
| 08:00 | ridcully | you can shoot off any body part with that line ;) |
| 08:01 | MJB47_ | what about your second trigger finger? |
| 08:57 | ddpigui | Hello |
| 08:57 | ddpigui | I am creating a project anyone good at art |
| 08:58 | ddpigui | recycle |
| 08:58 | ddpigui | CAN SOMEONE HELP ME |
| 08:59 | ridcully | ddpigui: this channel is about the programming language clojure |
| 09:03 | ddpigui | ik |
| 09:03 | ddpigui | I am using clojure in my project |
| 09:04 | MJB47 | yo ive used clojure before, is anyone here good at business planning? |
| 09:04 | ddpigui | Anyone Good at art |
| 09:05 | ridcully | ddpigui: if you are looking to hire clojure developers here, maybe you could structure your request better? what is "art"? |
| 09:05 | ridcully | and what is "good"? |
| 09:06 | ddpigui | clear |
| 09:06 | ddpigui | So is anyone good at art! |
| 09:06 | ddpigui | So far this is the logo PS it looks bad https://github.com/alwaysontop617/PIgui/blob/master/logo.png |
| 09:13 | ddpigui | So far this is the logo PS it looks bad https://github.com/alwaysontop617/PIgui/blob/master/logo.png |
| 09:14 | TimMc | Agreed, but you're asking in the wrong place. |
| 09:15 | Empperi | even though clojure is kind of art I agree with TimMc :) |
| 09: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." |
| 09:16 | ddpigui | Kk anyone who wants to join the pigui project join #gopigui |
| 09:40 | TimMc | ,(with-redefs [dec inc, inc dec] (inc 5)) |
| 09:40 | clojurebot | 6 |
| 09:40 | TimMc | ,(with-redefs [inc dec, dec inc] (inc 5)) |
| 09:40 | clojurebot | 6 |
| 09:43 | hiredman | is that a question? |
| 09:44 | gfredericks | ,(with-redefs [dec inc, inc dec] (apply inc [5])) |
| 09:44 | clojurebot | 4 |
| 09:45 | gfredericks | ,(with-redefs [inc dec, dec inc] (apply inc [5])) |
| 09:45 | clojurebot | 4 |
| 09:45 | gfredericks | I guess that first one is a bit surprising? |
| 09:45 | gfredericks | ,(with-redefs [dec inc] (with-redefs [inc dec] (apply inc [5]))) |
| 09:45 | clojurebot | 6 |
| 09:45 | gfredericks | ,(doc with-redefs) |
| 09: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... |
| 09:46 | gfredericks | "in parallel" ⇑ |
| 09: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 |
| 09:57 | TimMc | there's that too |
| 09:57 | TimMc | 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 | tangled_z | 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 | hiredman | 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 | TimMc | 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 | tangled_z | 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 | tangled_z | Ok, yeah, the command works in the groovy shell. |
| 10:19 | tangled_z | Thanks! |
| 10:33 | sdegutis | I'm back. |
| 10:45 | sdegutis | 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 | sdegutis | tangled_z: also you have a typo in the keyword |
| 11:04 | hiredman | tangled_z: there is a #datomic channel |
| 11:06 | hiredman | 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 | max3 | 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 | tangled_z | 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 | gfredericks | which is normally only a problem for properties with more complex expectations |
| 12:17 | gfredericks | 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 | gfredericks | 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 | gfredericks | you could have a protocol that includes the above behavior, but allows libs/users to make new implementations |
| 12:20 | gfredericks | 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 | gfredericks | TimMc: probably depends on your critera for "well" :) |
| 12:21 | gfredericks | 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 | gfredericks | 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 | gfredericks | 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 | xitrium | 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 | hiredman | 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 | hiredman | 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 | hiredman | 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 | TimMc | 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 | hiredman | and, actually, all kinds of other weird errors |
| 12:48 | hiredman | 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 | hiredman | 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 | hiredman | 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 | hiredman | my old boss actually wrote a post to the clojure mailing list begging people to stop aot compiling libraries back in 2009 |
| 12:54 | hiredman | https://groups.google.com/forum/#!topic/clojure/Bs70_PUj-TY |
| 12:56 | hiredman | so all that above is what you get from clojure's compiler |
| 12:57 | hiredman | 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 | hiredman | 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:02 | hiredman | export LEIN_I_KNOW_BUT_I_HAVE_REVIEWED_THE_DOCS_AND_LOOKED_AT_JIRA_ISSUES_AND_I_STILL_NEED_THIS |
| 13:03 | hiredman | TimMc: you know, the clojure repl has a -m option these days, even without lein-otf |
| 13:03 | hiredman | java -jar your-uber-jar clojure.main -m your.main |
| 13:03 | gfredericks | LEIN_USE_BUNDLER_INSTEAD_OF_LEIN=1 |
| 13:06 | hiredman | export LEIN_NO_SERIOUSLY_THERE_IS_THIS_WEIRD_CLASSLOADER_ISSUE_IN_JBOSS_I_NEED_TO_DEAL_WTIH=1 |
| 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 | justin_smith | 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 | sdegutis | 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 | rcassidy | ,(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 | TimMc | or do the changes, then delete itself from the plugins list |
| 15:03 | sdegutis | rcassidy: I had similar solution |
| 15:03 | sdegutis | ,(->> "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 | rhg135 | 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 | CStorm | (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 | justin_smith | 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: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 | TimMc | 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 | sdegutis | like, into source? |
| 17:07 | sdegutis | controlv ersion? |
| 17:07 | sdegutis | (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 | sdegutis | so i commit to it probably twice a year |
| 17:10 | sdegutis | 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 | TimMc | Some files are versioned in each repo, or you have branches? |
| 17:25 | TimMc | 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 | TimMc | maybe if I signed the commits... |
| 17:26 | gfredericks | https://github.com/gfredericks/dotfiles/blob/master/bootstrap |
| 17:26 | gfredericks | we all have our own personal paranoia levels |
| 17:27 | gfredericks | TimMc: actually a better explanation is probably the README of that repo |
| 17:38 | gfredericks | 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 | gfredericks | also, I think I may have run into an unsolveable problem |
| 19:12 | gfredericks | currently test.check's clojure.test integration consists of a macro (defspec) that expands to code that calls a function (assert-check) |
| 19:12 | gfredericks | 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 | gfredericks | 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 | gfredericks | the clojure version works just fine but cljs fails saying "java" is not defined |
| 19:14 | gfredericks | my theory was that this was somehow tied to clojure.test and cljs.test having different namespace names |
| 19:14 | gfredericks | 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 | hiredman | 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 | WickedShell | 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 | WickedShell | (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 | solatis | 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 | solatis | 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 | justin_smith | 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 | solatis | it's annoying that every language/ecosystem has its own best practices of doing things |
| 21:50 | solatis | 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 | justin_smith | 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 | solatis | 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 | justin_smith | it doesn't allow definition or implementation directly in frege at all |
| 22:17 | justin_smith | 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 | solatis | i need something to type into google |
| 22:18 | justin_smith | solatis: thread-first thread-last |
| 22:19 | justin_smith | 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 | solatis | is there any way to rewrite this function to omit the function declaration? is there a macro for that? |
| 22:22 | solatis | (fn [msg] (-> msg |
| 22:22 | solatis | :body |
| 22:22 | solatis | 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 | justin_smith | inf fact it is probably worse |
| 22:23 | solatis | sorry |
| 22:24 | solatis | i think you are correct |
| 22:27 | Kamuela | What does ! denote at the end of the function name? |
| 22:27 | solatis | impure |
| 22:27 | solatis | 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 | justin_smith | haha I corrected the accepted answer for that SO |
| 22:28 | justin_smith | 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 | Kamuela | This function DOES something, flag as unsafe! |
| 22:31 | solatis | nah |
| 22:31 | solatis | 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 | Kamuela | 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 | Kamuela | 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 | solatis | and yes, it's an immense forward shift |
| 22:35 | solatis | it makes it a lot easier to reason about code |
| 22:36 | solatis | when you think about it, the state of OOP being so dominant is really painful |
| 22:36 | solatis | 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 | solatis | and don't even get me started about the code bloat for all the interfaces, useless abstractions, etc |
| 22:38 | solatis | /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 | TEttinger | there are separate jars for docs and code |
| 22:40 | TEttinger | 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 | TEttinger | the java it makes is totally fine though |
| 22:42 | TEttinger | the build process is tricky |
| 22:43 | solatis | :i |
| 22:43 | solatis | :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 | TEttinger | 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 | TEttinger | Compiling 1878 source files... |
| 22:52 | rhg135 | <10000 files, pfft |