#clojure log - Oct 24 2013

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

0:05 akurilin: Quick question. What's the recommended simple library these days for scheduling recurring tasks in one's Ring app? Looks like at-at has some traction on Github.

0:12 ToBeReplaced: akurilin: i use ScheduledThreadPoolExecutor directly

0:13 muhoo: akurilin: there's at-at, and there's a new library raynes did too that's more like a cron

0:14 akurilin: muhoo, I was looking at chime as well, seems super minimalistic and uses clj-time pretty heavily

0:14 ToBeReplaced, that's fair, looks like a lot of these libs are just wrapping it

0:15 muhoo: akurilin: https://github.com/Raynes/moments

0:16 akurilin: muhoo, that's cool! Wasn't there on clojure toolbox

0:20 Hm probably more inclined to go with Raynes' stuff for now, let me try that.

0:25 arrdem: I feel like one could/should build a crontab like dsl atop that...

0:25 muhoo: that'd be * * * * * funny

0:38 marcopolo2: anyone know is I can do anything asynchronous inside pedestal app transactions?

0:54 akurilin: Say I'm doing some batch processing on my data set once a day and maybe I want to send out a few thousand analytics events or maybe Mandrill API calls as soon as I'm done fetching and processing this data.

0:55 It's my understanding that just looping through a few thousand entries and sending out HTTP requests for each as fast as you can will very possibly result in many failures on the way

0:55 either because of the network, or maybe the API starts throttling etc.

0:55 I think I read somewhere where for email batch spamming people were using queues and just slowly plowing through them

0:56 making sure the APIs would respond positively

0:56 bja: aha, my app's configuration is finally sane

0:57 I now have an app/config.clj where I define all of my config variables including defaults and then it defers to environ to pull out of env variables/properties/etc

0:57 not littering my app with (get env :random-setting $DEFAULT) is a good feeling

0:58 just define things like (setting "name" default)

0:58 and then config/name is a symbol that be referenced throughout

1:14 bitemyapp: akurilin: clj-http retries failed requests.

1:14 akurilin: you can use things like robert.bruce to customize retry logic as well.

1:39 ToBeReplaced: akurilin: this may sound like flamebait, but i'd avoid moments and chronicle unless your goal is "get done now"

1:39 akurilin: they use the word "simple" when i think they actually mean "easy"... they are hiding away all of the power of STPE and joda-time in favor of the bare-minimum use case

1:41 if that's sufficient for you, go ahead, but i had a great time really grokking joda and STPE, and i wouldn't trade the things i've learned in for one of those tools

1:57 bitemyapp: akurilin: I'd tend to agree with ToBeReplaced.

1:57 moments is pretty cool though :)

2:37 akurilin: ToBeReplaced, bitemyapp , thanks for clarifying, sorry for late response.

2:38 bitemyapp, I guess my question is about whether there are physical limitations to spamming an online HTTP api that would end up dropping a majority of my calls.

2:38 bitemyapp, so say I were to make a hundred futures to make clj-http calls

2:38 there's probably some sort of physical port limit in place

2:39 or the pipe would get clogged

2:39 or something else

2:39 I'm just not really fully conscious of these limitations right now

2:40 creese: Are there any good libraries for marshalling API requests and responses?

2:41 akurilin: bitemyapp, but yeah it's really cool that clj-http takes care of retries. Saves me the time to implement a queue, and I can even add some sort of backoff strategy if I wanted to

2:46 bitemyapp: akurilin: do not spam futures.

2:46 akurilin: do not spam external APIs.

2:46 tsdh: Hi. When hacking clojure, is there a way to only compile and execute a specific test namespace? Always compiling everything and running all tests with "mvn package" takes ages here.

2:51 jared314: tsdh: are you using lein or straight mvn?

2:52 oneness: tsdh: you should be able to run only one namespace by using the -D option just like in java. But this assumption needs to be verified.

2:52 ambrosebs: tsdh: hacking clojure.core?

2:52 tsdh: jared314: It's clojure itself, so maven.

2:52 ambrosebs: yep

2:52 oneness: Ah, mvn -Dtest=testclass google says. I'll try that.

2:53 ambrosebs: tsdh: I don't know, I've have that problem myself.

2:54 tsdh: Hm, "mvn test" seems to compile everything, too.

2:57 andyfingerhut: tsdh: Have you looked under "How To Run All Clojure Tests" on this wiki page? http://dev.clojure.org/display/community/Developing+Patches

2:57 tsdh: andyfingerhut: Not yet. Thanks.

2:57 andyfingerhut: tsdh: Or rather, just below that under "Run An Individual Test"

2:58 tsdh: andyfingerhut: Ah, that's it. Thanks!

2:59 andyfingerhut: tsdh: No problem. I don't have it memorized how to do it, but I remember where to look it up :-)

3:03 akurilin: bitemyapp, I understand, still doesn't really help me gauge what is considered "spam"

3:03 obviously each API owner has its own policy

3:04 anyways, I'll see if I can dig up some info on this around

3:05 tsdh: If I have an interface method with 3 parameters, when extending that in a deftype the impl has 4 params (the first being "this"), right?

3:07 akurilin: bbl

3:08 bitemyapp: akurilin: pretty easy to dispatch too many futures and run out of threads if you're not careful.

3:08 the agents thread pool is 1:1 OS threads.

3:09 you can't fire those off willy-nilly against an arbitrarily large coll.

3:14 andyfingerhut: /whois GOSUB

3:14 sorry. Must have had whitespace there.

3:23 tsdh: Hm, I have a testcase that uses (is (thrown? SomeEx (macroexpand '(some-form)))). When I eval the macroexpand in a REPL, I can see the exception printed, but still the macroexpansion returns a form. It seems the exception is somehow printed but caught...

3:24 Concretely, (some-form) is a (deftype ...) form that triggers a CompilerException.

3:25 The same applies with (reify ...). (defrecord ...) on the other hand triggeres the same exception, and there it's passed through and my test succeeds.

3:33 andyfingerhut: tsdh: Can you share the (deftype ...) form that triggers a CompilerException that you are trying?

3:41 tsdh: andyfingerhut: Sure, but it doesn't trigger the CE without my other patch. ;-)

3:41 andyfingerhut: Check CLJ-888 and the attached patch.

3:41 andyfingerhut: The tests that fail due to swallowed CE are commented out with a big FIXME.

3:42 andyfingerhut: tsdh: Got it. I may take a look here, but don't know what is going on with the swallowed exceptions yet.

3:45 iSocket: &"I worship his Shadow"

3:45 lazybot: ⇒ "I worship his Shadow"

3:47 johann: hey guys

3:47 iSocket: johann,

3:47 I Worship His Shadow

3:48 johann: has anyone had issue with heroku deployment and procfiles?

3:49 my app is crashing when i deploy it and heroku hasn't been recognizing my procfile so i am hoping that would fix it

3:50 iSocket--I Hope He Reciprocates Your Shadow Worship

3:59 andyfingerhut: tsdh: I don't know what is going wrong with those tests, but i tried 'eval' in place of 'macroexpand' on the first commented out one and it passed.

4:00 tsdh: Any particular reason you are using macroexpand there?

4:00 tsdh: andyfingerhut: Well, it should suffice to trigger the excetion, I've thought. But eval is as fine. I'll try the others. Thanks!

4:02 andyfingerhut: tsdh: I'm not sure if defprotocol has side effects you want to avoid eval for, but there is also a test helper function eval-in-ns that might be useful.

4:02 tsdh: Sorry, wrong name. It should be eval-in-temp-ns

4:04 tsdh: andyfingerhut: The worst side effect would be that some new type was defined in the test namespace, so I guess that's no issue.

4:04 andyfingerhut: Indeed, now all tests pass!

4:06 andyfingerhut: Great, I've updated the patch of CLJ-888.

4:07 andyfingerhut: tsdh: My guess is that macroexpand1 is doing something strange with the exception, but I don't know what. Like you, I see the exception output in the REPL, and it binds *e to it, but still the (is (thrown? ...)) fails. Weird.

4:08 * ucb waves

4:15 andyfingerhut: tsdh: A guess: parse-opts+specs calls your new throw-on-varargs lazily, so it isn't being forced to evaluate until later than you would expect.

4:15 tsdh: andyfingerhut: Ah, that would make sense. So (doall (macroexpand ...)) should also work.

4:16 andyfingerhut: tsdh: Makes my head swim to try to imagine what is going on there.

4:17 tsdh: andyfingerhut: Indeed, (doall (macroexpand ...)) works. So it's really caused by lazyness.

4:18 andyfingerhut: tsdh: Crazy stuff

4:19 tsdh: andyfingerhut: Totally. :-)

4:20 andyfingerhut: tsdh: eval is used all over in the Clojure tests, so that seems preferable to me over macroexpand anyway, for this kind of test.

4:22 tsdh: andyfingerhut: I have no preference.

4:39 borkdude: why does this get indented like it is? https://www.refheap.com/20129

4:39 I mean, why don't the maps have an indenting of 2?

4:39 clojure-mode 2.1.0

4:39 ddellacosta: do I need to escape this somehow if I'm comparing (with = )? org.docx4j.wml.R$Tab

4:40 borkdude: no idea, but presumably it's because you haven't close the s-expression?

4:40 *closed

4:41 although, I know different s-expressions tab differently.

4:41 borkdude: ddellacosta what do you mean, I didn't close it?

4:42 ddellacosta: borkdude: no, not saying you didn't close it, just that at the point the map is written the s-expression is not closed. But anyways, that's wrong since these things get applied differently for different functions, so never mind...haha.

4:42 sorry I'm not helpful on this one.

4:50 borkdude: this is kind of not so nice, because I don't want to fix indentation by hand

4:53 llasram: borkdude: I'm pretty sure that's standard indentation

4:57 borkdude: hmm ok

5:00 clgv: borkdude: talking about CCW?

5:00 borkdude: clgv emacs / clojure-mode

5:01 clgv: ah ok, just guessed because of the recent release ;)

5:02 borkdude: then at least I'm not crazy. I think this makes sense https://www.refheap.com/20130

5:05 clgv: borkdude: afaik the second is standard

5:05 borkdude: clgv seen from the code is data perspective it wouldn't make sense right, because why would you indent all but the non first elements of a list differently

5:07 clgv: borkdude: because in a list the first element is special as opposed to a vector where all have equal importance

8:00 does type hinting not imply interfaces and superclasses automatically?

8:03 llasram: clgv: It does

8:03 As in, the type implies all those things, and so does the type hint

8:03 clgv: weird in a separate function it works as expected but not in a deftype...

8:04 llasram: On deftype field or as part of a method signature?

8:04 clgv: on a deftype field

8:05 llasram: Hmm, odd. That should work fine.

8:05 clgv: it works for methods of the class, but not the ones of the super class

8:05 I manually hinted the subclass which did it but that is really strange

8:06 oh wait. I think I found the odd piece^^

8:06 you'll always get punished if you write (protocol-method [this] ...) and you really do not need `this` instead I need the field ;)

8:08 should have used the checking macro for the type info

9:44 FragDoctor: Hey

10:36 ohcibi: hi, i have a task in clojure that wants me to generate all palindrome five-tupels like [0 1 2 1 0] [0 1 3 1 0] and so forth.. I have a solution that involves three nested map&range calls which looks kinda ugly to me.. I'm wondering if there is an easy way to generate all 5-tupels with numbers from 0-9 or a better way in general... any ideas?

10:37 justin_smith: what about generating all the three digit numbers first, and then converting each one into a five digit palindrome?

10:38 no need for nested anything

10:39 sszzqq: use lein test clojure code is slow. If have any more rapid way?

10:40 tbaldridge: sszzqq: tests are just functions, you can run them from the repl

10:40 do (require '[my.namespace :reload true])) to reload namespaces after recompilation

10:40 justin_smith: you can require the namespace with the tests in it from a repl, then (clojure.test/run-tests)

10:41 tbaldridge: *reload namespaces after modification

10:41 sszzqq: I want save the edit the code in editor, repl have not syntax highlight..

10:41 justin_smith: sszzqq: you can save in an editor, then (require '[] :reload)

10:42 no need to do any coding directly in the repl

10:43 sszzqq: justin_smith: what file-name should be use, then in repl: (require '[] :reload) couold load it and test it?

10:44 justin_smith: (require '[the.namespace.that.changed] :reload)

10:44 I don't know the name of the namespace, you need to fill that in

10:44 after editing, of course

10:45 sszzqq: justin_smith: thanks, i see it ..

10:46 justin_smith: ohcibi:

10:47 ,(take 5 (for [a (range 10) b (range 10) c (range 10)] [a b c b a]))

10:47 clojurebot: ([0 0 0 0 0] [0 0 1 0 0] [0 0 2 0 0] [0 0 3 0 0] [0 0 4 0 0])

10:47 justin_smith: ,(take 5 (drop 400 (for [a (range 10) b (range 10) c (range 10)] [a b c b a])))

10:47 clojurebot: ([4 0 0 0 4] [4 0 1 0 4] [4 0 2 0 4] [4 0 3 0 4] [4 0 4 0 4])

10:47 logicprog: are there any plans to have cljs target asm.js ? that would be insane

10:48 justin_smith: logicprog: I don't know asm.js - is it really that likely to outperform the jvm?

10:48 dnolen: logicprog: no, we'll likely benefit from asm.js anyway

10:49 logicprog: I don't see think any browser except FF will actually support the AOT part of it.

10:49 logicprog: dnolen how cam we benefit if we domt target it?

10:50 dnolen: logicprog: because engines are optimizing around asm.js benchmarks now

10:50 logicprog: so if you write asm.js style code it will be fast

10:51 logicprog: but as far as compiling CLJS to asm.js itself, I don't really see the benefit, at least yet.

10:51 logicprog: how does this help me if cljs does not emit asm.js?

10:52 ohcibi: justin_smith: thanks...

10:52 dnolen: logicprog: there's an incredible amount of bit twiddling and integer arithmetic in CLJS data structures, you'll benefit

10:53 justin_smith: ohcibi: now I notice you were only using 3 nestings, so really all I added was the for semantics to replace the nested maps

10:54 xsyn: just so I understand. Does clojurescript compile to js to then compile on the v8?

10:54 jtoy: how can I debug why when I run " lein trampoline run -m pusher.campaigns/run'" my program starts up and then quits immediately, but when I run "lein repl; (use 'pusher.campaingns);(run)" works

10:54 dnolen: logicprog: the other place that asm.js helps is memory usage, but not really of any use to us - we need GC

10:54 justin_smith: ohcibi: but yeah, that is what for is good for, replacing nested mappings

10:54 ohcibi: justin_smith: I assume what I did is just what most functional newbies would do 8-))

10:55 justin_smith: this in combination with :when just blew my mind 8-)) (i forgot to add that a b c must (< a b c), but no problem with :when 8-)) thanks again

10:55 justin_smith: ohcibi: even coming from scheme and ocaml, I used nested map before I realized how much simpler for was

10:55 jtoy: im sure this is a simple fix, but I cant get it to work

10:55 justin_smith: ohcibi: no prob, glad I could help

10:56 jtoy: are you starting some thread or async action that somehow isn't being waited for? I thought the default was to wait for agents before exiting though

10:57 jtoy: justin_smith: no, I dont think i have any

10:59 justin_smith: jtoy: you could attach jdb to the dt-socket, if there is a way to pause and wait for the debugger inside your code

11:00 I have had luck when really weird bugs happen, connecting with jdb and seeing exactly what each thread was doing - I don't know if there is a way to "break" in the jvm and wait for a debugger attach off the top of my head, but it should be worth a google

11:02 jtoy: justin_smith: is there a clojrue way to do that? I have never programmed any java

11:02 justin_smith: another option: modify your code so that it first reads a line from stdin, then does the rest. then connect with jdb before providing that line

11:02 jdb is language agnostic

11:03 it provides an interface to the jvm, like gdb does to raw bytes

11:03 so you just need to be able to translate from the jvm names of yoru functions / bindings to their actual names

11:05 so (fn -main [& args] (read-line) ...) - run it, before entering a line of input, connect to the dt-thread with jdb or jvisualvm

11:06 jtoy: justin_smith: ok thanks, im goign to test it

11:06 justin_smith: jvisualvm may not be able to set breakpoints or step through code, but it gives a graphic overview of threads etc.

11:07 on further thought, it may be easier to turn on all profiling in jvisualvm while the app is waiting for input, then provide the input then analyze the profiling data of what happened

11:07 jvisualvm comes with java

11:21 edw: Anyone else get "pp does not exist" exceptions when firing up nREPL in Emacs? <https://gist.github.com/edw/7138535>

11:22 (Using most recent CIDER, but it's been going on sporadically for the last month or so.)

11:22 ndp: Yeah, I do occasionally

11:22 Never made sense to me, I don't require pp in any Lein profiles

11:23 edw: ndp: Yeah, it's occasional for me too; I've never been able to figure out under what circumstances it does (or doesn't) happen.

11:24 mdrogalis: Cider.. Huh, is nrepl not a thing anymore?

11:24 justin_smith: I think cider extends nrepl, trying to be an all around "emacs ide" thing

11:25 rkneufeld: nrepl.el has become "cider"

11:25 justin_smith: oh!

11:25 mdrogalis: Well, I'm late to the party.

11:25 llasram: I think the name is mostly that people were confusing nREPL and nrepl.el

11:25 so nrepl.el -> cider

11:25 mdrogalis: llasram: I see, thanks. :)

11:26 edw: In general, I think it's a good idea to give the thing that talks to nREPL qua protocol a different name from its implementation. And we want something that tastes better than SLIME.

11:26 llasram: nice

11:26 mdrogalis: edw: Kind of the same problem with the Java platform and Java language having the same name.

11:26 justin_smith: slime always made me think of nethack, eating slime molds

11:27 also, slime is what first brought me to emacs over a decade ago, so it was kind of sad moving away from slime with clojure

11:27 edw: mdrogalis: This "the thing is broader than its single, definitive implementation" idea is relatively new to many languages.

11:28 justin_smith: edw: you would think lisps would know better :)

11:28 edw: justin_smith: Using SLIME to talk to Scheme48 felt like being in an abusive relationship; I'm happy to have moved on.

11:28 justin_smith: Implementations for everyone!

11:28 justin_smith: heh, it worked nicely with cmucl / sbcl

11:29 and it was not even comparable to using vi (at the time vim could not even have a process inside a buffer - I had to switch to nvi for that, but nvi did it so badly I had to swollow the lump and learn emacs)

11:30 in the future, every language will be like linux, with thousands of cosmetically different "distros"

11:30 xsyn: gawd

11:30 that sounds horrific

11:31 justin_smith: try, the new snowjure, just like clojure, but let is renamed to ☃

11:31 and defn is renamed to ❄

11:32 pjstadig: justin_smith: i'm in!

11:33 justin_smith: the sweet thing, is you can bootstrap it from an existing clojure in two lines of code :)

11:33 well maybe more now that I think about it...

11:34 TimMc: (defmacro ☃ [& stuff] `(let ~@stuff))

11:35 justin_smith: heh

11:35 well, the trick is putting it in clojure.core so it gets pulled in by the default refer-clojure

11:35 pjstadig: justin_smith: https://github.com/sybilant/sybilant/blob/old-master5/sybilant/test/munging.syb#L4

11:36 justin_smith: so I think you need more than two lines

11:36 pjstadig: nice

11:37 pjstadig: sybilant looks interesting, how mature is it?

11:37 pjstadig: justin_smith: not really, still very much a work in progress

11:37 justin_smith: good enough to be a less painful way to play with x86 assembly?

11:37 pjstadig: a long term project

11:37 justin_smith: no such thing

11:38 justin_smith: heh

11:38 you mean x86 assembly is the least painful thing of all things? I am dubious

11:39 pjstadig: i want to create a language that can bootstrap itself without having to use another lower level language, one someone *cough* could write an OS in, one you could drop in assembly blocks for performance or whatever

11:39 i'm the most unlikely person to create such a language

11:40 justin_smith: heh

11:40 pjstadig: but typed assembly is interesting, and sybilant will have it

11:40 justin_smith: even just a good enough binding of assembler to a lispy syntax is interesting to me

11:40 pjstadig: something like this https://github.com/sybilant/sybilant/blob/old-master5/sybilant/test/types.syb

11:40 justin_smith: I remember reading about c-- ages ago, and found that very fascinating

11:40 c-- grew into msft clr

11:41 cmajor7: what would be a better collector for a netty based app that accepts many connection on a multicore server to strive for a consistent response times? -XX:+UseConcMarkSweepGC or ‑XX:+UseParallelOldGC (maybe G1, but it is Java 6 not the latest build…)?

11:45 sluukkonen: start with paralleloldgc

11:45 hyPiRion: cmajor7: hard to tell in general. The best is to try them out, really.

11:45 sluukkonen: explore other options if you experience full GC's with it

11:46 ystael: I'm having a problem with ztellman/byte-streams where it does not seem to load any of the conversions

11:47 After I (require '[byte-streams :as bs]) in a lein repl, (bs/possible-conversions String) evaluates to nil

11:47 Anyone know a possible cause for this issue?

11:47 justin_smith: if ram is not an issue, nginx in front load balancing multiple instances (even on the same host, each using its own port) will help keep response times low

11:47 cmajor7: hyPiRion, sluukkonen: leaning towards -XX:+UseParallelOldGC, but contemplating, since -XX:+UseConcMarkSweepGC might provide a better response time, but will eat more CPU/RAM and will have fragmentation… hence might bring the overall throughput down..

11:47 justin_smith: unless the app is stateful

11:48 ngw: how do you manage configuration in a compojure web app?

11:49 jtoy: justin_smith: I fied it by changing for to doseq, why would that fix it?

11:49 justin_smith: ngw: at my shop (doing brochureware web sites) we have resources/config/<environment>.clj

11:49 hyPiRion: cmajor7: What do you value the most? Obviously stop-the-world will make response times more varying, but will give a better average

11:49 justin_smith: jtoy: for is lazy, nothing was consuming it so it realized nothing

11:49 on a repl it gets consumed by the print part of the loop

11:50 ngw: justin_smith: and you use normal clojure data types?

11:50 justin_smith: ngw: yeah, it is a standard clojure edn file

11:50 we do a deep merge with a "defaults" provided by one of our libs

11:50 sluukkonen: cmajor7: cms, g1 et al. have more minor gc overhead than paralleloldgc, so if parallelold can keep up with the load (i.e. you don't experience full gcs with it), it's generally the best choice

11:51 you'll likely achieve the best throughput and latency in that case

11:51 justin_smith: ngw: also, we have been experimenting with also having a secret.clj.aes128 so we don't have the credentials for our config naked in the repo

11:51 for obvious reasons

11:52 otherwise github may just be our weakest security link

11:53 logic_prog: what is a godo resource on "recursion = low level, use higher level abstractions"

11:54 cmajor7: sluukkonen: yep, that is my thinking as well. thank you.

11:55 xuser: is it usual to see the Java collections framework being used in Clojure?

11:58 justin_smith: xuser: only when you care more about performance than sanity

11:58 less glibly, sometimes it is nice to have something like a dag lib that is mature and featureful in java

11:59 https://github.com/aysylu/loom for example, has good reason to use java data types

12:02 silasdavis: better way to remove first char in string than: (comp (partial apply str) rest) ?

12:02 hyPiRion: ,(subs "foo" 1)

12:02 clojurebot: "oo"

12:02 justin_smith: yeah, that is probably best

12:02 forcing strings to chars kills performance

12:03 silasdavis: thanks for that

12:05 justin_smith: logicprog: http://blog.fogus.me/2011/03/09/recursion-is-a-low-level-operation/

12:07 logicprog: hmm - actually that asserts the case, but doesn't really give full exposition :(

12:07 silasdavis: is there a nicer way to check if a string is a URI other than trying to create one and catching the execption?

12:08 justin_smith: silasdavis: for URL http://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/UrlValidator.html

12:09 I dunno about more general URI

12:14 silasdavis:

12:14 ,(do (time (dotimes [i 10000] (try (assert false) (catch AssertionError e nil)))) (time (dotimes [i 10000] (if false true))))

12:14 clojurebot: justin_smith: No entiendo

12:14 justin_smith: err

12:15 anyway, if you run that code, you will see how much slower catching an exception is than checking a boolean

12:15 if the performance matters at all

12:15 xuser: justin_smith: thanks

12:18 silasdavis: that and that it's ugly

12:19 justin_smith: yeah, there's that too

12:19 one of those problems you can fix with a macro, the other not so much :)

12:19 silasdavis: if I registered a custom URLStreamHandler

12:19 would clojure's slurp use it to read the URL

12:19 ?

12:20 thinking about doing this for s3

12:20 not clear to me from the source of slurp whether it would work

12:20 suspect not

12:20 llasram: It would

12:20 It would work

12:21 silasdavis: ah cool

12:22 I'll take that approach then, how does make-reader do that?

12:24 llasram: It just opens a reader on the result of calling the URL's openStream() method

12:25 xuser: justin_smith: I'll skip this http://docs.oracle.com/javase/tutorial/collections/index.html for now then to finally start getting into Clojure ;)

12:26 justin_smith: silasdavis: I have a fork of weavejester's s3 lib, specifically so I could upload streams

12:26 specifically I want to resize an image that comes from a remote host, and store the resize on s3, and not store it on disk in between - so I don't know the size of the output, and don't have a file to read from

12:27 if generalized stream upload to s3 helps you I can link the change, it is a small patch

12:27 silasdavis: justin_smith: did you write your own URLStreamHandler?

12:29 justin_smith: no, I just grabbed the outputstream from the java.net.URL, then feed that into an image resize (bufferedimage), then turn that buffer into a stream and feed that to the s3 upload

12:30 but most of that I did in my own resizer lib, the only change that required in the clj-aws-s3 lib was a multi-part upload that does not come from disk (multi part because that is the only kind of upload of indeterminate size s3 is ok with)

12:30 clj-aws-s3 took for granted that a multi-part upload would come from disk

12:31 I have no idea if any of this is relevant for what you need from your URLStreamHandler though

12:31 what are you trying to do?

12:31 staafl: any way to splat a macro?

12:31 (apply and '(true true)) gives me an error

12:31 llasram: staafl: none that are what you likely actually want

12:32 staafl: llasram, what's a sane solution?

12:32 llasram: staafl: What are you trying to do?

12:32 staafl: llasram, aggregate boolean values

12:32 llasram: Well, you know, at a higher semantic level :-)

12:32 Ok,

12:32 justin_smith: (defmacro andl [& args] `(and ~@args)) ?

12:32 err

12:33 llasram: heh

12:33 justin_smith: (defmacro andl [lst] `(and ~@lst)) ?

12:33 that may be what you want, but that is not much different from every?

12:33 silasdavis: justin_smith: I can't get URL to accept the s3 protocol

12:33 znDuff: Heh.

12:33 silasdavis: get MalformedURLException unknown protocol: s3

12:33 staafl: CompilerException java.lang.RuntimeException: Unable to resolve symbol: quote in this context,

12:33 * znDuff tries to remember who was asking about large websites publicly running their frontends on Clojure yesterday.

12:34 llasram: ,(reduce (fn [_ x] (if x true (reduced false))) true [true true true true true])

12:34 clojurebot: true

12:34 llasram: ,(reduce (fn [_ x] (if x true (reduced false))) true [true false true true true])

12:34 clojurebot: false

12:34 llasram: staafl: ^^ I think that's what you want for `and`

12:34 justin_smith: silasdavis: ahh, going the other way - we are converting s3 via rgex into protocol-relative links (http or https)

12:34 *regex

12:34 llasram: You can turn it into a function, for prettiness

12:35 staafl: llasram, "reduced"

12:35 does that short circuit the reduce?

12:35 justin_smith: llasram: (partial every? identity)

12:35 silasdavis: anyone know how to register a custom URLStreamHandler by any chance?

12:35 llasram: staafl: Yep

12:36 justin_smith: Ok yeah, that is shorter :-)

12:36 staafl: llasram, thanks

12:36 llasram: I just have reducers on the brain right now

12:36 staafl: justin_smith, thanks to you too

12:36 actually, I think I'll use (every? identity lst)

12:36 xuser: znDuff: you have a list?

12:36 llasram: For the best

12:37 justin_smith: daily mail is a big one, also soundcloud

12:38 there should be a list, if there isn't

12:38 (re: bit sites running clojure)

12:39 mavbozo: hi, is there any way to delete html tag in enlive deftemplate?

12:52 technomancy: there's one on the dev.clojure.org wiki, but you can't edit it

12:59 justin_smith: technomancy: http://dev.clojure.org/display/community/Clojure+Success+Stories ?

13:00 hyPiRion: heh, last edited 10 months ago

13:00 justin_smith: yeah, and the two biggest examples I know of in terms of degree of usage aren't even on that list

13:01 technomancy: that's the magic of wikis that you can't edit

13:01 justin_smith: also, needs a "how and how much" column

13:01 technomancy: ever wonder what were the biggest clojure companies in 2011? now you can know.

13:03 hyPiRion: heh

13:04 gfredericks: I do not understand vars

13:06 what is going on here? https://www.refheap.com/20137

13:07 justin_smith: gfredericks: weird, I got :thread-bound

13:07 which is what you expected, right?

13:09 hyPiRion: I got :origin-root but hm

13:11 gfredericks: I think you're creating a var containing a var

13:11 Works fine with let.

13:13 justin_smith: yeah, when you def something to be a var, that creates a var var right?

13:13 which is why the @?

13:14 so why do you guys get :origin-root and my repl gives me :thread-bound?

13:14 *clojure-version* => {:major 1, :minor 5, :incremental 1, :qualifier nil}

13:15 hyPiRion: same here

13:18 justin_smith: so this needs push-thread-bindings because binding would just grab the symbol, and not the var pointed at by the symbol, right?

13:29 hyPiRion: yeah, but I would guess the metadata fell off the var for some reason

13:32 si14: cemerick: hi. can I ask you a question about Friend?

13:33 cemerick: si14: shoot

13:36 si14: cemerick: how can I perform some actions (logging auth to database, for example) after authorization by friend-oauth2? I need to do this only when user is logging in and not every time user's authorization is checked. Can't fully wrap my head around docs on this, so asking you directly :)

13:37 broquaint: I've just installed cider from MELPA and when I boot the REPL (with cider-jack-in or an existing lein repl) I get the emacs version and nothing else (e.g no prompt) - https://www.refheap.com/20138

13:37 Is that situation familiar to anyone?

13:38 technomancy: broquaint: melpa serves unstable packages by design; I highly recommend sticking with marmalade

13:38 cemerick: si14: sounds like you actually want to write your own workflow, that does whatever logging you want, and delegates all the actual authentication to friend-oauth2

13:39 broquaint: Thanks, technomancy, but AFAICT cider isn't on marmalade ATM, in fact I'm only using MELPA because that's I saw it was available there :)

13:39 technomancy: broquaint: I recommend using nrepl.el until cider stabilizes

13:39 coventry: broquaint: Why do you want to use cider?

13:39 broquaint: i.e http://marmalade-repo.org/packages/cider - Package "cider" doesn't exist

13:40 coventry: Because I liked nrepl and prefer my REPLs in emacs.

13:40 technomancy: Thanks I'll switch back to nrepl in the mean time :)

13:40 coventry: broquaint: Take technomancy's advice, then.

13:40 broquaint: Indeed :)

13:40 * znDuff thinks that most of the discussion about cider emphasizes just why the rename was so necessary

13:40 znDuff: (ie. "back to nrepl", vs "back to nrepl.el").

13:40 technomancy: we get people with broken melpa packages in here practically every other day =\

13:41 si14: cemerick: ok, thank you. What's the best doc on this? Friend's README/source code? :)

13:41 technomancy: the fact that nrepl.el was deleted from melpa is just; ugh

13:42 I guess melpa users are just accustomed to dealing with random breakage

13:42 * broquaint removes melpa from his package-archives

13:43 cemerick: si14: friend's readme is pretty comprehensive re: the responsibilities of workflow fns. There's no examples of what I just described that I'm aware of, but it's roughly just function composition.

13:43 There's http://friend-demo.herokuapp.com, but that covers more basic matters than e.g. logging particular workflow requests

13:48 broquaint: Hrm ... same problem with nrepl 0.2.0.

13:48 nrepl.el

13:51 * si14 cemerick: thank you!

13:51 si14: *(without /me)

13:51 cemerick: si14: np, FWIW :-)

14:07 tsdh: How can I stop java.lang classes being imported in a namespace so that that namespace may define a var Package for example.

14:09 I.e., something like (:refer-clojure :only []) for classes.

14:09 mtp: pick better names? :)

14:09 tsdh: mtp: The namespace is generated from some model.

14:10 mtp: generate better names?

14:10 :p

14:12 tsdh: If the model defines a Package, then there is no better name than that. Adding articifial prefixes like +$+fuddle+$+ is not what I want.

14:12 Hm, if there was a way to enumerate all java.lang classes, I could `ns-unmap` these symbols...

14:15 arrdem: oh right. great. there goes the nrepl.el package. again.

14:18 tsdh: Ah, got it. I can iterate over `ns-imports' and `ns-unmap' the syms.

14:28 rasmusto: why not "clide"

14:28 technomancy: why not... nrepl-dot-el.el

14:29 rasmusto: i pronounce it en-prep-uhl-ehl

14:29 technomancy: man, the one time I go and pick a boring name for a project and it's not good enough

14:29 rasmusto: should have gone with nrepel

14:29 cemerick: technomancy: see, shouldn't slack off so hard :-P

14:29 technomancy: not bad

14:30 hiredman: enrepal-dot-ee-el.el

14:30 technomancy: hiredman: unacceptable; that filename is not representable on DOS filesystems

14:31 rasmusto: nrelpael

14:31 technomancy: (this is an actual thing real humans say unironically on emacs-devel)

14:31 well, one specific human

14:32 johann: hi everyone--im trying to deploy a clojure/clojurescript app to heroku and am running into the error R10 issue. i'm pretty new to clojure so i dont really understand how to manage the error

14:32 technomancy: you think having to deal with com.defunctstartup package names are bad, try dealing with 8.3 filenames

14:32 cemerick: that's a good domain name!

14:32 technomancy: johann: are you doing full AOT during push?

14:34 johann: technomancy: i do not think so. when i check the heroku logs i see that its still trying to grab jars before it times out and crashes and repeats

14:35 technomancy: johann: highly recommend generating an uberjar at push time

14:35 https://devcenter.heroku.com/articles/getting-started-with-clojure

14:37 arrdem: gfredericks: your swearjure presentation was glorious.

14:38 johann: technomancy: i was having issue using an uberjar earlier. i will read through this carefully and try again! thank you :)

14:39 technomancy: johann: there's a lot more that can go wrong when using lein at runtime; uberjars are a lot simpler

14:41 johann: gotcha. let me see what arises

14:41 seangrove: technomancy: uberjar + AOT?

14:41 technomancy: seangrove: yup

14:41 johann: technomancy: does it make a difference that im using httpkit?

14:41 technomancy: johann: no

14:42 seangrove: your doppleganger is screwing with your tab completion

14:42 or rather, everynoe else's tab completion

14:42 dnolen: Bronsa: let me know when 0.7.10 goes out

14:45 hyPiRion: http://www.infoq.com/presentations/swearjure :D

14:46 johann: technomancy: im getting the following error when i try to push it up to heroku https://gist.github.com/anonymous/0f341d99dd3b9ee18cb0

14:47 hyPiRion: (inc gfredericks)

14:47 lazybot: ⇒ 31

14:48 Bronsa: dnolen: I wanted to wait for TLDR-9 to get closed, but since it's unlikely that it will be completed by the end of the week I'm probably going to release 0.7.10 today

14:49 dnolen: Bronsa: if you want to hold it up for that no big deal

14:49 technomancy: johann: just `lein uberjar`

14:49 dnolen: Bronsa: there's a few other things I'd like to get into CLJS before the next release as well

14:50 arrdem: hyPiRion: I almost lost it at "swearjure in production"

14:50 johann: technomancy: after that i assumed that i have to set the :uberjar-name property in the project.clj right?

14:50 technomancy: johann: maybe you should start at the top. =) :uberjar-name in project.clj should be enough on its own.

14:51 Bronsa: dnolen: I think I'm going to release it anyway -- I have a small breaking change I'm going to make once that ticket gets closed and I want to release a 0.8.0 for that

14:51 hyPiRion: arrdem: yeah, I love it

14:51 arrdem: hyPiRion: what part did you play in this madness?

14:52 hyPiRion: ~quicksort

14:52 clojurebot: quicksort is https://www.refheap.com/paste/284a0552a6b69c6037faa2db5

14:52 hyPiRion: and hello swearjure, of course

14:52 $google hello swearjure

14:52 lazybot: [hyPiRion/hello-swearjure · GitHub] https://github.com/hyPiRion/hello-swearjure

14:53 technomancy: I wonder if swearjure is limited enough for genetic algorithms to operate on it sensibly

14:54 dnolen: Bronsa: k

14:54 arrdem: I would doubt it... limited it may be but the trivial operations are so convoluted that despite having very few primitives I think it would be hard.

14:54 Bronsa: dnolen: FYI not sure if it's something that cljs error messages could benefit from, but the patch aredington is working on adds the source form as metadata where it can,e.g #() -> ^{:source "#()"} (fn* ([]))

14:55 technomancy: whoa bronsa is into swearjure too?

14:55 =)

14:55 hyPiRion: technomancy: yeah, he's secretly making an analyzer for it

14:56 coventry: What the heck is going on with ##(#('%& '%& '%&)) ?

14:56 lazybot: ⇒ rest__28561#

14:57 arrdem: coventry: it's a gensym. somehow.

14:57 Bronsa: hyPiRion: ssssh don't tell them

14:57 dnolen: Bronsa: hm, that seems useful - not sure where we'd use that in the compiler, but it does seems neat for user macros?

14:57 coventry: arrdem: Yeah, I meant how is that producing the gensym?

14:57 technomancy: hyPiRion: do swearjure programs typically depend on the order of compilation via actual gensym values?

14:57 dnolen: Bronsa: what was the use case aredington had in mind?

14:58 bitemyapp: You people will use Swearjure but Haskell is a bridge too far? Weirdos.

14:58 arrdem: (inc bitemyapp)

14:58 lazybot: ⇒ 5

14:58 gfredericks: what my swearjure presentation is online?

14:58 mdrogalis: Watching the Swearjure talk. Pretty funny. :)

14:58 Bronsa: dnolen: he said he's working on a static analyzer, I think he needs to map back to the original clojure source

14:58 coventry: bitemyapp: I've been reading John Hughes lately. He makes an interesting case for monads.

14:58 hyPiRion: technomancy: no, not generally. My quicksort used one to check if I was at the end of a list

14:59 But I don't think it's common practice. I've used few in production at least.

14:59 dnolen: Bronsa: interesting, though it seems a bit strange to want to do that at the level of forms?

14:59 seangrove: (inc gfredericks) ; good fun!

14:59 lazybot: ⇒ 32

14:59 Bronsa: coventry: ##'#(%&)

14:59 lazybot: ⇒ (fn* [& rest__28573#] (rest__28573#))

14:59 bitemyapp: coventry: I don't think the case needs to be made in general, but rather a way to make them more accessible/nicer in a dynamically typed lang.

15:00 hyPiRion: ,'#('%& '%& '%&)

15:00 clojurebot: (fn* [& rest__29#] ((quote rest__29#) (quote rest__29#) (quote rest__29#)))

15:00 bitemyapp: coventry: part of what makes Monads nice in Haskell is they get enforced by the type system, with the compiler smacking you in the nose and calling you a bad kitty when you try to reach into an IO ()

15:00 coventry: maintaining the useful "boxing" of monadic results in a dyn-lang is a matter of discipline rather than tooling at the moment.

15:00 hyPiRion: Reads as: Call the symbol on the same symbol, and return the symbol if the symbol doesn't contain the symbol.

15:01 technomancy: hyPiRion: I'd expect that to need `%& though

15:01 coventry: hyPiRion, Bronsa: Oh, it was the default argument part I was missing. Thanks.

15:02 bitemyapp: Yeah, I can see how that would be a problem.

15:02 hyPiRion: technomancy: heh, to avoid naming collisions?

15:03 bitemyapp: coventry: it gets worse when you start getting into things like Monad Transformers.

15:03 coventry: keeping the monad stack in your head and figuring when to lift and when to send a functor through would be insane

15:03 technomancy: hyPiRion: oh, it's expanded by the #() reader macro; I see now

15:03 bitemyapp: I'm way too fucking lazy for that. I'd rather the compiler tell me I'm stupid.

15:03 technomancy: I was confused because plain '%& doesn't expand

15:03 Bronsa: dnolen: not sure I get what you mean, his approach looks like the only sane way to go source -> read form -> source without using a parser instead of the reader

15:04 hyPiRion: technomancy: ah, yeah. It has to be done inside a function literal

15:05 dnolen: Bronsa: sorry was busy w/ something else and didn't read closely, yes that makes sense.

15:05 coventry: Interesting that the function literal process gets a crack at them before their quoted.

15:06 TimMc: coventry: It doesn't, though.

15:06 arrdem: bitemyapp: and does it do so often?

15:06 Bronsa: coventry: quoting happens after read-time

15:07 TimMc: What? Quoting is part of reading.

15:07 bitemyapp: arrdem: of course - I'm stupid and the compiler is never wrong.

15:07 Bronsa: TimMc: no, 'foo -> (quote foo) is part of reading

15:07 bitemyapp: arrdem: I find GHC very very helpful when I'm writing Haskell code - especially in unfamiliar territory.

15:08 TimMc: gfredericks: It's weird to hear someone I've never met in person speak my name in a video. :-D

15:08 Bronsa: TimMc: what I'm trying to say is that the reader would have no way of knowing that "%&" #('%&) should stay that way instead of being gensym'd -- it is not aware of the quoting

15:09 technomancy: bitemyapp: offloading some of the cognitive ovehread to your exocortex, as it were

15:09 bitemyapp: technomancy: that's precisely it.

15:09 arrdem: clojurebot: GHC is an exocortex

15:09 clojurebot: Ok.

15:10 technomancy: "Computer, it's late. Tell me if this makes any sense."

15:10 bitemyapp: arrdem: good call.

15:10 gfredericks: TimMc: I just put your face on infoq

15:10 bitemyapp: technomancy: since I didn't have the experience of writing grench, how good of a job did OCaml do of catching you?

15:11 technomancy: bitemyapp: it was extremely helpful

15:11 bitemyapp: I thought that OCaml wouldn't be as good at separating side-effects because it doesn't have the IO monad

15:11 gfredericks: hyPiRion: okay so did anybody figure out this var thing? I don't understandy your var within a var comment. I know I'm _doing_ that, but I can't see how it should affect the outcome

15:11 technomancy: turns out returning unit gets you 80% of the way there

15:11 or 80% of where I imagine "there" to be, having never been there myself

15:11 hyPiRion: gfredericks: no. All I know is that it works inside a let.

15:12 bitemyapp: technomancy: possibly. the IO Monad as a free-standing "feature" doesn't do a lot, just forces bind out of IO like any other monad.

15:12 gfredericks: hyPiRion: as in (let [x @v] ...)?

15:13 bitemyapp: technomancy: the more useful bits are that this works well for all monads in all computation and it can enforce arbitrarily deep stacks of monads if you need the type system to enforce some declarative model of computation for you.

15:13 hyPiRion: gfredericks: as in (let [v (doto (clojure.lang.Var/create ...))] ...)

15:13 bitemyapp: technomancy: in practice, simple code in Haskell ends up being similar to simple code in OCaml. it's at the hairy edges where they diverge.

15:13 technomancy: clojurebot: typed clojure is http://p.hagelb.org/typed-clojure.jpg

15:13 clojurebot: You don't have to tell me twice.

15:14 bitemyapp: technomancy: I like the Hotel California in the background. That's where they trap the bugs so they can never leave.

15:14 technomancy: bitemyapp: there was one place where I wanted to use Option monadically and I would have had to pull in a 3rd-party lib

15:15 but the manual equivalent of map in that case wasn't bad at all; it was more of a "oh, I guess that's what map is for" moment

15:15 marcopolo2: technomancy: hovercars and punchcards, that an interesting view of the future

15:16 bitemyapp: technomancy: that and the lack of "real" concurrency are why I use Haskell. I don't know that concurrency in Haskell would be very much fun if the monads weren't there to enforce barriers.

15:16 the features play off each other nicely.

15:16 the STM containers in Haskell aren't nearly as "clean" or uniform as Clojure though.

15:16 dnolen: cemerick: (or anyone else) any thoughts about CLJS warnings?, I was considering changing it so that the only options is enable/suppress :all, or enable/suppress :undeclared.

15:16 seangrove: ~typed clojure

15:16 clojurebot: typed clojure is http://p.hagelb.org/typed-clojure.jpg

15:16 technomancy: bitemyapp: yeah, I wouldn't use OCaml for somewhere concurrency mattered

15:17 marcopolo2: dnolen: what about wrong arg count?

15:17 gfredericks: hyPiRion: oh I see; hmm

15:18 cemerick: dnolen: Seems like differing use cases really do want/need fine-grained control

15:18 dnolen: marcopolo2: this is just getting rid of useless knobs - there won't be less warnings

15:18 gfredericks: hyPiRion: that's super bizarre and I can't explain it. but having it as a local is what I need anyways so I guess I'll just go ahead with it

15:18 TimMc: gfredericks: That was a good talk! :-D

15:18 marcopolo2: dnolen: ok

15:18 dnolen: cemerick: ok sure, I'm also fine to leave it as is. Just wasn't obvious to me that anybody actually used these knobs.

15:19 hyPiRion: gfredericks: Can't explain it either :x. I'd guess it inlines the var reference inside the let for some reason?

15:19 bitemyapp: technomancy: also strange is Clojure's lack of retry.

15:19 no orElse either.

15:20 cemerick: dnolen: I don't think anyone does, yet. I definitely want to make it so that you can configure cljsbuild to fail on certain warnings.

15:20 seangrove: dnolen: What knobs currently exist?

15:20 gfredericks: TimMc: phew

15:20 TimMc: I like all the nervous laughter in the audience.

15:21 At least one person is thinking "Should I be taking notes? Oh no, what if my code isn't swearjure-compatible!"

15:21 technomancy: hahaha

15:21 arrdem: more than one person is pondering how many pages would need to be allocated to the JVM's stack in order to run the leiningen build of swearjure...

15:21 gfredericks: technomancy's tweet afterwards was the best comment that has ever been made about anything I've done

15:22 technomancy: I don't even remember

15:22 dnolen: seangrove: :undeclared, :redef, :dynamic, :fn-var, :fn-arity, :fn-deprecated, :protocol-deprecated

15:22 TimMc: 50 years from now, engineers will stand by the water cooler and complain about the swearjure-implemented financial software they have to maintain.

15:23 gfredericks: technomancy: you said it was "surprisingly G-rated", which is a reaction I've been trying to duplicate ever since

15:23 TimMc: haha nice

15:23 technomancy: oh right; hehe

15:23 seangrove: dnolen: Thanks, would love to have cljsbuild fail on some of these

15:23 cemerick: I haven't worked on cljsbuild at all, would it be a breaking change, or something that could be in a point release?

15:24 TimMc: gfredericks: Speak to me of this var within a var; it sounds naughty and I am intrigued.

15:24 dnolen: seangrove: yes this has come up before, a way to pass a handler into the compiler so that build tools can dictate what happens when errors are encountered.

15:25 gfredericks: TimMc: https://www.refheap.com/20137

15:25 I'm just trying to get a thread-localable reference type

15:25 that works correctly with bound-fn and friends

15:25 but without being interned in a namespace

15:25 seangrove: dnolen: I could work on that sometime next week

15:26 Any existing design doc?

15:26 stuartsierra: gfredericks: Not sure exactly what you're trying to do, but maybe with-local-vars would help.

15:27 TimMc: gfredericks: Oh huh.

15:28 gfredericks: stuartsierra: I tried that but the var seems to quit existing at the end of the scope? or something like that

15:28 TimMc: technomancy: The "bug-free world" thing, when was that produced?

15:28 dnolen: seangrove: there isn't, but I don't think this really requires one at this point - the simplest hook is all we need, and best if it's only really supported/documented at closure.clj.

15:28 stuartsierra: gfredericks: yes

15:29 seangrove: dnolen: Got it, will take a look.

15:29 TimMc: If it's any time within the last 30 years I need to smack someone.

15:29 technomancy: TimMc: wish I had a source, sorry

15:29 gfredericks: stuartsierra: I'm trying to make a variant of with-redefs (that works only on functions) that makes thread-local modifications via a hidden dynamic var

15:29 (for testing)

15:29 Bronsa: gfredericks: putting the push-thread-bindings inside the try seems to work

15:29 gfredericks: waaat

15:29 everything about this is weird

15:30 stuartsierra: gfredericks: "hidden dynamic var" - three words that I never wanted to hear together ;)

15:31 gfredericks: stuartsierra: the use case is being able to safely parallelize tests that stub functions

15:31 pepijndevos: What is a good introductory piece on datomic?

15:31 tbaldridge: pepijndevos: theory or practical use?

15:31 bitemyapp: pepijndevos: well datalog would be learndatalogtoday.com - Datomic? Maybe the Day of Datomic repo.

15:32 Craig Andera had a nifty presentation on some aspects of Datomic not long ago.

15:32 pepijndevos: tbaldridge, something that would exaplin what datalog is well to someone from a more traditional background

15:32 bitemyapp, link doesn;t work

15:33 tbaldridge: Rich's talks are pretty good: http://www.infoq.com/presentations/datomic-functional-database

15:33 bitemyapp: BAH

15:33 pepijndevos: http://www.learndatalogtoday.org

15:33 Bronsa: dnolen, cemerick: released 0.7.10

15:33 tbaldridge: pepijndevos: and in that one Rich actually pulls out Emacs in the middle of a talk...I thought I'd never see the day.

15:33 cemerick: yeah, it'll be a breaking v2 change

15:33 gfredericks: rich was using emacs at the first clojure conj

15:33 dnolen: Bronsa: sweet

15:34 tbaldridge: pepijndevos: I've also heard good things about http://www.youtube.com/watch?v=ao7xEwCjrWQ but I haven't watched all of it yet.

15:34 bitemyapp: Oddly, he's using Aquamacs in the presentation.

15:34 cemerick: Bronsa: thanks much; I'll tweak up the cljs patch once dnolen gives it a look

15:34 pepijndevos: http://www.learndatalogtoday.org

15:34 bitemyapp: pepijndevos: yes.

15:35 pepijndevos: http://webchat.freenode.net

15:35 technomancy: bitemyapp: I used to think "oh, rich uses aquamacs; I should make sure my elisp libs support it I guess" but then I realized he's probably not going to use anything fancy =)

15:35 pepijndevos: oops

15:35 bitemyapp: technomancy: the man probably uses hammocks more than Emacs :)

15:36 pepijndevos: bitemyapp, tbaldridge , thanks

15:36 technomancy: bitemyapp: I wish I could find the sjl tweet where he shows a screenshot of the recommended editor for working through SICP and it's a pen and paper

15:37 mdrogalis: technomancy: Hah

15:37 sjl: technomancy: https://twitter.com/stevelosh/status/310487495198523393

15:37 technomancy: nice; thanks

15:40 marcopolo2: (inc sjl)

15:40 lazybot: ⇒ 1

15:41 technomancy: sjl: been a while. still doing much clojure these days?

15:41 sjl: technomancy: right now mostly scala at work

15:41 bitemyapp: I'm actually pretty curious how much of Simple's stack is Scala/Clojure/JRuby.

15:41 dnolen: cemerick: Bronsa: patch looks good, lets go w/ NO_SOURCE_FILE as in Clojure

15:41 sjl: we do use some clojure though so I'll be getting back into it at some point

15:41 gotta do something now though, back in a bit

15:41 technomancy: sjl: ah, well hope it happens sooner rather than later =)

15:42 cemerick: dnolen: sounds good, I'll revisit tonight or tomorrow. Do you have any idea re: the orphaned require-macros expression? Just vestigial?

15:42 dnolen: cemerick: parse 'ns is a monstrosity, I barely understand any of it.

15:43 cemerick: heh, fair enough

15:43 dnolen: cemerick: likely vestigial.

15:43 cemerick: I'll fix up that misspelling as well

15:43 dnolen: cemerick: sounds good

15:43 cemerick: Could use some typed-clojure action in there :-P

15:45 akurilin: Is the convention of using ! at the end of fun names for functions that have a nil return value + side effect or in general for any side effect? As in, would a logging function get a ! in its name?

15:46 bitemyapp: akurilin: any side effect unless it's super obvious.

15:46 a family of logging fns probably don't need it. they're for logging. that's a side effect.

15:46 akurilin: In my case, I have a fun that returns a future, but the future itself is doing exclusively a side-effect. So you kind of get something back :P

15:46 bitemyapp: But, "transfer-money" if it's side-effecting should get a !

15:46 doesn't matter

15:46 that's not what I said.

15:47 the ! is to prevent anybody from being surprised by side effects.

15:47 akurilin: bitemyapp, I know, I like your approach.

15:47 bitemyapp: It's not a hungarian notation for return values.

15:47 if you want to note return values, annotate the var with core.typed.

15:47 akurilin: got it.

15:47 bitemyapp: principle of least surprise and all that.

15:47 tbaldridge: akurilin: technically the ! means it's not STM safe. Hence why send doesn't have one. It's side effecting, but still transaction safe.

15:47 akurilin: bitemyapp, yeah I like that.

15:48 TimMc: gfredericks: The trouble in implementing the SKI combinator calculus in Swearjure is K, right? That would be like implementing clojure.core/constantly

15:48 bitemyapp: akurilin: tbaldridge's approach is stricter but also valid.

15:48 I don't think any expects a logging fn to be STM safe.

15:48 anybody*

15:49 akurilin: speaking of typed, would it be a good a fit for annotating "controller" functions that get called straight from the router? To make sure the input schema is what I expect it to be rather than anything.

15:49 bitemyapp: it wouldn't really verify much for you. Just that you're getting request, params, etc?

15:49 akurilin: it wouldn't really verify much for you. Just that you're getting request, params, etc?

15:50 akurilin: bitemyapp, I'm more interested in schema / type verification of the param map I'm getting.

15:50 any way I can declaratively constrain that?

15:50 bitemyapp: akurilin: that's runtime bro.

15:50 akurilin: clj-schema

15:50 technomancy: TimMc: K is constantly, right

15:50 bitemyapp: or mississippi

15:51 akurilin: bitemyapp, so clojure.typed is more of a hinting system?

15:51 bitemyapp: akurilin: I don't think you're understanding the difference between a type system and runtime schema enforcement.

15:51 akurilin: a type system cannot enforce/prevent things that happen at runtime from user input.

15:52 it can ensure you don't write any code that expects data to be in the schema of a defined HMap that won't be in there

15:52 but it can't spew error messages at users at runtime.

15:52 type systems can reach into the nature of "values" with dependent and occurrence typing, but that's *still* nothing to do with runtime schema enforcement.

15:54 akurilin: I'm probably thinking of something like a map being cast into a well-defined struct, and that would blow up if there's no translation between the two.

15:55 bitemyapp: core.typed doesn't cast anything or change your code, it enforces the correctness of your types.

15:55 you can define an HMap that specs out the contents and types of the contents in a map in core.typed to enforce correct usage of that data.

15:55 gfredericks: TimMc: I haven't looked at SKI in long enough that I have no idea anymore. I remember having the impression it was conceptually straightforward and just needed a bunch of futzing with rest and that sort of thing

15:55 i.e., lots of non-objectionable details

15:56 technomancy: at one point I decided I was going to implement SKI in terms of lein tasks

15:56 I never did, and if anyone else wants to beat me to it I'd be tickled

15:56 akurilin: bitemyapp, I'd have to look more in depth into it when I have time to better relate to what you're saying.

15:57 bitemyapp: akurilin: do you want to enforce correct access of a Map with specified keys and values at compile time, or do you want to enforce the schematic correctness of inputs at runtime?

15:57 former: core.typed latter: clj-schema/mississippi/etc

15:58 well, "compile" time.

15:58 TimMc: Oh well, back to the URL mines.

15:58 bitemyapp: I wonder who had the job of making an HTML parser that works everywhere at Google?

15:58 and are they still alive?

15:59 akurilin: bitemyapp, ok thanks for clarifying the distinction, again, I'll have to look further into this before I can appreciate it.

15:59 dmi3y: Hello, can someone advice please how to make ajax call passing basic authentication parameters using ClojureScript ?

16:00 TimMc: bitemyapp: They probably have a collection of parsers with weights -- completely broken docs get the strip-tags parser and low weight, nice semanatic markup gets higher weight and maybe knows how to down-weight headers and menus.

16:00 coventry: If the JVM SecurityManager disallows getStackTrace, does that mean all exceptions come without stack traces?

16:01 akurilin: Is the idea of a data access layer reasonable with Clojure with cjj and korma? I'm ending up with quite a few different functions for each "model" for just getting hold of the data I need for them.

16:01 So that to me is a DAL as far as I can tell.

16:03 bitemyapp: akurilin: possibly.

16:03 One doesn't really want to be spending a lot of time on CRUD, generaly.

16:03 generally*

16:03 akurilin: I would indeed prefer not to.

16:05 gfredericks: okay I got this var thing going I think

16:07 https://gist.github.com/fredericksgary/7143494

16:09 ^ clojure stubbing for the paranoid

16:09 oops it has a borg

16:10 tbaldridge: resistance is futile

16:11 hiredman: technomancy: remember the job is one third done, because SK give you I

16:11 gfredericks: borg eliminated

16:11 bitemyapp: gfredericks: is there a parallel runner for Clojure?

16:11 gfredericks: bitemyapp: I have no idea :)

16:11 bitemyapp: well this is relevant to my interests :)

16:11 gfredericks: PHEW

16:12 I didn't mean that ironically that's actually how I react to most things

16:15 scopedTV: I'm looking for a std library function that applies a function to the values of a map. Is there such a function?

16:16 tsdh: scopedTV: And what should it return? The map with transformed values?

16:16 seangrove: Any way to get emacs in I-search to show me "match 2 / 50" as I'm banging C-s?

16:16 scopedTV: tsdh: Yes.

16:16 manutter: scopedTV: check out https://github.com/weavejester/medley

16:17 specifically the map-vals fn

16:17 tsdh: This should also do: (apply hash-map (mapcat (fn [k v] [k (transform v)]) my-map))

16:18 scopedTV: yeah I figured something like that out, but thought there must be a better method.

16:18 Thanks!

16:18 hyPiRion: tsdh: only if you want to use hash maps. Sorted maps go boom with that one

16:18 bitemyapp: seangrove: hook + count-matches + output to sub-bar.

16:19 the 2 out of X part would be a little tricker, still doable.

16:19 tsdh: hyPiRion: Uh, then use (apply sorted-map ...), no?

16:20 hyPiRion: tsdh: yeah, I'm just nitpicking. It's just good to be aware of the subtle details

16:20 seangrove: bitemyapp: The obvious worry being that the size of the buffer may be too big an kill the search

16:23 tsdh: hyPiRion, scopedTV: Then that's probably better, i.e., works with any kind of map: (into (empty my-map) (map (fn [k v] [k (transform v)]) my-map))

16:23 hyPiRion: yeah, medley has a good version of it

16:24 tsdh: hyPiRion: Indeed, nice.

16:28 arrdem: bitemyapp: so I'm staring at the do monad... isn't this just excessively complicated function composition or do I need to se the other monads to appreciate it?

16:28 bitemyapp: technomancy: and to balance out the nice things I said earlier: http://www.yesodweb.com/blog/2013/10/pipes-resource-problems

16:28 arrdem: the do monad is just sugar for bind

16:28 arrdem: if you want to learn why monads are useful, it's best to just write Haskell programs.

16:29 arrdem: also: http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-Way/

16:29 TimMc: gfredericks: Man what I don't

16:29 arrdem: bitemyapp: I may wind up doing just that... lets hope I pass GHC's IQ stat check

16:29 TimMc: I don't have brain for vars today, I guess.

16:31 bitemyapp: arrdem: I wouldn't sweat it, I'm an idiot.

16:32 gfredericks: TimMc: yeah it's a littel hairy

16:33 TimMc: mostly it's just jumping through hoops to make sure there's only one dynamic hidden var created at a time

16:34 xuser: bitemyapp: you don't like doing CRUD apps in clojure or in general?

16:34 bitemyapp: Programmers should automate away boring tasks.

16:35 That's our purpose for existence.

16:35 coventry: arrdem: Still not sure I buy it, but section 2.4 "Why Use Monads?" is a good place to start. http://citeseerx.ist.psu.edu/viewdoc/summary;jsessionid=0F0DFB385D76652AEB59F86E31F368DA?doi=10.1.1.29.4575

16:36 Also section 3.1 "On Category Theory." But I totally don't buy that.

16:36 TimMc: gfredericks: I'll stare at that on the subway sometime.

16:39 mdrogalis: Hm, where the heck is BigDecimal?

16:39 ,clojure.lang.BigInt

16:39 clojurebot: clojure.lang.BigInt

16:39 mdrogalis: ,clojure.lang.BigDecimal

16:39 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.lang.BigDecimal, compiling:(NO_SOURCE_PATH:0:0)>

16:39 arrdem: coventry: thanks, I'll throw that on the reading list.

16:39 mdrogalis: Oh, it's Java's BigDecimal.

16:41 bitemyapp: coventry: the point is reliable abstractions which you can reason about at a high level.

16:41 if certain things aren't guaranteed or ensured by the compiler, then you lose the ability to ignore the less important details and thus cannot continue the march up the abstraction ladder

16:41 noncom: hi, i have a little question about macros: https://www.refheap.com/20142

16:41 bitemyapp: coventry: are you familiar with PG's essay that mentions "blub programmers"?

16:42 coventry: bitemyapp: Yes, but that's the point of any serious program.

16:42 bitemyapp: what point, what program?

16:42 arrdem: noncom: ~@

16:42 coventry: bitemyapp: "the point is reliable abstractions etc. etc."

16:43 bitemyapp: coventry: not long ago programmers were complaining about how procedures were too declarative and restrictive compared to their gotos.

16:43 arrdem: noncom: that's our sequence insert operator.

16:43 bitemyapp: coventry: I'm talking about something more universal and important than any one program.

16:43 arrdem: noncom: so (let [foo [1 2 3 4]] `(~@foo)) -> '(1 2 3 4)

16:43 bitemyapp: coventry: I'm talking about continually advancing the state of the art by enabling ourselves to build up reusable, composable, reliable abstractions.

16:44 arrdem: coventry: can I get the title of that paper? my browser isn't loving your link.

16:44 bitemyapp: Category theory happens to provide some nice faculties for discussing computational models at a high level.

16:45 coventry: arrdem: Sorry must be cookie-linked. "Generalising Monads to Arrows", John Hughes, 1998.

16:45 arrdem: coventry: no worries, thanks!

16:46 noncom: arrdem: hmm, i try and get an error, look the update: https://www.refheap.com/20142

16:46 coventry: bitemyapp: We've had this discussion. I don't think anything's changed, although my perspective's a little broader.

16:47 arrdem: noncom: that's because you aren't in a quoted form...

16:47 coventry: noncom: ,(macroexpand '(defmacro k [& body] ~@body))

16:47 ,(macroexpand '(defmacro k [& body] ~@body))

16:47 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

16:47 noncom: but the second try in the refheap uses quote

16:47 bitemyapp: coventry: the practical output of what I'm saying should be: learn new things, offer alternatives, don't simply reject things because they're unfamiliar.

16:47 coventry: Bah. Anyway, when something mysterious happens in a macro, macroexpand is the first tool to reach for.

16:48 bitemyapp: We're not going to keep making houses with mud forever.

16:48 arrdem: noncom: http://en.wikibooks.org/wiki/Learning_Clojure/Macros

16:49 noncom: as with normal clojure code a macro "returns" the tail form. In order to generate or return code, the notation used is a backquoted list `(foo bar)

16:49 noncom: you can insert values into a backquoted form via ~<expr>

16:49 noncom: arrdem: but the second try in the refheap is (defmacro k [& body] `(~@body)) and still gives an error..

16:50 arrdem: noncom: probably... because you need do as the first element of that spliced list

16:50 noncom: i can't find a difference from the example from the wikibook that you referenced

16:50 oh that, wait i try

16:51 true that was about the (do) thing!

16:51 thanks!

16:51 arrdem: noncom: np

16:55 coventry: noncom: Sorry, that was a bad example. (macroexpand '(k (+ 1 2) (- 2 1))) would have been informative.

16:56 noncom: coventry: cool! i have tried like (macroexpand k) before and it failed, but now i'm starting to see things..

16:58 coventry: bitemyapp: Obviously, that's preaching to the choir. :-)

16:59 arrdem: bitemyapp: but I like playing with mud...

16:59 bitemyapp: arrdem: off to the Fortran mines with you then!

16:59 arrdem: I suppose clouds would be more fun...

16:59 coventry: One day, we will build a ball of mud which will build balls of mud for us.

16:59 arrdem: coventry: the power <strike>set</strike> ball of mud?

17:00 noncom: might turn out to be something like that: http://filer.case.edu/dts8/thelastq.htm

17:01 arrdem: bitemyapp: no thanks, that's where they send the grad students

17:10 avishai: question

17:10 arrdem: ~answer

17:10 clojurebot: Excuse me?

17:10 arrdem: dang.

17:10 avishai: i want to issue a few parallel actions and have a timeout for the entire operation

17:11 i can do this with futures

17:11 but

17:11 it's damn ugly

17:11 bitemyapp: avishai: core.async, alts, timeout.

17:11 avishai: you're welcome.

17:11 avishai: core.async ain't good since it's blocking

17:12 bitemyapp: avishai: could've fooled me, I think it has async in the name bro.

17:12 avishai: no,

17:12 the operations i'm using are

17:12 bitemyapp: so...change...them?

17:12 avishai: can't

17:12 they're plugins

17:12 external

17:13 bitemyapp: and it's impossible to wrap these operations?

17:13 avishai: with future or threads

17:13 it's possible

17:13 znDuff: well, there you are.

17:13 brehaut: avishai: jsut make an alternative to future that wraps up a future and a chan

17:14 avishai: then use select

17:14 good idea

17:14 any alternative without core.async?

17:14 brehaut: avishai: making new bits out of existing bits is what this FP is about

17:15 avishai: ok

17:15 brehaut, thank you very much

17:16 brehaut: avishai: its worth keeping in mind that in clojure all the different primatives for this stuff are largely intended to be used together

17:16 theres no 'one true model'

17:17 avishai: yes

17:17 tbaldridge: avishai: you can do blocking operations with core.async. Just do them inside a (thread...) block. It returns a channel, and then the rest of your code can be async

17:17 avishai: the problem is i'm still very young clojurer

17:18 i find it a bit confusing at this point to jump from blocking to non-blocking code in the same project

17:18 brehaut: avishai: its only a problem if you arent willing to learn. so looks like not a problem

17:19 avishai: no, it's not a problem; if anything it's a challenge!

17:19 thanks a lot. you people are awesome!

17:24 brehaut: avishai: i find that the sync / async thing sort of follows the general difficult challenge of partitioning a program into independant components. it mostly takes some experience mucking about learning the capabilities and trade offs of each bit and how they fit together

17:24 rasmusto: i ran into something last night. I have a bunch stuff that runs in a pmap, and I want to use a memoized function in there, but stuff doesn't get cached until everything has already kicked off... is there something like a "blocking memoize"?

17:26 brehaut: rasmusto: its possible that core.cache has something for that?

17:27 arrdem: rasmusto: what clojure version are you using?

17:27 rasmusto: arrdem: 1.5.1

17:27 brehaut: rasmusto: although thats surprising as memoize is jsut using an atom and swap!

17:27 arrdem: rasmusto: yeah... that should work just fine...

17:27 coventry: rasmusto: Do you mean that if someone is already computing (f x), all other calls to (f x) should block until the result is cached?

17:28 rasmusto: coventry: that's what I was thinking, yeah

17:29 my understanding from reading the source is that it does (apply f args) if it can't find a cached version, and only after doing so will it update the cache

17:30 so if I have a long-running function that I call a dozen times in parallel, they will all run to completion and each swap in their (identical) results

17:30 arrdem: rasmusto: yeah. this won't do any blocking on a parallel computation.

17:31 coventry: rasmusto: Is pmap smart enough to fire up more computations if a current thread is blocking?

17:31 rasmusto: coventry: I'm not sure

17:31 arrdem: coventry: if the current thread is blocking then it should yield to other green/real threads and life will be good.

17:31 rasmusto: arrdem: could I write a similar function to memoize that updates an argument map with values in a future?

17:32 coventry: rasmusto: pmap only runs (+ 2 (.. Runtime getRuntime availableProcessors)) processors.

17:32 arrdem: rasmusto: totally. I was just about to.

17:32 rasmusto: coventry: hmm, ok. What impact does that have in this case?

17:33 coventry: rasmusto: If more than two threads block, there will be fallow resources.

17:33 rasmusto: coventry: ah, gotcha

17:34 coventry: rasmusto: My impression is that reducers are supposed to be smarter about this kind of thing.

17:34 rasmusto: But I could be wrong. I have only read / heard about them, not played with them.

17:35 rasmusto: coventry: same here, I might have to explore them more now that I have a potential application

17:38 arrdem: rasmusto: https://www.refheap.com/20143 is what I'd do.

17:38 oops.

17:38 bug: the trailing ret needs an @

17:39 (doall)ing that sequence could be worthwhile depending on your application.

17:39 coventry: arrdem: That's still going to lead to duplicated work, isn't it? Don't you need some kind of locking based on the arguments?

17:39 * arrdem facepalms

17:40 rasmusto: was going to say something ;p

17:40 arrdem: coventry: no so this does do locking

17:40 unless I'm totally crazy.

17:40 rasmusto: this will spin up futures for each call, then swap them out when each call completes, yea?

17:40 arrdem: coventry: because I swap! in the ref returned by the future.

17:41 rasmusto: no.

17:41 so here's my understanding of what this will do.

17:41 for every element of the args, check to see if it's in mem

17:41 mem is _only_ refs, or nil. if the ref exists, deref it (this is blocking)

17:42 if the value is nil, swap! in a new future and yield the deref of the future.

17:42 rasmusto: ohh, wow. My eyes totally missed the map part

17:42 arrdem: yeah. so this is sequential on the args, which is why it'll work.

17:42 but it's parallel on the computation.

17:42 potentially.

17:42 rasmusto: hrm, okay.

17:43 I'm not sure if I want something that requires a map in its implementation

17:43 * arrdem shrugs

17:43 rasmusto: I think I just want a drop-in replacement for memoize

17:44 arrdem: I will have to think about how yours works a bit

17:44 arrdem: You could refactor the fn out and use it instead of memoize. Thanks to the atomicity gurantee of swap! it should Just Work (TM)

17:44 rasmusto: ah okay, so this is something that I'd call at a higher level.

17:45 my code is a bit nested though, and I'm concerned with a function call that's a few layers deep

17:45 not something that I can easily pull out and map across

17:45 (this is an issue on my end)

17:47 arrdem: I mean... the straight memoize is also trivial... https://www.refheap.com/20146

17:51 herm... so how does swap! effect the order semantics of an atom... isn't it essentially a (with-lock <atom> (set! <atom> (apply ... )))?

17:53 because if that's the case then you can escape any synchronization issues by getting rid of that (let) form and just swap! associng (future (apply f args)) directly.

17:54 rasmusto: hmm

17:54 arrdem: then the return value is just (deref (get .. args)), which expression is guranteed to be blocking :D

17:56 the problem with this is that (future) isn't pure... and (swap!) warns that the update fn may be applied multiple times due to retrying so it's _possible_ that you will be duplicating work depending on weird system synchronization cases.

17:56 s/case/behavior/

17:56 coventry: arrdem: I must still be misunderstanding. The following code prints out "1" four times, but if the memoization was working the way I expected, that would only happen once. What am I missing? https://www.refheap.com/20148

17:57 turbofail: arrdem: not necessarily even that weird. it should happen fairly often

17:57 coventry: (Just take out the (user/starbreak) line. It's a convenience function of mine.

17:58 arrdem: coventry: hum... weird! time to start testing my own snippets before pasting :D

17:59 coventry: Well, it's what I would expect from reading the code, as I described in my earlier question with the map question.

17:59 s/map question/map version/ :-)

18:00 turbofail: yeah, the future doesn't really help here, the problem is still that the value in the atom won't necessarily get updated with the key in time

18:01 arrdem: ok ok trying my (swap!) is atomic version.. lets see what happens..

18:01 L31K A BAu5

18:01 coventry: this version totally works.

18:01 https://www.refheap.com/20149

18:02 assuming that swap! never has to retry at any rate.

18:02 hyPiRion: You could've made it a promise too

18:03 doesn't use a new thread for the computation that way

18:04 rasmusto: why is fact always 1

18:05 arrdem: rasmusto: because I suck? :P

18:05 rasmusto: it looks right to me...

18:05 I guess I suck too?

18:05 turbofail: if it checked for the existence of the arguments in the memo table inside the swap! function then it wouldn't matter if swap! retried

18:06 arrdem: turbofail: oooh cute...

18:06 * arrdem edits

18:06 turbofail: and rest assured, swap probably will retry if you call the memoized function from multiple threads

18:07 rasmusto: fact needs to multiply x and (fact (dec x))

18:07 otherwise it keeps recursing and then hits 1 * 1

18:08 arrdem: rasmusto: lol looks like I mixed fib and factorial to no effect :P

18:09 rasmusto: factonachi sequence

18:09 fibotorial

18:09 arrdem: haha, that's cracking me up. You're 100% right

18:10 arrdem: Mckenzie Labs: wasting stack frames for multiplying 1 since 1992 :D

18:11 turbofail: well actually it can still duplicate work because two threads updating the atom for the same arg-value will both create futures that will run in the background, even though only one of those futures will ever end up inside the memo table

18:12 arrdem: so actually... with that swap-safe-assoc... the v will be (eval)'d first, so you will generate a bogus future which gets thrown away...

18:12 turbofail: right, that

18:12 arrdem: o/

18:13 turbofail: so a promise is probably what you actually want

18:13 arrdem: or you could throw the (future) in a (partial) so that it won't be evaluated, then only call the partial if the key isn't in the map...

18:14 turbofail: well you want to only call the partial if the swap! succeeds

18:14 which is not something you can really do

18:15 arrdem: oh yeah I see what you're saying.

18:15 turbofail: i think what you actually want is (delay (apply f args))

18:16 or something to that effect

18:16 arrdem: yeah delay is perfect.

18:16 marcopolo2: What's that lein config called that lets you reference a dependency you are working on, instead of having it in the dependencies vector

18:17 technomancy: marcopolo2: checkouts?

18:17 arrdem: except that it kills all possibility for parallelism in the evaluation..

18:18 mtp: yogthos‘ away-nicks are unnecessary. thanks for your understanding.

18:18 marcopolo2: technomancy: that's it, thanks!

18:19 technomancy: np

18:19 turbofail: arrdem: well it'll still allow parallelism for different arguments. it'll only kill parallelism for calls with the same arguments, which is exactly what we wanted

18:19 rasmusto: turbofail: that's correct. In my case I want it to block same-argument stuff

18:20 if the function itself is parallel itself that's still fine, and all of the other callers upstream can just hang out while it finishes

18:22 arrdem: ok cool! turbofail: good catches :D

18:23 rasmusto: arrdem: turbofail: is this kind of function something that could be widely used? I know I have an application for it, but I don't know if it could fit elsewhere

18:24 turbofail: rasmusto: dunno. for all i know core.cache might already have this

18:24 i haven't looked

18:26 arrdem: I doubt this fits in core.cache, just because that's several cache implementations with no use cases.

18:27 would probably fit in the flatland toolkit or some other snippets lib.

18:27 https://github.com/flatland/useful perfect fit.

18:30 rasmusto: arrdem: I'll drop it into my code for now and see how it behaves. https://www.refheap.com/20149 is the final one you wrote, yes?

18:30 arrdem: rasmusto: nope.

18:31 that (future) needs to be a (delay)

18:31 otherwise ok.

18:31 rasmusto: arrdem: ah, alright. you're awesome :)

18:31 turbofail: er. also needs to use the non-overwriting swap function

18:32 arrdem: https://www.refheap.com/20152

18:42 kovas: dnolen: u alive?

18:43 dnolen: kovas: yep

18:43 rasmusto: arrdem: performance numbers (idk how applicable the test case is) https://www.refheap.com/20153

18:43 kovas: dnolen: having trouble loading core.match

18:43 getting FileNotFoundException Could not locate clojure/core/match__init.class or clojure/core/match.clj on classpath: clojure.lang.RT.load (RT.java:443)

18:43 arrdem: turbofail, rasmusto: PR'd to flatland/useful

18:43 kovas: with [org.clojure/core.match "0.2.0"]

18:43 rasmusto: arrdem: awesome :)

18:44 kovas: also tried [match "0.2.0-SNAPSHOT"]

18:44 ha

18:44 well, just tried again and it works

18:45 heisenbug

18:45 arrdem: rasmusto: yeah that really isn't to surprising. for lightweight fns the coordination overhead of the atom is gonna really kill performance

18:45 dnolen: kovas: heh

18:45 seangrove: technomancy: No idea how you manage to even idle in emacs. I can barely glance without eyes glazing over.

18:45 kovas: damn state

18:45 dnolen: kovas: I've seen a few projects using it and I haven't heard complaints

18:45 muhoo: what's the difference between find and get? why would you use find instead of get or vice versa?

18:46 akurilin: Man, nrepl is the coolest thing ever. Running tasks from production straight from the app, reusing all of the existing code.

18:46 dnolen: muhoo: find returns the map entry, sometimes useful because it combines the beneft of contains? and get w/o needing to provide a not found value

18:46 akurilin: On that note, how does nrepl execute code on the target appliction? Does it spin up a new thread for each connection, and run everything on that?

18:47 muhoo: dnolen: thanks

18:50 rasmusto: arrdem: I hope to get some real numbers from my horribly inefficient code sometime this week, I'll let you know what happens

18:51 brehaut: Lexicon PSA: From now on, any bug caused by using when in place of if is now known as a Hagelbug

18:52 arrdem: ~lexicon

18:52 clojurebot: I don't understand.

18:52 arrdem: that should be a wiki page somewhere...

18:52 brehaut: you'll have to use your on-board memory

18:55 arrdem: eh I'll just mmap in a markdown file...

19:04 akurilin: bbl

19:07 johann: technomancy: got it to work! thanks for your responsiveness earlier :)

19:07 technomancy: johann: cool. anything confusing or unclear about the docs?

19:09 johann: techomancy: i probably was such in an ansy that i didn't slow down and understand the whole $PORT variable thing

19:09 techomancy: but that probably lends to my ability to focus than the docs themselves :P

19:20 Creap: I just found out about with-test, haven't seen much about it earlier. Is in uncommon for people to use it in their code? I think it looks interesting as an immediate and always up to date example of a function..

19:21 arohner_: Creap: I dont use with-test because I don't like the indention, and I like my src and tests separate

19:21 coventry: Creap: It hasnt't seen much use because people find it breaks up the flow of reading the code.

19:22 arrdem: Creap: I'd rather see docstrings or margalina docs than tests inline... tests would be kinda weird. maybe one in the docstring. maybe.

19:23 dnolen: cemerick: Bronsa: patch landed! a very nice one thanks.

19:24 Creap: ok, makes sense.. but wouldn't another benefit be to be able to test private functions?

19:26 coventry: Creap: Personally, I would find using (#'fully.qualified/name args) in the test file less disruptive.

19:26 arrdem: coventry: wouldn't that be a access error for a private fn?

19:27 wow it isn't...

19:29 coventry: Be sure to use this power only for good. :-)

19:29 Creap: :)

19:30 brehaut: arrdem: theres not really any such thing as a private function.

19:31 technomancy: brehaut: well, closures =)

19:31 brehaut: technomancy: not so much private as just local right?

19:31 arrdem: brehaut: I knew that private was really metadata, but I thought that it did do something in aot.

19:31 s/ato/gen-class/

19:31 technomancy: brehaut: not sure the difference is meaningful

19:32 brehaut: technomancy: probably true

19:32 technomancy: well, it's different from ^:private, just not "what you think of as the english definition of private"

19:35 brehaut: technomancy: if it were stateful things it might matter more

19:37 bitemyapp: arrdem: nope.

19:37 arrdem: vars are vars, regardless of when compilation happens.

19:39 arrdem: how many communication media can we spread our converations across? Time to fire up SC2 and talk on B.Net too?

19:40 MrJones98: i'm pretty new to clojure and experimenting with a library… they use alter-var-root but during testing (via lein test), it seems that the var is not being bound to the expected value

19:40 does anyone have helpful links for me to learn more about any nuances that are related?

19:42 bitemyapp: MrJones98: that's curious. alter-var-root should uh...just work. But lets drop the hypotheticals and just show us the code you're talking about. Use refheap if you need a pastebin.

19:43 hiredman: the nuances are "libraries that use alter-var-root should be avoided"

19:43 bitemyapp: that's like half of my libraries. I'm going to choose to take pride in this.

19:43 MrJones98: here's a link to the library that i'm trying to use

19:43 https://github.com/clojurewerkz/archimedes/blob/master/src/archimedes/core.clj

19:44 bitemyapp: hahahaha, I fucking knew this was going to be a clojurewerkz library.

19:45 MrJones98: i'm still too new to this community to have any idea if i should be laughing or crying

19:45 coventry: MrJones98: What test is failing?

19:45 MrJones98: but… transact!* on line 13 is what's causing me problems

19:45 coventry: In what context?

19:46 MrJones98: so archimedes isn't the test that's failing but one within titanium… i'm trying to modify titanium to work with titan 0.4.0

19:46 and in the process, pointing titanium to the latest version of archimedes

19:47 bitemyapp: Jenga Tower library usage.

19:47 MrJones98: and every test within titanium is failing, appearing as if transact!* is not being bound to something else

19:47 bitemyapp: "it appears I have too many wobbly wooden blocks stacked on top of each other. Clearly I can only solve this by stacking more wobbly wooden blocks"

19:47 MrJones98: bitemyapp: it sort of feels that way

19:47 bitemyapp: MrJones98: so...stop that.

19:48 MrJones98: i've been considering just starting over with just the parts i need to interact with ttian

19:48 coventry: Wow the titanium dependencies are pretty stupendous.

19:48 bitemyapp: MrJones98: throwing stuff away is almost always a good idea.

19:49 MrJones98: i'm still very new to clojure… so slowly learning which libraries are a good idea or not

19:49 i started with titanium… then saw that it built on top of archimedes and ogre

19:50 bitemyapp: I use some ClojureWerkz libraries but I try to hold them at a distance and not stack up the tower of things I don't understand pretty well very high.

19:51 MrJones98: any recommendations of "good" libraries i can take a look at to compare with?

19:51 coventry: MrJones98: Why do you want bleeding-edge archimedes?

19:52 MrJones98: i don't want bleeding edge archimedes necessarily… i'm looking for bleeding edge titan

19:52 coventry: bleeding-edge titanium works with the specified archimedes dependency.

19:53 (In my hands.)

19:53 Fails with bleeding-edge archimedes as you describe, though.

19:53 MrJones98: bleeding edge titanium doesn't work with bleeding edge titan though… so i started down this path trying to modify titanium to work with the latest titan

19:54 and titan 0.4.0 runs with blueprints 2.4.0… so then i decided to look at the latest archimedes

19:54 and then started building my jenga tower

19:55 bitemyapp: MrJones98: do you need to be using Titan specifically?

19:56 MrJones98: bitemyapp: that is a very good question… i was originally using neo4j but the graph mutations i was doing required something like faunus which got me to titan

19:57 bitemyapp: MrJones98: there's also the option of using Titan directly.

19:57 which is just Java

19:57 MrJones98: bitemyapp: yeah, i started this morning ready to integrate titan directly… then saw titanium so thought i might learn something trying to work with it

19:57 figured it might be a good clojure learning experienc3e

19:57 i have some decent experience working with titan/faunus directly from groovy

19:58 bitemyapp: MrJones98: did you try what coventry described?

19:58 native Clojure libraries are generally nicer.

19:58 noprompt: bitemyapp: sketch, refine, repeat.

20:00 MrJones98: bitemyapp: i'm thinking it's easiest to just roll my own "library" to interact with titan directly

20:00 bitemyapp: noprompt: wut

20:00 noprompt: bitemyapp: about throwing stuff away.

20:01 bitemyapp: noprompt: ah, yes.

20:01 MrJones98: if you make a nice micro-library please put it on github.

20:01 MrJones98: bitemyapp: will do

20:01 are you working with graph dbs?

20:02 bja: is tools.logging supposed to clobber pr/prn/print/println?

20:02 or rather, it clobber print

20:02 *clobbers print

20:02 but not pr and prn

20:03 noprompt: bitemyapp: although i feel programming is more like working with clay.

20:03 or mudd.

20:03 :)

20:03 technomancy: noprompt: https://mobile.twitter.com/tangentialism/status/379996890366238720?p=v

20:04 noprompt: technomancy: lol.

20:05 MrJones98: general question… if i'm working with something like databases where i need to open a connection, what's the "proper" clojure way to managing that?

20:05 i've seen how clojurewerkz does it with monger and titanium...

20:06 bitemyapp: MrJones98: make the connection a value. bucket of state for talking to the database and retaining results/dispatching queries

20:07 MrJones98: then just pass it around.

20:07 Be a lazy ass about this at your own peril.

20:07 noprompt: s/"proper" clojure\(way\)/\1 in which others will not give me "shit"

20:07 damn forgot a space. :/

20:07 coventry: MrJones98: Why do you want bleeding-edge titan, out of curiosity?

20:08 bitemyapp: MrJones98: make the rest of the API as pure as possible.

20:12 MrJones98: noprompt: i generally assume that i will always get shit from someone

20:12 bitemyapp: i'm not sure i even know what "being lazy" means when it comes to clojure

20:12 noprompt: MrJones98: you have won at least half the battle.

20:14 MrJones98: coventry: regarding titan, i'm looking to experiment with this particular feature of faunus 0.4.0 - Added FaunusRexsterExecutorExtension which allows remote execution of a Faunus script and tracking of its progress

20:15 noprompt: wow.

20:15 bitemyapp: MrJones98: proliferating statefulness throughout the API unnecessarily.

20:15 MrJones98: otherwise, all of my other development to date has been on titan 0.3.2

20:16 bitemyapp: makes sense… i've become a big believer of not having state if at all possible

20:16 frees up my brain to worry about other stuff

20:21 noprompt: i don't think i actually grok what i'm doing with this lein plugin.

20:25 i just want to watch some files at a path, load a file, grab the value of a var and something with it.

20:26 arrdem: bitemyapp: -E_BAD_CONTEXT

20:26 * noprompt begins crying.

20:26 arrdem: oh. right. the ^private thing.

20:33 noprompt: omfg. clean. i just needed to clean.

20:35 seangrove: dnolen: What patch was that?

20:50 Bronsa: seangrove: http://dev.clojure.org/jira/browse/CLJS-632

20:56 seangrove: Bronsa: Very nice

21:17 noprompt: ok. i give up. serious question. if i want to reload source code whenever it changes w/ a leinigen plugin what's a good gameplan?

21:18 technomancy: noprompt: just use your repl

21:20 noprompt: technomancy: i'm trying to automate a compilation function. ie. something that writes to a file.

21:21 technomancy: the changes could be in a directory.

21:21 technomancy: oh gotcha, so not for general dev use

21:21 there's a ring middleware you could try

21:23 noprompt: technomancy: right. here's the idea: i'd like to specify the name of a var which will contain that data. that data may depend on values in another namespace. whenever i make changes in the "source-paths" whatever they may be i'd like to reload the namespaces and recompile the value of the var.

21:24 do note, i understand my grammar is awful.

21:24 Raynes: noprompt: I'm gonna need you to head on down to LA now and visit me.

21:25 noprompt: Raynes: iz that so?

21:25 Raynes: Iz

21:25 noprompt: Raynes: :)

21:25 Raynes: what's the score?

21:25 Raynes: noprompt: wat

21:25 noprompt: Raynes: as in "what's happening"

21:27 Raynes: noprompt: Nothing. That's why you should be here.

21:27 We could make things happen.

21:27 noprompt: ah, indeed.

21:27 well i was supposed to visit bitemyapp/callen next weekend.

21:27 Raynes: Damn him.

21:27 Why is he special?

21:27 noprompt: yes.

21:27 Raynes: Am I not good enough for you?

21:27 seangrove: dnolen: http://dev.clojure.org/jira/browse/CLJS-636 Didn't touch closure.clj at all, but this seemed like the right place to put the warning hooks to some degree

21:27 Raynes: Don't answer that. I get it.

21:27 noprompt: you are worth.

21:27 * Raynes saunders off.

21:27 noprompt: *worth

21:28 ugggh WORTHY

21:28 Raynes: That wasn't a word.

21:28 * Raynes saunters off

21:28 noprompt: no wait!

21:28 srsly i need lol halp.

21:28 Raynes: :P

21:28 fakedrake: hello

21:29 where does lein download packages it pulls as dependencies?

21:29 noprompt: i've been at this for like an hour now.

21:29 fakedrake: ~/.m2/repository

21:30 fakedrake: noprompt: yay! thanx

21:30 noprompt: Raynes: do you get what i'm trying to do?

21:30 Raynes: Oh, I didn't actually look.

21:30 noprompt: Raynes: and perhaps know of how i could do it?

21:31 Raynes: noprompt: I imagine that lein-prism is probably a good starting point.

21:32 noprompt: Raynes: well now i have more source to read.

21:32 Raynes: I'm sorry.

21:33 noprompt: Raynes: nah it's all good.

21:33 Raynes: good ol watch/load-file do something wasn't working right.

21:36 oh snap it's almost lunchtime :)

21:39 welp better go eat

21:42 fakedrake: lein repl doesnt seem to find clojure.contrib

21:42 how do I get that?

21:43 technomancy: clojurebot: what happened to contrib?

21:43 clojurebot: Well... it's a long story: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

21:45 fakedrake: so what is the best way to get pwd from the repl?

21:45 technomancy: should be (System/getProperty "user.dir")

21:47 fakedrake: aha

21:47 is that also the best way to do that from an actual app?

21:48 technomancy: sure

21:48 note that you can't actually change the current directory of the jvm

21:49 so it's really "what directory did I start in"

21:49 fakedrake: hmm

21:49 allrighty then

21:50 so the repl is not like eshell then

21:55 llasram: In what way is a raven like a writing desk?

21:58 fakedrake: well eshell is sort of a repl for elisp, and ipython is an interpreter that can be used as a shell to some extent

21:58 i kind of assumed clojure repl would be something like that

22:00 llasram: That's fair

22:00 But the JVM is a strange beast

22:01 fakedrake: llasram: indeed it is

22:07 technomancy: fakedrake: it's more like M-x ielm than M-x eshell

22:08 I don't know anything that's like eshell

22:09 except erlang's interactive prompt has the same name, but that's about as far as the similarities go

22:09 hyPiRion: no, that's just erl

22:12 l1x: hey guys

22:13 how can i autocompile all the clj files in a src folder? it seems that lein uberjar only compiles the project.core (that is the :main in the project.clj)

22:14 llasram: l1x: First, why do you want to ahead-of-time compile the files?

22:16 l1x: llasram: i might be just a noob, so here is what i want to do: i have a project called project, i have project.namesapce1 namespace in src/project/function/namespace1.clj

22:17 i would like to have all of the namescpaces available in lein repl

22:17 makes sense?

22:17 llasram: Well, what you want makes sense, but there's some degree of mismatch

22:18 Compilation is a deployment optimization, and is only generally necessary if you're using `gen-class`

22:18 If you just want stuff in a REPL, you definitely shouldn't need to `compile`

22:18 If the paths you mentioned are exactly what you have, there's probably a mismatch between the namespace name and the path to find the associated file

22:19 The `project.namespace1` namespaces should be in a `project/namespace1.clj` file under a source path (default just `src`)

22:19 l1x: i see

22:20 so i cant really have a logical source code management when the db layer is in the db directory?

22:21 llasram: Well, you can have multiple `:source-paths` in your leiningen `project.clj`. But underneath the source path, the directory structure needs to match the namespace

22:21 l1x: or i can still do project.function.namespace1 and project/function/namespace1.clj?

22:21 llasram: that's fine

22:21 l1x: great

22:21 this is what i am going to do

22:22 llasram: Cool beans

22:22 l1x: thanks a million llasram

22:22 llasram: np

22:22 l1x: clj community <3

22:22 technomancy: l1x: you can set :init-ns in :repl-options of project.clj, and `lein repl` will start off with that ns loaded

22:22 so if you put a bunch of :requires in that ns it con be convenient

22:23 coventry: l1x: You can also the necessary (require)s in a file dev/user.clj in your project, and they will be in the repl's "user" namespace.

23:33 ddellacosta: anything that does filter + remove in the same function? Specifically, give me a list of the values that match and another that doesn't match a specific keyword value in a map? Probably using filter/remove is not the right strategy in this case.

23:33 seangrove: partition-by?

23:34 ddellacosta: seangrove: right, that is a good avenue to look down...thanks!

23:34 seangrove: ,(partition-by even? (range 0 10))

23:34 clojurebot: ((0) (1) (2) (3) (4) ...)

23:34 seangrove: Ah, no, that's wrong...

23:34 group-by?

23:34 ddellacosta: hmm, that's not was I was hoping for

23:34 yeah, I mean, it's definitely something in this family

23:35 yep, perfect

23:35 ,(group-by #(= (:a %) "foo") [{:a "foo"} {:a "bar"}])

23:35 clojurebot: {true [{:a "foo"}], false [{:a "bar"}]}

23:35 ddellacosta: seangrove: excellent, thanks again

23:36 seangrove: ddellacosta: No problem, I just looked at the coded where I used partition-by and I sort the collection first

23:36 ddellacosta: seangrove: ah, I see

23:42 bitemyapp: ddellacosta: comp?

23:42 ddellacosta: you could do it with reduce.

23:42 ddellacosta: bitemyapp: didn't try comp

23:43 bitemyapp: ,((comp (partial filter even?) (partial remove string?)) (range 10))

23:43 clojurebot: (0 2 4 6 8)

23:43 ddellacosta: bitemyapp: yeah, reduce would work too I guess. Lots of ways to do it. The thing I like about group-by is it fits what I'm trying to do conceptually perfectly, which is split a group apart based on a predicate though.

23:43 bitemyapp: ddellacosta: ^^

23:43 oh, okay, well if that works.

23:43 ddellacosta: bitemyapp: the thing is, comp is just giving me one set of results, isn't it? I need both the matches and non-matches

23:44 bitemyapp: which is why I was thinking of something in that family, but didn't quite know until seangrove suggested group-by

23:45 bitemyapp: ddellacosta: yeah when you said filter and remove I assumed that was literally what you wanted

23:45 ddellacosta: hmm, bummer that I can't use a boolean like a keyword with a hash though.

23:45 bitemyapp: it does sound like group-by is what you want

23:45 ddellacosta: bitemyapp: yeah, it's pretty perfect for this specific scenario.

23:45 bitemyapp: in general I think I use filter/remove too much actually

23:46 `cbp: :-o

23:46 ddellacosta: should start grabbing comp more off the bat, I'm less comfortable with it

23:46 seangrove: juxt?

23:46 clojurebot: juxt is the bestest option though if it doesn't weird you out

23:46 ddellacosta: haha

23:46 seangrove: I don't think juxt is appropriate, but it always seems to come up right about now

23:46 ddellacosta: yeah, I still feel like I don't know what the hell I'm doing when I use juxt

23:46 I really need to practice more

23:47 seangrove: There's always 4clojure

23:47 I'd like to see some of the medley stuff move into core

23:47 ddellacosta: seangrove: you know, I got through the first 50 or so when I started learning clojure, and haven't gone back

23:47 seangrove: Especially mapping a function over a map's keys/values and getting a modified map back

23:47 ddellacosta: seangrove: I really should--I've learned so much since then

23:47 seangrove: what's medley?

23:47 now my curiosity is piqued

23:48 ah, this? https://github.com/weavejester/medley

23:48 neat

23:49 oh, yeah, some awesome stuff there

23:49 dissoc-in seems like a no-brainer, for example

23:49 filter-keys/-vals too would be pretty natural to include in core methinks

23:49 neat

23:50 seangrove: Well, prismatic's plumbing has some similar functions

23:50 * ddellacosta adds medley to list of awesome libs by weavejester he is using

23:51 seangrove: ddellacosta: If you haven't started using dommy, well, now's a good time to look ;)

23:51 Thoroughly impressed with it

23:51 ddellacosta: seangrove: ah, man, I just finished porting so much stuff to domina.

23:51 `cbp: ,(let [m {:a 1 :b 2 :c 3 :d 4}] ((juxt :a (apply juxt (disj (set (keys m)) :a))) m))

23:51 clojurebot: [1 [3 2 4]]

23:51 ddellacosta: seangrove: that said, really not happy with it, I wish dommy had been more mature when I started

23:51 or rather, that I'd known about it

23:52 seangrove: ddellacosta: Probably a mechanical-ish transformation. But if domina works for you (it barely did for us), then there's no worries

23:52 ddellacosta: for example, hear the crickets chirping: https://github.com/levand/domina/issues/60

23:53 seangrove: it works, mostly...but the problem is, I think, that wrapping Google Closure is fundamentally problematic. It really uses a different paradigm.

23:53 seangrove: and domina doesn't make great choices at many points, AND the response from the dev team is painfully slow.

23:54 seangrove: ddellacosta: Well, dommy's approach seems much smarted to me anyway. Tradeoffs in both directions, but the precompile-everything-possible with a lovely api is great

23:54 ddellacosta: anyways, enough griping, I'll look into dommy.

23:54 seangrove: yeah, that sounds nice, and is the direction we're heading in anyways. Will definitely be investigating it further.

23:55 seangrove: ddellacosta: What company/product are you working on again?

23:56 bitemyapp: Saw you popup on the nunjuks hn thread, but selmer isn't client-side, right?

Logging service provided by n01se.net