#clojure log - Oct 26 2014

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

0:14 ghadishayban: man i went down the rabbit hole today

0:15 started hacking on clojure.lang.Range (CLJ-1515), decided to revive it as a deftype

0:15 deftype doesn't support java transient fields, so I added that to the compiler

0:16 then I rejiggered core.clj to load range after deftypes and protocols have been definied

0:16 and now it's time to see if it performs

0:24 amalloy: ghadishayban: what on earth did you need a transient field for in implementing Range?

0:25 anyway, just reimplementing clojure.lang.Range in clojure sounds like a dead end: the future is transducers

0:26 ghadishayban: amalloy: hash codes are supposed to be transient

0:26 amalloy: I don't know why, just regurgitating

0:27 this enables range to work better better with transducers

0:27 amalloy: i mean, it's clear why: you don't want to waste space on disk caching something that's easily recomputable

0:28 ghadishayban: say more words re: dead end?

0:28 not sure I follow you

0:30 amalloy: ghadishayban: i mean, it's not clear what you mean by reviving c.l.Range as a deftype. if you mean you ported the existing implementation to clojure: i don't see how that's useful. we already have c.l.Range, and it doesn't get used because rich changed his mind and did it in clojure

0:30 if you have instead some brand-new implementation that is based on reducers or transducers or something, then that could be progress, but i'm pretty sure it's already been done. i did Range as a reducer, and nobody wanted to merge it; i think someone has done it as a transducer already

0:31 ghadishayban: gosh you are hating so fast

0:32 there is existing work, tagged for 1.7 to revive c.l.Range (CLJ-1515)

0:32 Tim's current impl has a tiny downside, in that it has a 5x performance penalty for existing seq usages of range

0:33 that is because it doesn't use chunked seqs

0:33 I saw the Range ticket a while back, it is really nice, didn't realize it's yours.

0:33 kudos

0:34 I decided to do something similar but with Iterable & IReduce

0:34 as well as CollReduce (this duplication is slightly annoying)

0:35 amalloy: well, good luck to you. i'm glad to see CLJ-1515 looks like it might actually happen; when you opened with "i started hacking on c.l.Range" it sounded like some uninvited windmill-tilting, and i was trying to save you a bunch of wasted effort

0:35 my windmill-tilting was *invited* and still made no progress

0:35 ghadishayban: Range as a transducer doesn't make sense because a transducer isn't a source, but a transformation

0:35 yeah it may be wasted effort

0:36 trying to maintain existing seq usages and also reducible usages is a total PITA

0:37 personally I'd rather clojure.core.reducers/range

0:37 (that also implemented iterable)

0:38 oh yeah also being a java.util.List

0:38 bbloom: ghadishayban: why can't first/next/more/seq/etc from ISeq and ISeqable, as implemented on a Range object, just implement chunking?

0:38 ghadishayban: in core i mean

0:38 totally can

0:38 amalloy: ghadishayban: yeah, being j.u.List was the worst part by far

0:39 bbloom: ,(-> (range) class supers)

0:39 clojurebot: #{clojure.lang.Obj clojure.lang.Sequential clojure.lang.IPersistentCollection clojure.lang.IMeta java.io.Serializable ...}

0:39 bbloom: looking at the full list locally seems quite doable manually

0:39 ghadishayban: bbloom: waiting on Tim to see if he updates the patch

0:39 amalloy: bbloom: if you call next, it has to allocate an object; the point of chunking is to avoid that allocation

0:39 i don't see how you can "make next implement chunking"

0:40 ghadishayban: gimme a second to push up what I have

0:41 bbloom: amalloy: just saying that the result of next should itself be chunked, in case somebody does (map f (next (range) ....

0:41 amalloy: bbloom: for sure

0:42 bbloom: amalloy: if you make a RangeSeq object, that itself supports chunking, i see no reason not to use it for all Range methods that return seqs

0:42 ghadishayban: my patch doesn't account for someone doing (rest (range))

0:42 as in it falls back to the regular chunked-seq

0:43 bbloom: ghadishayban: do you have a RangeSeq object?

0:43 or an anon class or whatever

0:43 ghadishayban: although that could be improved. spent enough time reimplementing fucking grade school counting

0:43 bbloom: i'd just make a RangeSeq(start, stop, step) and return that from first/next/more

0:43 ghadishayban: bbloom: I delegate to the existing range seq impl

0:44 bbloom: now private as range-seq*

0:44 bbloom: sure ok

0:44 anyway, i'm pretty confident w/ a little elbow grease that patch can be a good perf win and get accepted

0:44 rritoch: What is the purpose of having both next and rest? They seem to return the same values and looking at their code one calls ISeq/next and the other ISeq/rest, but the ISeq interface doesn't document the difference between next and more.

0:45 ghadishayban: bbloom: yeah it should be possible to add chunking

0:45 bbloom: rritoch: evolution

0:45 ghadishayban: bbloom: though the one thing I add to it is Long arith, rather than Number

0:45 bbloom: rritoch: http://clojure.org/lazier

0:45 rritoch: very old page

0:46 rritoch: bbloom: Thanks, checking it now...

0:46 ghadishayban: https://github.com/ghadishayban/clojure/commit/906cd6ed4d7c624dc4e553373dabfd57550eeff2

0:47 quizme: hi, can somebody help me with a class loading problem? http://pastebin.com/PukYbX5e I'm really stuck.

0:47 ghadishayban: bbloom: amalloy: commit message covers it mostly. feedback would be awesome

0:48 bbloom: ghadishayban: sorry man, i've stared at too much code today. off to bed

0:49 maybe bug me later in the week :-)

0:49 ghadishayban: ha yeah grade school counting is so interesting though

0:52 amalloy: ghadishayban: i have range PTSD after clj-993. not much interest in reading through it, i'm afraid

0:53 ghadishayban: no worries.

0:53 totally understand the patch ptsd

0:54 justin_smith: ,((juxt rest next) [1]) ;; rritoch

0:54 clojurebot: [() nil]

0:54 justin_smith: they aren't always the same

0:56 rritoch: justing_smith: Thanks, that's a good example though I'm not sure I understand the reasoning behind this particular difference

0:56 ,(type (next '(1 2 3 4)))

0:56 clojurebot: clojure.lang.PersistentList

0:56 rritoch: ,(type (rest '(1 2 3 4)))

0:56 clojurebot: clojure.lang.PersistentList

0:57 rritoch: ,(type (rest (map identity '(1 2 3 4))))

0:57 clojurebot: clojure.lang.LazySeq

0:57 rritoch: ,(type (next (map identity '(1 2 3 4))))

0:57 clojurebot: clojure.lang.Cons

0:57 rritoch: Why would next be returning a cons?

0:58 justin_smith: rritoch: the difference is explained in detail in the article bbloom shared, next is about being lazier

0:58 ghadishayban: rritoch: ,(source map)

0:58 ,(source map)

0:58 clojurebot: Source not found\n

0:58 ghadishayban: map is introducing the cons

0:59 rritoch: ,(type (map identity '(1 2 3 4)))

0:59 clojurebot: clojure.lang.LazySeq

0:59 rritoch: I specifically used map just to get a lazyseq to see the difference as per the docs about lazyness

1:00 But if next is supposed to be lazier why is rest the one returning a lazyseq?

1:00 justin_smith: rritoch: look at the source of map, it has lazy seq wrapping cons

1:02 dopamean_: is there a way to have leiningen check a github repo for the source of a dependency ?

1:02 i wrote i library id like to use and its not on clojars or anything

1:03 justin_smith: dopamean_: you can use lein install to make it available locally, or lein push to put it on clojars

1:03 dopamean_: cool. thanks.

1:03 justin_smith: dopamean_: for super advanced usage there is also setting up your own maven repo

1:03 rritoch: justin_smith: Ok, I guess the better question is, why does seq unwrap a lazy sequence?

1:04 ,(type (lazy-seq (cons 1 '())))

1:04 clojurebot: clojure.lang.LazySeq

1:04 rritoch: ,(type (seq (lazy-seq (cons 1 '()))))

1:04 clojurebot: clojure.lang.Cons

1:05 rritoch: It would seem to me that rest is lazier since it maintains the lazy type.

1:06 justin_smith: rritoch: I don't know, and it may be that rest is lazier now, and next is doing what rest used to do and I got them mixed up

1:06 yeah, rest is lazier

1:06 the source of my confusion is that rest used to do what next does now iirc

1:08 rritoch: justin_smith: ok, so basically next is better to use in constructs where lazyness is harmful, such as filter functions which rely on bound variables that may not be still bound if no doall is called on them before leaving the binding?

1:08 justin_smith: But in cases where filter functions don't utilize bound variables, rest is bettee

1:09 err, better

1:09 justin_smith: rritoch: well, next is not eager

1:09 it's just slightly more eager

1:10 ,(do (rest (map println (iterate inc 0))) nil)

1:10 clojurebot: 0\n

1:10 justin_smith: ,(do (ext (map println (iterate inc 0))) nil)

1:11 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ext in this context, compiling:(NO_SOURCE_PATH:0:0)>

1:11 justin_smith: ,(do (next (map println (iterate inc 0))) nil)

1:11 clojurebot: 0\n1\n

1:11 justin_smith: it realizes 1 more element than rest does

1:16 rritoch: justin_smith: Hmm, that may actually be enough for me in most cases. I often am using (first (filter ....)) where I really only want the first result

1:17 justin_smith: Either way, thanks, I'll have to experiement with it a bit but at least I now have some grasp on the difference between the two.

1:19 TEttinger: I wonder if a standardized version of (first (filter ....)) called something like "search" would be a good idea

1:19 or even take-when

1:19 as a counterpart to take-while

1:21 justin_smith: gimme, as counterpart to get

1:22 ghadishayban: TEttinger: sometimes the predicate can be rewritten with some

1:22 TEttinger: right, I usually forget some

1:23 justin_smith: ,(some even? (range))

1:23 clojurebot: true

1:23 justin_smith: ,(some #(and (even? %) %) (range))

1:23 clojurebot: 0

1:23 ghadishayban: thing is some returns the result of the predicate

1:23 rather than the element that satisfied it

1:23 justin_smith: yeah, a version that just returns the thing would be handy

1:24 (though the workaround is not all that onerous)

1:24 ghadishayban: it can't be done.

1:24 ^ that's the batsignal for someone to prove me wrong

1:24 justin_smith: haha

1:26 * rritoch agrees with ghadishayban, and hands him a beer.

1:28 dysfun: is there a non-horrible way of automatically memoizing file contents at the point of use unless the file has been updated since last read?

1:28 every way i can think of would not count as 'non-horrible'

1:30 TEttinger: dysfun, sounds fairly OS-specific

1:31 dysfun: not really. i'm quite happy for it to hit the disk every time i call

1:31 but only to check metadata

1:31 justin_smith: dysfun: I made one in my spawning-grounds lib that is OS agnostic https://github.com/caribou/spawning-grounds

1:31 TEttinger: nice, justin_smith

1:31 dysfun: oh, *you're* the guy behind caribou

1:32 justin_smith: dysfun: just a hired hand

1:32 not the founder

1:32 TEttinger: is it guy or guys behind caribou?

1:32 dysfun: ah right

1:32 justin_smith: though I am the only one working on it now that we all got layed off

1:32 dysfun: i really wanted to like caribou

1:32 TEttinger: caribou looks good. what happened with layoffs?

1:32 justin_smith: dysfun: me too :(

1:33 TEttinger: the company got bigger, moved up to clients that are bigger, thus: have they own stack, their own devs, etc.

1:33 dysfun: the least-worst option i've found was luminus. but only because i used half of those things anyway

1:33 justin_smith: great for the company, bad for our attempts to use clojure

1:39 rritoch: So, I was reading through clojure.core docs last night, since I've missed so many critical functions, and ran into on additional conundrum, the seque function seems to be specifically designed to work with a BlockingQueue yet to my knowledge clojure doesn't have it's own construction function for making a BlockingQueue. Shouldn't there be some (blocking-queue [1 2 3]) like func?

1:42 I actually work with a blocking queue every day, and just use (BlockingQueue.) but it seems this seque may be a gateway to producing more "idiomatic" code for this usage case where there are multiple workers which not only do work, but generate work orders, along with the GUI generating work orders.

1:42 Or something like that, I'm too lazy to check the actual code right now.

1:44 Ok, just looked it up, I'm using LinkedBlockingQueue but it seems I could use the sequeue function on it.

1:50 justin_smith: rritoch: maybe you want clojure.lang.PersistentQueue/EMPTY

1:50 dysfun: i'd be inclined to use a PersistentQueue of promises to get blocking

1:54 rritoch: dysfun: I'm not sure that solution would work because I have no way of knowing ahead of time how many requests are going to be returned. The blockingqueue though has caused a lot of problems because they're blocking in agent send!'s so I've had to resort to polling since the application doesn't stop the agents when the agents ae shut down because they're blocking.

1:55 dysfun: heh

1:55 perhaps atom notifications?

1:56 justin_smith: core.async is a fun way to do workers on queues

1:57 dysfun: await-for looks handy

2:06 rritoch: dysfun: Actually, that await-for could make the code cleaner if we called await before shutdown-agents, as we could log the fact that we're still waiting for the agents to complete but it doesn't avoid this polling mess.

2:08 dysfun: Now if I could unblock on a atom notification that would clean up all of this as I am maintaining an atom that changes to "STOP" when these agents need to be stopped.

2:09 justin_smith: rritoch: in core.async this is done via alts! or alts!!

2:10 rritoch: justin_smith: I don't have the option of async processing

2:10 justin_smith: one channel will return a "stop everything" message, the other your result, and then you act on the first one that gives you a value

2:11 rritoch: not even bounded async with a timeout?

2:11 rritoch: justin_smith: I think I already mentioned this, but I tried to add asynchronous processing and the code was all removed by my boss.

2:11 justin_smith: oh, I did not see that

2:11 rritoch: It was a few days ago that I mentioned it

2:12 My work constraints are severe when dealing with code in common libraries, and this queue is in a common library.

2:14 I'm checking the code for agent now because if I could interrupt the agent, from a atom's notification, that would really clean things up

2:15 bodie_: anyone played much with clojurescript reactjs libs like Om? I'm just picking what to start in on and looking for input :)

2:15 dysfun: om is pretty cool

2:16 and it's been made really efficient too

2:16 it's faster than pure reactjs

2:17 bodie_: yeah it seems a little more featureful than the other cljs react options

2:17 from what I've seen anyway, which could be good or not

2:18 dysfun: you'll either love it or hate it, but if you love clojure, probably love it

2:18 bodie_: :D

2:19 if I hate it, I'll check myself before I wreck myself and take a look at Reagent

2:19 dysfun: be aware there's a reasonable learning curve because it's still fairly new and the docs aren't there yet

2:24 rritoch: It seems agent doesn't directly provide a means to interrupt the processes

2:25 But what if I call (.shutdownNow Agent/pooledExecutor) ? Per the docs that should be calling interrupt which would be enough to get out of a blocking request on the blockingqueue.

2:25 justin_smith: rritoch: in general, it's cleaner in the jvm to write code that should be interruptible so that it checks for interruptions - there is no generally clean way to interrupt the process in another thread

2:26 rritoch: there is also (shutdown-agents) if you are not using that already

2:27 oh, now I see you mentioned it already above

2:27 rritoch: justin_smith: I am, but shutdown-agents doesn't call interrupt, so it doesn't cause the blocking request to the queue to return.

2:29 dysfun: what you need there you see is transactions

2:29 or at least some way of indicating responsibility for the job

2:29 rabbitmq has some awkward acknowledgement dance

2:29 rritoch: There should probably be a shutdown-agents-now, function. I assume since pooledExecutor static property of agents isn't documented there's no guarantee that calling the shutdownNow directly will be comptaible with future versions of clojure though.

2:30 dysfun: but the idea is that a piece of code should take ownership of making sure data is in a consistent state when it's working with that data

2:31 so once you've taken it off the queue, you become responsible for either finishing it or saving state so it'll be picked back up when you restart

2:31 rritoch: dysfun: I understand that, but these are blocking because there is no data in the queue

2:33 dysfun: So these workers are simply waiting for work and haven't received anything to be reponsible for yet, but since shutdown-agents doesn't call interrupt, these workers hang forever unless I use a fairly CPU intensive polling implementation

2:33 dysfun: seems to me you could poll quite infrequently and it would be fine

2:33 have you investigated a back-off algorithm?

2:34 rritoch: dysfun: I'm polling at 22ms to ensure that to the end user it appears to be instant.

2:34 dysfun: right. so the idea was you'd poll at 22ms. if there was nothing for that say five times, you poll at 40ms. then 100, etc.

2:35 justin_smith: rritoch: if that's the case, what about adding logic that stops and shuts down if a nil comes down the queue? then part of shutdown can be putting nil onto each of the queues

2:35 dysfun: bonus: you can very easily construct a lazy list of the times and iterate through them

2:36 a nil sentinel value seems like an easy fix

2:36 rritoch: justin_smith: Now that is an awesome solution that we haven't considered

2:36 TEttinger: (inc justin_smith); again

2:36 lazybot: ⇒ 104

2:36 rritoch: justin_smith: I would just need to verify backwards compatibility by throwing a nil into the queue to see what the normal handling of nil does.

2:37 justin_smith: rritoch: fair enough - and if that is already a non-sto-case then you could use ::stop-drop-and-roll

2:37 or whatever

2:38 dysfun: :please-dont-accidentally-create-a-keyword-with-this-name-or-bad-things-will-happen

2:38 rritoch: Well, either way. I still think there should be a means of interrupting agents

2:38 justin_smith: dysfun: well that's what the extra : helps with :)

2:39 rritoch: But for this particular case putting nils, or some other "stop" instruction into the queue would solve the issue.

2:39 dysfun: ::ugly-hack-pretend-i-dont-exist :)

2:39 oh, you could namespace it

2:40 :queue-sentinel/SHUTDOWN

2:40 TEttinger: ,(keyword ": : : \u0000")

2:40 clojurebot: :: : :

2:40 TEttinger: better,

2:40 justin_smith: rritoch: I did some research not long ago on interrupting threads in the jvm from the outside, and in general the code should check (.isInterrupted (Thread/currentThread))

2:40 TEttinger: ,(keyword ":\u0000:")

2:40 clojurebot: ::

2:40 justin_smith: ,(.isInterrupted (Thread/currentThread))

2:40 clojurebot: false

2:40 justin_smith: dysfun: dude, that is what ::kw does

2:40 ,::kw

2:40 clojurebot: :sandbox/kw

2:41 dysfun: oh, right

2:41 * dysfun doesn't deal much with keywords these days because java interop

2:41 justin_smith: rritoch: that is to say, shutting down from the inside of the thread can be done cleanly and safely, but there is no such option from the outside

2:42 it's not a clojure limitation, but a jvm one

2:43 rritoch: justin_smith: In the case of a blockingqueue I believe it throws an interrupted exception and I could simply have the error handler for the agents ignore errors when in the "STOPPED" state.

2:44 Either way, this is the only case I've run into yet where agents are hanging, and the alternative of putting a "stop" instruction into the queue does solve the problem.

2:46 dysfun: hrm, now that SHA-1 is broken, what should we use to hash files to detect corruption SHA-256?

2:46 i suspect SHA-1 is probably 'good enough' for these purposes

2:49 justin_smith: dysfun: if your enemy is simple entropy, sha-1 should be good enough

2:49 but if you have reason to suspect tampering, then you need to work a bit harder

2:50 rritoch: SHA-256 will likely have its first collission within the next 10 years based on moores law, so if your dealing with a massively parallel application, using something like scrypt, while costly memory wise, would have a much longer lifeetime (about 30 years)

2:52 Another agent issue I've run into is the need to know if all agents are blocking

2:52 This again I've solved with polling

2:53 But if I do go with putting a stop into the queue, I'll still need to be able to test if all agents, other than self, are blocking, so the system can bugger-off (shutdown-agents) if the queue is empty and all agents have completed their work.

2:56 If you check out the new Xeon/PHI coprocessors you'll see moore's law is effectivly still holding, it's just taken on a new dimension. Once quantum processing is viable moore's law will again be accurate, as-is.

2:57 TEttinger: Xeon/PHI, eh?

2:57 rritoch: Yeah, they're pushing out about 3 teraflops

2:57 Raynes: TEttinger: Motherf*cker. I've been pinging you for two weeks.

2:58 We gonna have to take this outside?

2:59 rritoch: Right now I get about 4 teraflops (max) from my 2X 280X radion processors which are crossfired, though under massivly parallel code they'll burn up quickly at 4 teraflops if you don't reduce the clock-speed.

3:00 dysfun: justin_smith: well yes, it's for tampering, but given the rigid format of the file, you'd have to work quite hard, and honestly, it seems unlikely

3:00 arrdem: what are we breaking out the PHIs for?

3:00 TEttinger: Raynes, hey

3:00 rritoch: R9 280X is about 2 years old, so for the most part the law is holding from a processing speed standpoint, but the law specifically is based on the size of transsssistors

3:00 Raynes: TEttinger: Does you has a bot running on quakenet in a rougelike channel that periodically posts to refheap?

3:00 TEttinger: yes

3:01 Raynes: Okay.

3:01 TEttinger: why?

3:01 clojurebot: why is the ram gone

3:01 rritoch: This is related to my comment that SHA-256 will probably have a collission within the next 10 years.

3:01 Raynes: Just trying to confirm it's you. I originally thought it was spam because some of it was rape jokes and other unsavory shit.

3:01 But it's a totally reasonable usage of refheap, so ++ :P

3:01 TEttinger: yeah we try to quotegrab people saying bad things so they realize it's on the web forever

3:02 Raynes: Badass.

3:02 TEttinger: it's steadily improved the channel

3:02 arrdem: ballin

3:02 Raynes: That's what I dreamed refheap would be used for.

3:02 dysfun: you've written a bot to try and shame people into being decent?

3:02 arrdem: I'll bet it has...

3:02 Raynes: You're a scholar and a gentleman.

3:02 rritoch: I was grossly disappointed by these R9's though since they run so damn hot, so I'm in no hurry to rush out and try the Xeon/PHI's

3:02 Raynes: amalloy: ^ The mystery is solved.

3:02 TEttinger: dysfun, no I wrote it to replace the previous bot that left

3:03 rritoch: Either way, 2 teraflops with 4 teraflop "spikes" is more than enough for anything I need to do.

3:03 TEttinger: there are still unsavory sorts in the channel, but they're getting less attention

3:03 rritoch: But theses PHI's having intel architecture do have my attention

3:03 TEttinger: nihilanth in particular has become a veritable computer business professional

3:04 dysfun: because when i think of gaming, i immediately think of professionalism

3:04 rritoch: I haven't seen any documentation on them yet though, but if they will run JVM/Clojure I may be forced to buy one once I know they're not burning up.

3:05 TEttinger: rritoch: the $1700 price tag seems quite heavy for such early tech

3:05 then again, if they do take off, wowza

3:05 arrdem: table top gaming is very professional until the dice start rolling :P

3:05 rritoch: TEttinger: That isn't much more than what i paid for the 2X 280X's

3:05 dysfun: rritoch: how awesome would it be to have one under your desk and just send work off to it as needed?

3:06 justin_smith: dysfun: bonus - also a foot-warmer

3:06 rritoch: Well, right now with GPU's you really need to write separate code, which is a lot of overhead, if these PHI's will run JVM it would be worth the investment.

3:06 dysfun: back when i had a dog, he was a pretty good foot-warmer too

3:07 rritoch: But as I said, I still haven't located any documentation for it so I don't know what it can or can't do.

3:07 dysfun: but i'm thinking something about the size of the new mac pro with all the cpu resource you'd ever need in it

3:07 Raynes: TEttinger: Could you give it an actual user account though?

3:07 TEttinger: if you could get hardware virtualization support for those Phis, create 57 VMs on one machine, hot diggity...

3:07 uh, sure, how would I do that with a lazybot?

3:08 * Raynes ponders if lazybot even does it

3:08 Raynes: &(range 1000)

3:08 lazybot: ⇒ (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ... https://www.refheap.com/92317


3:08 rritoch: TEttinger: Better yet, rewriting the leiningen compile process to use separate JVM's for each file and we'd have nearly instant compiles *evilgrin*

3:08 Raynes: TEttinger: You can pass an API Key. I believe the docs show you how to do that.

3:09 TEttinger: I haven't modified that part of lazybot, I'll take a look

3:09 dysfun: rritoch: did someone say "worker thread problem waiting to happen" ? :)

3:09 Raynes: TEttinger: Wait, there's no plugin that captures bad things and posts them to refheap

3:09 You had to write that yourself lol.

3:10 TEttinger: I use the existing refheap paste of the clojure eval

3:10 rritoch: dysfun: Yeah, again why I think agents should have a shutdown-agents-now, that would be very useful when dealing with coprocessors which are known to hang and need to be reset occasionally

3:10 TEttinger: and when I did it, it was... a year ago or more

3:10 Raynes: Oh

3:10 I see

3:11 * Raynes doesn't remember abstracting this.

3:11 dysfun: rritoch: not everything about the jvm is sweetness and light.

3:11 Raynes: TEttinger: I'll add a tthing.

3:11 thing*

3:11 TEttinger: Raynes, I mentioned you in conversation today on the topic of "age doesn't really matter for ability to learn to code" (someone was baffled that a 9-year-old son of a friend was writing Java plugins for Minecraft)

3:12 Raynes: <3

3:12 I started at like 14 though.

3:12 dysfun: the internet has gotten a lot more helpful since i started programming

3:12 TEttinger: yeah, I guessed around then

3:12 * dysfun started at 10

3:12 TEttinger: minecraft is definitely better documented for kids and total beginners than clojure was at the very start, I would think

3:13 I also mentioned the Oak quote about "Java is designed with average programmers in mind"

3:15 rpaulo: I dislike that generalism about programming languages

3:16 dysfun: i don't think that's subjective. it was designed to ensure a certain type of safety that the average programmer may find helpful

3:16 rpaulo: if a programming language makes you think less about concurrency issues, would it be fair to say "designed with average programmers in mind"?

3:16 TEttinger: rpaulo, well it was the author of the language that became java who said it...

3:16 it was on his mind, certainly

3:16 dysfun: you don't design java if you're looking to implement something like clojure

3:16 rpaulo: yes, but it needs context and the context is in comparison to C

3:17 TEttinger: although they did nab one of the scheme designers to do java's generics, IIRC

3:17 rpaulo: these days I suppose it's harder to say that about java

3:17 TEttinger: yeah, java is good for beginners because of the wealth of resources, but the same could be said for C#

3:17 dysfun: because they've added so much to the language?

3:18 i don't think java is that good for beginners. it's huge

3:19 the reason i like clojure and i don't like java is that clojure is actually a reasonably small language to do most things

3:19 it only gets sketchy where java gets involved imo

3:20 TEttinger: tbh, java wasn't a bad language for me to learn "real techniques" in. I had had some decent instruction in old-style C++ and C before that, but nothing about how to really develop in those languages (using an IDE, using existing APIs, reading docs, etc.)

3:21 dysfun: this might sound a little bit bizarre, but i actually prefer c docs to javadoc and c++ docs. it reads a lot easier, even if it's generally ugly to look at

3:21 TEttinger: clojure would be overwhelming at the start for me, even though it comes very smoothly now

3:21 Renato_Ferreira: for kids, something like python or even Scratch is the way to go. for older beginners lisps in general are nice and many still learn scheme, and I'd say that learning C before Java is highly desirable

3:21 TEttinger: (doc map)

3:21 clojurebot: "([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments. Returns a transducer when no collection is provided."

3:22 dysfun: yeah, but when you learned clojure, you already knew other languages that suggest OO approaches to you

3:22 TEttinger: dysfun, actually I had learned a bit of haskell first

3:22 dysfun: i'm teaching a friend clojure tomorrow. he's never programmed before. this should be interesting

3:22 TEttinger: dysfun, you may need to start with just "how to run leiningen"

3:23 rpaulo: dysfun: hmm, interesting. I mentioned clojure to a friend who knows a bit about web programming and he found the concept of functional languages interesting. He's has a physics major, though

3:23 dysfun: yup

3:23 TEttinger: and before that, "this is the terminal, use cd to change directory"

3:23 rritoch: dysfun: That brings up an issue I've been thinkging a lot about recently, It would be good if the (. function could be unbound or rebound to create a purely clojure environment which has no direct access to Java other than via existing functions. Since . seems to be a special form though I don't see any potential for doing it.

3:23 dysfun: i have started to use lighttable myself this weekend so i'll be better prepared to use it with him tomorrow, because i don't fancy teaching him emacs as well

3:23 rpaulo: dysfun: he found it interesting, but I don't think he followed up on it

3:24 TEttinger: dysfun, yeah lighttable is great, when you aren't using limited thread things like swing or LWJGL

3:24 Renato_Ferreira: is it worth to use lighttable instead of sublime?

3:24 TEttinger: yes.

3:24 dysfun: rpaulo: the more i program clojure, the more i regret taking all of those OO programming jobs when I should have been programming lisp (which i've been doing in my spare time for about the last 7 years)

3:25 TEttinger: I personally use NightCode because I can't effectively use the instarepl in LightTable with an OpenGL game

3:25 dysfun: TEttinger: he wants to build a webapp. and have you experienced the horror of javafx and nrepl yet? that was tedious to work around

3:26 TEttinger: I'm not going near JavaFX, it looks like a nightmare of meat and clowns

3:26 dysfun: well i got annoyed with it when i realised the webkit control made the DOM read-only and you basically need to instantiate a new webview to have two 'pages' in memory at the same time

3:26 well, if you're going to swap one back in, anyway

3:26 TEttinger: geez...

3:27 dysfun: by that time i'd spent half a week figuring out how to make it all work together

3:27 rritoch: Have any of you tried libGDX via clojure? That is the direction I'm considering heading since JavaFX is still bug-soup.

3:27 TEttinger: rritoch, yes, I use it

3:27 play-clj is an excellent binding

3:28 libgdx is highly reliable at this point, though updating is occasionally a hassle

3:30 dysfun: i think most of my problem with lighttable at this point is that i haven't mapped a lot of keybindings i use in emacs

3:30 rritoch: Cool, I only found it recently and haven't yet tried it, but it seems to be much more advanced than JavaFX so if it is also more stable than it is probably the best solution for a modern GUI.

3:30 vmarcinko: hello all, just need a confirmation - it's impossible to add metadata to dispatched multimethod fn (defined via defmethod)? Similarly, I cannot construct defmethod fn value dynamically?

3:30 since it doesnt have syntax such as

3:31 (defmethod mymulti :somevalue (fn [..] ...))

3:31 Renato_Ferreira: rritoch: I have only used it with Java so far, but on the forums there's a pretty popular game made with clojure

3:31 vmarcinko: but (defmethod mymulti :somevalue [...] ...))

3:32 Renato_Ferreira: i think it's called Bounce Away

3:34 rritoch: Well, it will be awhile before I get to the point of adding a GUI to my systems, I just recently realized that the MVC platform I built isn't thread safe so I need to resolve that before I add on a GUI.

3:35 TEttinger: rritoch, yeah libgdx has something called scene2d.ui that's quite good once you figure out how to make custom skins

3:35 rritoch: Originally the platform was creating separate instances of the models views and controllers for each dispatching thread, but that fell apart when I added OSGi support which published them as services.

3:36 What I've ended up with is a giant mess, but once I clean up that mess, I hope to implement libGDX as a OSGi bundle.

3:36 TEttinger: dayumn!

3:37 justin_smith: libGDX as an OSGi bundle really sounds like another mess waiting to happen

3:37 TEttinger: you should ask on #libgdx about that, it's a little less active now but there are devs available a bit earlier in the day who could give pointers

3:37 libgdx currently uses gradle with maven artifacts to distribute

3:37 it has native code as well

3:38 rritoch: justin_smith: which is exactly why I'm waiting to add libGDX support, having two giant messes to deal with concurrently would be nearly impossible.

3:39 TEttinger: when they updated to 1.0.0, they switched the build system to gradle when you set up a project. most people had no idea how to use gradle, and the #libgdx channel for roughly 3 weeks was almost nonstop "how does gradle work"

3:39 rritoch: But I want the GUI pluggable so as new/better GUI technologies emerge, the old ones can be unplugged without being tied to the core functionality.

3:40 TEttinger: good idea. libgdx itself uses a lot of abstractions to better support touch-based UIs on android

3:40 (you can treat a touch like a mouse click with no hover)

3:56 rritoch: Is there an easy way to catenate the columns of 2 lists? ex. (somefunc '(("A" "B" "C") ("a" "b" "c"))) => ("Aa" "Bb" "Cc")

3:58 I just found some code where I do this manually via nested loops, which I wrote a long time ago, but it is really bad code.

3:59 I'm thinking this must be an ideal case for zipmap

4:00 Raynes: &(apply map str '(("A" "B" "C") ("a" "b" "c")))

4:00 lazybot: ⇒ ("Aa" "Bb" "Cc")

4:01 rritoch: Ok that is clearly awesome

4:02 Raynes: Thanks.

4:02 Raynes: 8^)

4:27 dysfun: the docs for midje suggest that to strip the tests out of the build, i can bind false to a var during a build. my question is how can i do that?

4:33 borkdude: has anyone ever made an animation or visualization of the shared tree structure of persistent data structures in a small program?

4:37 zoldar: dysfun: if you keep the typical directory layout in the project - tests under "./test/" or "./src/main/clojure", and code under "./src" or "./src/test/clojure" - tests should be excluded from the actual (production) build

4:38 dysfun: the approach with var would be needed if code and tests were mixed together in the same directory

4:39 dysfun: yes, that's exactly what i want to do

4:39 zoldar: ah

4:40 dysfun: so right now i've built some macros that deal with it by generating nil where the tests would go if we're building for production (detected by checking environment)

4:40 but it's a fugly solution and midje documents this variable you can bind but doesn't say how

4:40 zoldar: dysfun: maybe this will help: https://groups.google.com/forum/#!topic/clojure/mJBRPQct9x4 - last answer by Phil

4:41 ouch, even this didn't work, just read rest of the answer myself

4:42 dysfun: i found that *load-tests* is the comparable clojure.test variable, but i haven't seen a means to setting that either

4:43 TEttinger: (inc Raynes); for good measure

4:43 lazybot: ⇒ 52

4:43 dysfun: brilliant

4:43 i'm just going to stick with my macros

4:43 llasram: dysfun: Are you using Leiningen?

4:44 TEttinger: borkdude, I saw one in an explanation of them as part of a talk someone gave... no idea where it was

4:44 dysfun: yes, i'm using leiningen

4:44 borkdude: TEttinger I've seen the article of hyPiRion. But maybe someone made a "live" visualization of in memor instances

4:45 TEttinger: hyPiRion: do you still have the sources used to generate the images in that talk, if there were any?

4:45 llasram: dysfun: You might be able to use https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L251-L256

4:46 Although that may only work for vars the core Clojure runtime defines...

4:46 dysfun: which this isn't

4:47 llasram: Right

4:48 dysfun: these are my fugly macros: https://www.refheap.com/92321

4:49 use is basically just stick (dev-prelude) and an import at the top of your files where you want to use inline testing. but it's not very nice

4:50 llasram: dysfun: If you have a core "configuration" type namespace,

4:51 you could do the same sort of "environment" detection there and `alter-var-root` the relevant var(s)

4:51 dysfun: i'm not convinced that's any better

4:51 it's less easily reusable

4:51 llasram: Really? It could be a tiny lib you just depend on in every namespace

4:52 So it's a bit of out-of-project code, with only the `require`ment as repetition

4:52 dysfun: i.e. i'd be able to get rid of the macro invocation at the top level

4:54 llasram: And the per-ns definition of the `nil-macro`s

4:54 dysfun: okay, i'll have a look at that now. thanks.

4:55 hrm. can i exclude midje during production build through lein and still use ns/:require to include it?

4:55 llasram: Er, no

4:56 This approach means you'd be depending on it. Otherwise the vars wouldn't exist to set.

4:56 dysfun: hrm. that's a different kind of evil

4:57 on the other hand, it's not that big and disk and bandwidth are cheap

4:57 actually, there's another approach

4:57 llasram: Or you could always have out-of-line tests like a normal person ;-)

4:58 dysfun: if i create a midje-dummy package which just has a single clojure file with a namespace and that variable, then i can change deps with leiningen's environment stuff

4:58 so i'm depending on something much smaller in production

4:59 llasram: Yeah, you could do that... It seems unexpected that you'd need to

4:59 Does marick document how he does in-line tests?

4:59 I thought that he dogfooded that feature

4:59 dysfun: only that i should bind a specific variable

5:00 llasram: Seems simplest to just do it however he does, or maybe communicate with him and e.g. pitch the midje-dummy approach

5:00 dysfun: personally i'm thinking that he should just detect the environment from leiningen

5:01 piranha: hi all. So I have a ThreadPool executor, which runs my tasks. And I can have same task scheduled to run few times in a row. I would like to wait for the last one - i.e. only run it if there was 2 seconds without any activity since last one. What do I use for this?

5:01 llasram: It seems relatively benign here, although in my experience that way ultimately leads only to madness and death

5:01 dysfun: heh

5:02 llasram: Just because in Clojure you'll use the same REPL to do purely "dev" stuff, but you'd like to pull some data from the "production" database, to then include in the "test"-mode tests you run. All in the same process

5:03 dysfun: this being an open source project that deals in PII, i don't think so :)

5:03 llasram: dysfun: fair enough

5:03 piranha: not quite following. Can you be more concrete?

5:03 dysfun: how fortunate to skip that particular variant of hell

5:04 piranha: llasram: I do something when Dropbox notifies my webhook. And Dropbox can send a lot of notifications when user changes few files in a row (or a single file few times). I need to run my task only once (multiple runs conflict with each other). I can't decide on a way how to solve that. :)

5:05 right now I'm using FixedThreadPool, which seemed as a simplest way

5:05 but it seems I have to build some locks or maybe use a separate library...

5:05 dysfun: this is actually the perfect use of a lock

5:06 piranha: yeah, but the thing is that I need to wait until latest notification

5:06 do I just sleep in my thread? :\

5:06 dysfun: that was the question i was just typing :)

5:06 piranha: :-))

5:06 llasram: piranha: Use a Clojure agent

5:06 piranha: hm!

5:06 never used them, they are not present in cljs and I'm mostly doing that :)

5:06 thanks, I'll look at that

5:07 are they like ThreadPool as well? :)

5:07 dysfun: agents are allocated from a thread pool

5:07 llasram: piranha: Clojure agents provide uncoordinated serialized access to a piece of state

5:07 You can queue up any number of operations against the state, which then run and update it one-at-a-time

5:08 piranha: llasram: hmm... can I tell them to run just the last one?

5:08 I don't really need all the intermediate results...

5:08 and it's going to be making a lot of queries against dropbox api

5:10 maybe it's better to use http://clojurequartz.info/ in the end?

5:11 it seems their jobs have keys and I guess if you supply same job few times last one is going to win

5:13 dysfun: an atom and a map seems like a simple solution

5:14 you'll r

5:14 un at most one extra job in the time it takes to run a job

5:14 llasram: Yeah, it seems like you want effectively just producer/consumer with the consumer taking the batch of all available messages whenever it runs

5:15 I don't think there's a most-obvious way to do that in Clojure, but a ref or atom + agent comes close, especially if the agent represents an actual identity in your program

5:16 piranha: hm

5:17 ok, I'll experiment a bit then

5:18 borkdude: is there something like difform for clojurescript?

5:22 SagiCZ1: can i get class object just from the class name as in java's "classname.class" ?

5:29 borkdude: SagiCZ1 just the class name gives the class object, like java.util.Date

5:29 (let [class-obj java.util.Date] ...)

5:32 SagiCZ1: borkdude: do i have to use fully qualified names?

5:32 borkdude: SagiCZ1 only if you have not imported them

5:34 SagiCZ1: thank you

5:43 piranha: llasram: regarding agents: what would I use their state for? :)

5:43 i.e. I'm not exactly sure how to model my jobs, they are for side-effects only

5:48 dysfun: you use the piece of state to represent the identity of eg. a file

5:49 piranha: hmm

5:49 dysfun: so an agent becomes representative of that file

5:49 piranha: so I have to have like hundreds agents?

5:49 dysfun: ergo the serialisation happens on a per file basis

5:49 agents aren't particularly heavy

5:49 they're only running when something has to do something

5:50 piranha: so maybe I should have an atom of agents?

5:50 where I add new agents when I have to download new stuff

5:51 and agents themselves then will remove from there when they are done?

5:51 or is this bad idea? :)

5:51 dysfun: hang on, you shouldn't do i/o in agents

5:51 piranha: hm, where do I do i/o?

5:52 dysfun: you could use a future with an agent

5:53 hrm, i'd have to think

5:54 piranha: heh, that sounded like a quite simple thing to me initially, and now it seems like it is not :)

5:56 dysfun: no, rereading the clojure documentation, i'm wrong. io is fine in agents, but you'll want to use send-off

5:59 SagiCZ1: how can i programatically acheive the same thing as is "load file in repl" ?

5:59 dysfun: you're going to have to expand on that

6:02 SagiCZ1: ok, i have some defmethods defined in separate file than their associated defmulti.. i can require the namespace with the defmulti and it loads the file correctly but it doesnt load any of the namespaces with defmethod, how can i force them to load as well? for now i have to manually load the file with defmethod in repl

6:03 dysfun: you can't do that. but you can require that namespace in your defmulti file and then (def foo other-ns/foo) for them

6:03 llasram: piranha: It's be a bit of an abuse of agents. This problem isn't really about any of the things Clojure does well. A thread(pool) + queue probably is the simplest afterall

6:04 dysfun: or at least that *might* work

6:05 but it'd probably be easier just to include the defmulti file from the defmethod file

6:05 possibly reexporting

6:05 llasram: I think their problem is the other way around

6:05 SagiCZ1: There isn't any magic. You just `require` the implementation namespaces somewhere

6:06 e.g. your entry-point namespace should `require` all the implementation namespaces you'll need

6:06 SagiCZ1: yeah the defmulti file could require all the defmethods right

6:07 llasram: Well, you probably shouldn't do that

6:07 The implementation namespaces depend on the interface namespace, so that would introduce a circular dependency

6:07 But you can have yet another namespace which requires all of them

6:08 SagiCZ1: llasram: mm.. thats not very pretty

6:09 llasram: I'm not sure what else you'd want

6:09 In OO languages you don't expect loading a parent class to load every subclass that's defined anywhere else ever

6:09 Pretty much the same deal here

6:10 SagiCZ1: well there is one namespace with multiple defmultis.. and multiple files which group the implementations of the defmulti via defmethods

6:10 so when i add a new file with new implementations, i should require it from the entry-point namespace right?

6:11 llasram: Yes

6:12 SagiCZ1: llasram: ok and is there a way to require all namespaces which start with com.example.* or do i have to list them all?

6:12 llasram: You *could* do something where you enumerate resource paths starting with a certain prefix then load all the corresponding namespaces

6:13 It'd be fiddly though

6:14 SagiCZ1: and the question above?

6:14 llasram: I pre-answered it -- they're the same thing

6:15 SagiCZ1: and can i require it but not refer any symbols?

6:15 llasram: I'm afraid I don't follow

6:15 SagiCZ1: well all it takes now is to tell my editor to load the file in repl.. thats not the same as what require does

6:16 llasram: Um. Yes it is

6:16 (doc require)

6:16 clojurebot: "([& args]); Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly. Libs A 'lib' is a named set of resources in classpath whose contents define a library of

6:16 llasram: (doc load)

6:16 clojurebot: "([& paths]); Loads Clojure code from resources in classpath. A path is interpreted as classpath-relative if it begins with a slash or relative to the root directory for the current namespace otherwise."

6:16 SagiCZ1: oh.. i apologize

6:17 llasram: ~guards

6:17 clojurebot: SEIZE HIM!

6:17 SagiCZ1: so my main entry function could get a list of the namespaces (implementations) that it needs to require and just call require on each one

6:17 llasram: If you've got a large number of them you want to be always loaded, then that seems like a not-unreasonable solution

6:18 SagiCZ1: there could be about 20-30 of them

6:21 llasram: OOC why some many?

6:21 s,some,so,

6:22 SagiCZ1: the defmulti is called update.. and the thirty implementations represent thirty different ways to update something

6:22 im not sure if i should separate them into different namespaces

6:23 llasram: `update` a datastructure, like `update-in`?

6:24 SagiCZ1: yeah

6:24 more like assoc

6:26 is that a bad design idea?

6:29 llasram: Well, depends on why you need it :-)

6:29 There's certainly precedence in e.g. Common Lisp

6:30 And ClojureScript implements most such core operations in terms of protocols, so they are extensible to other datastructures which have near-enough semantics

6:31 SagiCZ1: yeah well my decision was driven by the fact that each of the implementations will be quite long and complicated and there is no way i could stuff them all into one namespace, presumably the one that defines the defmulti

6:32 llasram: What are the actual things you are implementing this for?

6:36 SagiCZ1: trading strategies, the core entry-point has a list of all strategies and calls update on each one, the update gets dispatched according to the type of strategy

6:37 piranha: llasram: dysfun: I tried to invent something simple and small, but in the end decided it's not worth the time, and used immutant.scheduling, which works fantastically :)

6:38 llasram: SagiCZ1: Ahhh, ok. That makes sense.

6:38 piranha: cool beans

6:39 SagiCZ1: llasram: good to hear, thanks for help

6:39 llasram: np and good luck!

7:00 otfrom: ,(= {:foo 0.1} {:bar 0.1})

7:00 clojurebot: false

7:00 otfrom: that is not what I expected

7:00 ,(= [0.1 0.2] [0.1 0.2])

7:00 clojurebot: true

7:00 otfrom: ,(= ["foo" 0.1] ["bar" 0.1])

7:00 clojurebot: false

7:01 otfrom: hmm... googling for this is going to be hard. Any suggestions?

7:01 SagiCZ1: whats the issue?

7:02 how could the map be the same when they have different keys?

7:03 ,(= (map values [{:foo 0.1} {:bar 0.1}]))

7:03 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: values in this context, compiling:(NO_SOURCE_PATH:0:0)>

7:03 SagiCZ1: ,(= (map vals [{:foo 0.1} {:bar 0.1}]))

7:03 clojurebot: true

7:03 SagiCZ1: there u go

7:05 hyPiRion: TEttinger: I don't have animation, but I certainly have visualisation. It's in C though: https://github.com/hyPiRion/persistencia/tree/master/persistent-vector

7:05 But if there's interest, I can probably make something for Clojure.

7:05 TEttinger: (inc hyPiRion)

7:05 lazybot: ⇒ 53

7:06 TEttinger: that's neat

7:06 otfrom: sorry, I should go back to sleep really.

7:06 * otfrom facepalm

7:06 TEttinger: borkdude, any interest?

7:07 borkdude: yeah :)

7:08 I was thinking something in ClojureSCript with React

7:09 if I had more time on my hands I would try it myself, but not so in the coming few weeks

7:10 hyPiRion: I really want to make something to generate animations, showing how each function on a persistent vector works. I've yet to find something à la graphviz with animations for the browser.

7:11 If not, I'd have to learn tree layout algorithms and how to draw in the browser.

7:13 borkdude: hyPiRion could also keep it simple and just render a png and show that

7:13 hyPiRion: yeah, that'd work too

7:14 borkdude: svg

7:14 SagiCZ1: hyPiRion: if you think about drawing in browser, checkout html5 and svg

7:15 borkdude: hmm https://code.google.com/p/canviz/

7:23 rritoch: Under windows is there a hotkey to kill a repl command that's in an infinite loop?

7:25 I'm trying to see if there's any advantage to seque vs (future (dorun ...)) and ctrl-c won't stop a (repeatedly #(or 5))

7:25 Amazingly it has maxxed all my cores also

7:26 Anyhow, I just killed the shell

7:27 borkdude: ctrl-d maybe? dunno

7:27 rritoch: borkdude, thanks I'll try that next time

7:33 Is there a bug in seque? When I ran (def a (seque 5 (repeatedly #(or (println ".") 5)))) it output 6 dots, when I expected 5?

7:37 borkdude: ctrl-d didn't work either, but anyhow

7:40 Here's an example that simply doesn't make sense to me

7:41 ,(let [a (atom 0) b (seque 5 (repeatedly #(swap! a inc)))] @a)

7:41 clojurebot: 0

7:41 rritoch: Hmm

7:41 In mine it returned 7

7:42 ,(let [a (atom 0) b (seque 5 (repeatedly #(swap! a inc)))] (Thread/sleep 500) @a)

7:42 clojurebot: 0

7:43 rritoch: Very odd, but I get 7 every time locally as long as I sleep

7:45 llasram: rritoch: seque is pretty weird and old. I've never seen it used in "real" code myself

7:47 rritoch: Ok, well either way it seems insanely broken, even with a take 500 I'm still getting 7 as a result

7:47 ,(let [a (atom 0) b (seque 5 (repeatedly #(swap! a inc)))] (take 500 b) (Thread/sleep 500) @a)

7:47 clojurebot: 0

7:51 rritoch: ,(let [a (atom 0) b (repeatedly #(swap! a inc))] (future (dorun 500 b)) (Thread/sleep 500) @a)

7:51 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

7:51 llasram: Maybe lazybot allows futures... do not recall

7:52 &@(future :maybe?)

7:52 lazybot: java.lang.SecurityException: You tripped the alarm! future-call is bad!

7:52 llasram: nope

7:52 Too dangerous

7:52 rritoch: Well, either way, ^^^ returns 501 locally, which is much closer to what I expected

7:53 But dorun is still running 1 too many times

7:55 llasram: rritoch: It's a bit counter-intuitive, but `dorun` notes that it forces the "successive nexts"

7:55 rritoch: Actually, I guess it matches the docs, but doesn't make sense

7:55 llasram: OTOH, using lazy-seqs for side-effects is generally a bad idea

7:56 What's your ultimate goal?

7:56 rritoch: Yeah, I'm just doing it for testing purposes to see if there is any benefit to seque vs running dorun in a future

7:56 seque seems to use an agent to fill the queue so fundamentally it's similar

7:56 llasram: Sure, but what's your goal then?

7:57 rritoch: At the moment, just to improve my clojure coding skills :)

7:57 There were a lot of functions in clojure.core that I wasn't familiar with

7:57 llasram: Ah

7:59 rritoch: I guess seque may still be useful if you pass in your own linkblockingqueue, but these with-side-effect tests has me pondering if/how it actually functions.

8:00 llasram: I really don't think it is useful, honestly

8:01 Between directly accessing the j.u.c APIs and core.async, seque just seems error-prone and weird

8:05 mi6x3m: hey clojure, is it a good idea to use eval in macros to evaluate forms in the context of let bindings?

8:05 like for instance I have something similar

8:05 (let [x 5] (first (lazy-seq (println x))))

8:05 llasram: mi6x3m: it is pretty much the opposite of a good idea

8:05 In fact, it is not actually possible, if I understand you correct

8:06 *correctly

8:06 mi6x3m: well the idea would be to eval println x in the context of x = 5 in this case

8:06 llasram: Yes, but the identifier 'x' is only bound to the value '5' at run-time. At macro-expansion time all you have is that there is an in-scope local named 'x'

8:07 mi6x3m: llasram: ignore it's a macro for a moment

8:07 let's concnrete on the upper example

8:07 I want 5 to be printed

8:07 llasram: mi6x3m: Then how is that different from what the compiler does anyway?

8:08 mi6x3m: llasram: well I thought the lazy-seq won't be touched until run time

8:09 actually it won't indeed

8:09 but when it's evaluated it's not considering the bindings

8:09 , (let [x 5] (first (lazy-seq (println x))))

8:09 clojurebot: 5\n

8:10 mi6x3m: what

8:10 Bronsa: mi6x3m: println returns nil

8:10 llasram: What did you expect to happen?

8:10 Bronsa: ,(let [x 5] (first (lazy-seq (doto x println))))

8:10 clojurebot: 5\n#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

8:10 Bronsa: ^

8:10 mi6x3m: nevermind, it works correctly, I was confused by the nil println returns

8:10 lol

8:11 thanks Bronsa

8:14 rritoch: In relation to mi6x3m's question. What if your dealing with dynamically bound variables, will a ((bound-fn ...)) expose bound variables to lazy sequences?

8:14 llasram: rritoch: If I understand your question correctly, then yes -- that's what `bound-fn` is for

8:14 mi6x3m: rritoch: should I guess, there's not much other context imaginable :)

8:15 rritoch: ex: instead of (doall (filter my-var-dep-fn '(1 2 3 4)) using (filter (bound-fn my-var-dep-fn) '(1 2 3 4))

8:15 llasram: &(def ^:dynamic v 0)

8:15 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

8:15 llasram: ,(def ^:dynamic v 0)

8:15 clojurebot: #'sandbox/v

8:16 llasram: ,(binding [v 1] (first (repeatedly #(-> v))))

8:16 clojurebot: 1

8:16 llasram: ,(binding [v 1] (first (repeatedly (bound-fn [] v))))

8:16 clojurebot: 1

8:16 llasram: Oh, hah

8:17 Helps to make it do what I'm trying to actually do

8:17 ,(def ^:dynamic v 0)

8:17 clojurebot: #'sandbox/v

8:17 llasram: ,(take 2 (binding [v 1] (repeatedly #(-> v))))

8:17 clojurebot: (0 0)

8:17 llasram: ,(take 2 (binding [v 1] (repeatedly (bound-fn [] v))))

8:17 clojurebot: (1 1)

8:17 llasram: There we go

8:18 rritoch: Oh, that's different

8:18 Actually, nm, it's not

8:18 Well, maybe

8:18 rritoch: Did you mean `my-var-dep-fn` to be itself a dynamically bound var, or a function which depends on a dynamically bound var?

8:22 rritoch: ,(take 2 (binding [v 5] (filter (bound-fn #(< % v)) '(1 2 3 4 5 6 7 8))))

8:22 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: v in this context, compiling:(NO_SOURCE_PATH:0:0)>

8:23 llasram: rritoch: you want bound-fn* there

8:23 Oh, and to re-def v :-)

8:23 clojurebot resets itself every so often

8:27 rritoch: Aah, ok. I get it now

8:30 ,(take 2 (binding [v 5] (filter (bound-fn [x] (< x v)) '(2 3 4 5 6 7 8))))

8:30 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: v in this context, compiling:(NO_SOURCE_PATH:0:0)>

8:30 rritoch: ,(def ^:dynamic v)

8:30 clojurebot: #'sandbox/v

8:30 rritoch: ,(take 2 (binding [v 5] (filter (bound-fn [x] (< x v)) '(2 3 4 5 6 7 8))))

8:30 clojurebot: (2 3)

8:31 rritoch: Either way, that is exactly what I was hoping for so I can get rid of most of my doall's

8:32 But I'll normally need the (bound-fn*) version

8:46 SagiCZ1: is there an assoc-like function that throws an exception if i try to alter a non-existent key?

8:46 (assoc-like map :non-existent-key value) ---> exception

8:49 ,(assoc {:a 0} :b 3)

8:49 clojurebot: {:b 3, :a 0}

8:58 mi6x3m: ok I will need all the help I can get

8:58 given this code http://pastebin.com/7RA8ZS7W

8:58 why is fis = nil when InputStreamReader is being constructed?

8:59 fis is correctly bound to the FileInputStream instance

8:59 but somehow it's not visible when the lazy seq is evaluated

8:59 Bronsa: this is related to my previous question

8:59 it's what confused me originally

9:03 for some dreadful reason fis is not visible in the lazy-seq :/

9:04 SagiCZ1: mi6x3m: thats some funky indenting

9:04 mi6x3m: SagiCZ1: there's a reason for that :) I'm sorry

9:04 I forgot to reformat

9:06 I am sure there's a simple reason for that, but I can't locate any apparent reason

9:10 okay everyone, I managed to get it down to a 1 liner

9:10 ,(let [x nil l (lazy-seq (cons (println x) ())) x 5] (first l))

9:10 clojurebot: nil\n

9:10 mi6x3m: but clearly it should be 5

9:10 also skipping x nil is an error

9:11 ,(let [l (lazy-seq (cons (println x) ())) x 5] (first l))

9:11 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)>

9:12 SagiCZ1: mi6x3m: wish i could help but i don't think i understand lazy-seq enough to explain this

9:13 mi6x3m: SagiCZ1: I appreciate :)

9:13 SagiCZ1: I nailed it down, lazy-seq creates a function

9:14 ,(macroexpand-1 '(lazy-seq (cons (println x) ())))

9:14 clojurebot: (new clojure.lang.LazySeq (fn* [] (cons (println x) ())))

9:20 rritoch: SagiCZ1: I have a solution for your assoc issue which seems to work, though I don't think the clojure core contains anything similar

9:20 mi6x3m: SagiCZ1: well, nothing is lazier than eval I guess

9:21 llasram: why would it be the opposite of a good idea?

9:21 rritoch: ,(let [replace (fn [m & x] (assert (every? (partial #(contains? %1 %2) m) (keep-indexed #(if (even? %1) %2) x))) (apply assoc (conj (seq x) m)))] (replace {:a 1} :b 2))

9:21 clojurebot: #<AssertionError java.lang.AssertionError: Assert failed: (every? (partial (fn* [p1__25# p2__26#] (contains? p1__25# p2__26#)) m) (keep-indexed (fn* [p1__27# p2__28#] (if (even? p1__27#) p2__28#)) x))>

9:21 rritoch: ,(let [replace (fn [m & x] (assert (every? (partial #(contains? %1 %2) m) (keep-indexed #(if (even? %1) %2) x))) (apply assoc (conj (seq x) m)))] (replace {:a 1} :a 2))

9:21 clojurebot: {:a 2}

9:22 SagiCZ1: rritoch: looks complicated

9:22 rritoch: I'm not sure how tomake that nicer

9:22 SagiCZ1: thank you though.. i will look into it

9:22 rritoch: It use keep-indexed on the k-v args to pull out all of the keys

9:23 Than asserts on every key being contained in the map

9:23 Which I believe is basically what your looking for, enforcing that only certain keys are used

9:26 SagiCZ1: rritoch: cant we just call contains? and then either assoc or throw exception?

9:27 jeffterrell: mi6x3m: Maybe you figured this out already, but I think your (first) one-liner should return nil because println returns nil.

9:27 rritoch: assoc allows multiple k-v's

9:28 mi6x3m: jeffterrell: it's not that, lazy-seq doesn't consider the current binding context at runtime

9:28 because it creates a function at compile time

9:29 rritoch: ,(let [replace (fn [m & x] (assert (every? (partial contains? m) (keep-indexed #(if (even? %1) %2) x))) (apply assoc (conj (seq x) m)))] (replace {:a 1} :a 2))

9:29 clojurebot: {:a 2}

9:29 rritoch: That's a little cleaner, but not much

9:29 jeffterrell: ,(let [x 3, l (lazy-seq (cons x nil)), x 5] (first l)) ; testing…

9:29 clojurebot: 3

9:29 SagiCZ1: rritoch: thank you

9:31 mi6x3m: damn eval doesn't consider bindings also

9:31 jeffterrell: mi6x3m: The only `x` that the call to `lazy-seq` knows about is the first binding. If you wanted it to consider the current binding context at runtime, I suggest using an atom.

9:31 ,(let [x (atom 3), l (lazy-seq (cons @x nil))] (reset! x 5) (first l))

9:31 clojurebot: 5

9:31 mi6x3m: I am really not interested in creating atoms for a simple iterative macro

9:32 llasram: mi6x3m: What are you actually trying to achieve?

9:32 mi6x3m: llasram: I'm writing an iterative version of try-let

9:32 llasram: Iterative?

9:32 mi6x3m: building up the bindings vector dynamically

9:33 llasram: Clojure doesn't really work that way

9:33 SagiCZ1: llasram: you dont have any idea if clojure has an 'assoc-like' function wont accept update for non-existent keys?

9:34 llasram: SagiCZ1: It does not

9:34 mi6x3m: llasram: I can stop right now if the original version had ANY licensing info attached to it

9:34 llasram: mi6x3m: Have you asked the author of the original version to provide a license?

9:35 mi6x3m: llasram: no, I have not :)

9:35 rritoch: Is there any function which automatically grabs even members of a sequence other than using this (keep-indexed #(if (even? %1 %2) coll) syntax? It would be helpful if there was a filter-indexed as that would be much less buggy than keep-indexed.

9:35 mi6x3m: but I could, yes

9:36 let me do so right now llasram:

9:37 llasram: rritoch: Not built-in. You can do anything you want on top of map-indexed though (which you'll need vs keep-indexed to allow the collection to have nils)

9:37 Actually, *thinking*

9:37 take-nth

9:37 ,(take-nth 2 (range 10))

9:37 clojurebot: (0 2 4 6 8)

9:38 jeffterrell: rritoch: Are you wanting even values or even indexes?

9:38 rritoch: Even indexes

9:39 llasram: Yeah, then take-nth is your function

9:39 jeffterrell: Nice one llasram, didn't know take-nth could do that.

9:40 (doc take-nth)

9:40 clojurebot: "([n] [n coll]); Returns a lazy seq of every nth item in coll. Returns a stateful transducer when no collection is provided."

10:03 SagiCZ1: ,(type (take-nth 5))

10:03 clojurebot: clojure.core$take_nth$fn__4684

10:03 SagiCZ1: i thought i would get a transducer

10:05 Bronsa: SagiCZ1: you are

10:05 SagiCZ1: a transducer is just a regular function

10:05 there's no "transducer type"

10:14 Paperboy: http://itch.io/games/genre-puzzle Free Games Here

10:16 icelesstea: Programming is the best puzzle game there is.

10:18 gfredericks: except it's not always clear when you've beaten the level

10:19 icelesstea: The uncertainty and the sudden moments of clarity and understanding are partly the reason why it is so great.

10:24 mi6x3m: is gensym global global

10:24 or global only to the calling macro?

10:24 i.e. context

10:24 Bronsa: global

10:25 mi6x3m: so `(x#) `(x#) is safe Bronsa ?

10:26 inside the same macro

10:26 Bronsa: yes

10:27 mi6x3m: alright

10:27 gfredericks: if "safe" means "I get two different gensyms"

10:29 beepbeep_: General question. Reduce is called left-fold and is a commonly known concept. Is there such a thing as left folding but also grouping by something?

10:32 AimHere: In what way do you want to 'group' stuff?

10:37 llasram: beepbeep_: Like MapReduce? It's a common pattern, but I don't know of a name for it (outside of MapReduce), nor does Clojure include it all packaged up

10:38 beepbeep_: llasram, that might be it, gonna check it out

10:45 mbac: in core.clj i say (:use [a.x as x]) (:use [b.y as y]) and then later in the file i reference values x/cmd and y/cmd

10:45 clojure says y/cmd conflicts with x/cmd. wah?

10:45 llasram: mbac: You want `:require` not `:use`

10:46 the latter `refer`s all the symbols from the namespace into the referencing namespace

10:46 only one thing can be bound to `cmd` in your `core` namespace

10:47 mbac: oh

10:50 thank you!

11:15 SagiCZ1: this is my implementation of safe-assoc https://www.refheap.com/92331 any obvious mistakes or slow-downs?

11:17 so far it is about 10 times slower than regular assoc :(

11:19 not sure i really want safe assoc anymore

11:21 llasram: SagiCZ1: That approach is doing quite a few additional allocations

11:22 SagiCZ1: llasram: in the assert?

11:22 llasram: SagiCZ1: It'd be much faster to just `recur` over the kv-pairs and check `contains?` before applying each

11:23 yes

11:23 Well, all over the place

11:24 SagiCZ1: what else the (every?) function does?

11:24 llasram: You've got one for each element from the `take-nth`, one for the #() argument to `every?`, and one for the `partial`

11:25 Plus you aren't even checking if `key` is in the `map`

11:25 FYI (apply (partial ...) coll) is the same as (apply ... coll)

11:26 Bronsa: that partial is not only useless, but will also slow things doen

11:26 down*

11:26 SagiCZ1: how am i not checking if the key is in the map?

11:27 llasram: SagiCZ1: Because you only verify that every other `kvs` is the map, and `kvs` does not include `key` or `val`

11:30 SagiCZ1: kvs is a list of (key value key value key value) by taking every second, i get a list of all keys, dont i?

11:31 ,(take-nth 2 [:key 5 :key2 10 :key3 0])

11:31 clojurebot: (:key :key2 :key3)

11:31 Bronsa: SagiCZ1: you have key val & kvs, you're checking for the keys in kvs but not for `key`

11:31 SagiCZ1: Bronsa: snap!

11:31 got it now

11:40 gfredericks: ,(inc (partial 41))

11:40 clojurebot: 42

11:41 Bronsa: gfredericks: you had me wat-ing for a second there

11:42 gfredericks: $findfn 41 41

11:42 hrmph.

11:42 ,(deliver inc 41)

11:42 clojurebot: 42

11:43 jeffterrell: (doc deliver)

11:43 clojurebot: "([promise val]); Delivers the supplied value to the promise, releasing any pending derefs. A subsequent call to deliver on a promise will have no effect."

11:43 jeffterrell: Ah, interesting.

11:43 gfredericks: you could do a whole WAT lightning talk on clojure GIGO

11:44 llasram: ,('+ 3 2 1)

11:44 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: Symbol>

11:44 llasram: ,('+ 1 1)

11:44 clojurebot: 1

11:44 llasram: There we go

11:44 gfredericks: ,(#'and true false true)

11:44 clojurebot: true

11:45 llasram: hah

11:45 SO GOOD

11:45 jeffterrell: You guys are making me feel dizzy. Like the ground is shifting underneath me.

11:46 llasram: ,(get :anything {} :haha)

11:46 clojurebot: :haha

11:46 gfredericks: ,(get 42 43 44)

11:46 clojurebot: 44

11:46 llasram: Actually, maximum wat-looking:

11:46 ,(get :key {:key :foo} :bar)

11:46 clojurebot: :bar

11:48 gfredericks: ,(->> "foo bar" keyword vector pr-str read-string reverse)

11:48 clojurebot: (bar :foo)

11:48 gfredericks: not too weird

11:48 llasram: ha

11:48 fun though

11:48 jeffterrell: ,(keyword "foo bar")

11:48 clojurebot: :foo bar

11:49 justin_smith: ,(((get get get get) get get get) {:a 42} :a)

11:49 clojurebot: 42

11:49 jeffterrell: lol

12:00 ourkid: hi - what are the equivalents of clojure's PDS classes in Java

12:02 llasram: PDS?

12:02 gfredericks: persistent data structuer

12:03 ourkid: it's still not clear what you mean; clojure's classes are written in java; are you wondering about mutable versions that come with the jre?

12:03 ourkid: yeah - PDS as in persistent data structure

12:03 i mean given that PDS's are quite sensible, why were Java's collections written as they were ?

12:04 gfredericks: well mutable collections are faster generally

12:04 I don't think PDS's were popular until quite recently

12:05 ourkid: They weren't popular because there wasn't so much multithreading until recently?

12:05 justin_smith: there was a point where we finally had enough RAM that pds were generally usable

12:05 gfredericks: they're still not *actually* popular; i.e., I don't think anywhere near the majority of programmers use them

12:05 justin_smith: this point was well after java was designed

12:05 ourkid: Ah - so it's a memory efficiency issue then?

12:05 gfredericks: yeah that's part of it

12:06 PDS requires a lot of GC

12:06 ourkid: So I guess if Java were starting from scratch then the PDS approach would be high on the feature list.

12:07 gfredericks: unclear what "java starting from scratch" would mean really

12:07 SagiCZ1: ourkid: i don't think so

12:08 ourkid: I guess I mean any new language would look to use PDS's if it also supported threads

12:08 SagiCZ1: java's principles revolve around mutable and stateful classes, pds wouldn't help there

12:08 hyPiRion: ourkid: Actually, the PDS Clojure uses weren't invented when the datastructures in java.util were implemented.

12:08 Java is almost 25 years old, so there's that as well.

12:08 ourkid: Right I see - Java is a mutable basket case; I think that is understood.

12:09 Does Scala implement PDS like collections?

12:09 jeffterrell: Heh, "a mutable basket case", I like that.

12:09 hyPiRion: I wouldn't be too surprised if Java came with PDS if it work on it started today.

12:09 gfredericks: ~java is a mutable basket case

12:09 clojurebot: Roger.

12:09 hyPiRion: ourkid: yes, Scala has roughly the same collection types as Clojure

12:10 gfredericks: my memory is that scala doesn't have nearly the emphasis though

12:11 ourkid: So Scala's map can be safely shared among threads?

12:11 gfredericks: well it has mutable maps too

12:12 ourkid: Yes, I know. I am just wondering why the same emphasis is not there in Scala. Is there something unique about Clojure's implementations of PDS's ?

12:13 hyPiRion: Well, the transients are unique as far as I know.

12:14 And they share a common interface.

12:14 But apart from that, there's no reason any other language can't implement them.

12:15 ourkid: OK understood - thanks all.

12:15 hyPiRion: (roughly speaking)

12:15 np

12:15 gfredericks: hello hyPiRion

12:16 hyPiRion: hello gfredericks

12:17 justin_smith: hyPiRion: they do require gc though, don't they?

12:18 gfredericks: if you wanted to do PDS in C, what would be the downside of reference-counting? would it not be both easy and not-too-slow?

12:18 hyPiRion: justin_smith: yes, hence the roughly speaking part. And they should have hashing functions on elements

12:18 * gfredericks knows very little about C

12:19 justin_smith: gfredericks: building up a pds creates garbage as you go, if you don't have a smart gc that detects and immediately reclaims short used stuff, you are going to get frequent and expensive gc cycles

12:19 llasram: gfredericks: Hmm... Interesting. I guess you could ref-count the components and explicitly discard instances

12:19 hyPiRion: gfredericks: it's possible with RC, but then you'd have to detect cycles. And the reference count has to be thread safe.

12:19 gfredericks: justin_smith: isn't the point of reference counting that you don't need a general-purpose GC?

12:20 llasram: Probably easier to just run a garbage collector. You can actually write garbarge-collected C with e.g. http://www.hboehm.info/gc/

12:20 gfredericks: hyPiRion: wherein might you create a cycle?

12:21 justin_smith: gfredericks: the point of a good gc is that you don't need to reference count :P

12:21 hyPiRion: gfredericks: that's sort of depending on the language, but (let [a (atom nil) b [a]] (reset! a b) b) creates one

12:22 gfredericks: justin_smith: it'd be an impl detail of the PDS's; you'd just be responsible for cleaning up when you're done with something

12:22 hyPiRion: llasram: that's what I did for my master's thesis. Worked out surprisingly well (can't comment on the boehm GC perf though)

12:23 gfredericks: I don't think I have the energy to figure out if I'm crazy atm

12:23 llasram: hyPiRion: nice. I've never had reason to try that, but it's good to know it works :-)

12:23 * gfredericks goes back to debugging quantum modular arithmetic functions

12:23 llasram: gfredericks: Still working on that algebra lib?

12:24 gfredericks: I've been thinking of doing one just for monoids

12:24 So simple, yet so useful

12:24 gfredericks: llasram: that'd be easy to add to mine

12:24 you just need + amirite?

12:24 llasram: urrite

12:24 gfredericks: wait I already have it

12:25 llasram: well then maybe my work is done

12:25 gfredericks: I think I only had it as in impl for groups/rings/fields

12:25 but it still works

12:25 llasram: https://github.com/gfredericks/lib-4395/blob/master/src/com/gfredericks/lib_4395.clj#L18-25

12:27 llasram: Cool. Hmm

12:27 justin_smith: gfredericks: doing a bit more reading, reference counting might not be totally crazy (and is specifically mentioned as useful in garbage heavy algorithms used with pds) - but you'll need thread safe reference update which adds a wrinkle I would think

12:29 gfredericks: hoo ray!

12:31 justin_smith: gfredericks: reference counting and graph algos don't mix very nicely though

12:31 (but of course we have adjacency list representation for that)

12:31 gfredericks: justin_smith: graph algos meaning the sort where you get cycles?

12:32 justin_smith: gfredericks: yeah, graphs in general are allowed to have cycles

12:32 gfredericks: right but any pure PDS use will not have cycles

12:32 justin_smith: and weird tricky to work with kinds if you consider the layers of indirection before you see the cycle

12:32 gfredericks: you gotta incorporate references to get them

12:32 justin_smith: right

12:35 gfredericks: another issue (especially if you are looking at concurrency) is that the reference count updates can create pipeline bubbles and cache misses, and that shit gets expensive

12:36 gfredericks: man computers

12:37 * gfredericks will tell you what

12:37 justin_smith: gfredericks: one nice thing about idiomatic clojure is how rarely updates to data in one thread will touch anything another thread can even see

12:37 CPUs like that

12:38 gfredericks: oh goodness this quantum stuff is so slow; I'll be lucky if I can factor 15

12:40 justin_smith: idea: "low pass filter" toggle on youtube, to eliminate the high pitched whine in quad-copter vids

13:01 gfredericks: another neat thing: tcl values are immutible, and it uses reference counting

13:02 gfredericks: justin_smith: good to know

13:03 Bruce_Wayne: Hey, anyone know the best way in a web app to have a user upload a file?

13:04 I need the user to be able to use the open-file-dialog box to give me the full path to the file

13:04 that way I can read it in and work with it

13:04 justin_smith: Bruce_Wayne: well, the path doesn't do you any good - it's on the user's computer

13:05 but you can use an input type="file"

13:05 then the contents of the file they use will come in with the request when they submit the form

13:06 andyf: justin_smith: gfredericks: Are one of you gentlemen writing programs in tcl? I haven?t, but have seen enough that I?m glad I haven?t.

13:06 justin_smith: andyf: we were talking about reference counting gc and pds

13:07 andyf: and that was a bit of trivia I encountered when looking at the issues involved

13:07 Bruce_Wayne: I was trying to use the hiccup implementation of upload file

13:07 gfredericks: andyf: never once in my life

13:07 Bruce_Wayne: https://github.com/weavejester/hiccup/blob/31c06bec7eec038c6d3bfc051f4033362f142ffb/src/hiccup/form.clj

13:08 justin_smith: andyf: tcl is succeptible to quoting hell, but it has a semi-declarative aspect that you don't see in eg. sh or perl (its main competitors)

13:08 Bruce_Wayne: I thought: https://gist.github.com/jtackett/14ea479e0e3260b9ef4f

13:08 would work

13:08 through hiccup library

13:08 any advice?

13:08 justin_smith: andyf: instead of mutation, you work with data transformations, so it is almost functional in that sense

13:09 gfredericks: anybody know of an efficient bit-vector impl? i.e., should be PDS-like

13:09 andyf: justin_smith: Like I said, I haven?t actually written serious code with it, but at work our large test teams use it a lot. I?m amazed at the scale they use it. Didn?t realize everything was immutable.

13:09 justin_smith: Bruce_Wayne: if the name is nil, how will you collect the data from the request?

13:09 Bruce_Wayne: when i post the form to the url all it seems toreturn is the file name

13:10 the name isn’t nil

13:10 that is just the last arg past

13:10 the name is the param passed in

13:10 https://gist.github.com/jtackett/236f06b8bb10b6ee9d64

13:10 justin_smith: andyf: yeah, there's this weird way that macro languages (of which tcl could be considered a variant) are closely related to functional programming, in that it's all about input to output transforms and not maintaining mutable state

13:11 Bruce_Wayne: OK, you should be getting the file contents as an input stream inside the request body

13:12 Bruce_Wayne: it simplifies things a lot if you use the wrap-multipart-params middleware in ring

13:12 Bruce_Wayne: so when I post that to the url how do I capture the file contents?

13:13 justin_smith: Bruce_Wayne: the file contents will be inside the request body

13:13 Bronsa: 1.7.0-beta3 is out

13:13 err, alpha3

13:13 justin_smith: Bruce_Wayne: http://ring-clojure.github.io/ring/ring.middleware.multipart-params.html

13:14 you will have a :params key on the request, and you can look up the file contents under that map

13:14 Bruce_Wayne: alright

13:14 so when i do the file upload

13:14 it will return the name of the file along with it’s contents

13:15 but i need to use the multipart-params to get to the file content

13:15 justin_smith: wrap-multipart-params makes it easier

13:15 Bruce_Wayne: is there another way?

13:15 justin_smith: it's going to be in the request either way

13:16 Bruce_Wayne: if you don't use the w-m-p middleware, it will be a stream, so you'll have to dump the stream into a byte-array or file or whatever

13:16 Bruce_Wayne: ugh ok

13:16 I’ll use the wmp middleware

13:17 strange that the normal param just returns the name of the file when printed

13:17 justin_smith: Bruce_Wayne: it sends the filename and the contents, they are both in there

13:17 somewhere

13:18 Bruce_Wayne: but when you prn the params of the post

13:18 it is the file name

13:18 justin_smith: right, it's not in the params

13:18 you need a middleware before anything ends up in :params of the request

13:19 the :params key is not part of what comes from the client, it is created server side to simplify your handler logic

13:19 Bruce_Wayne: alright

13:19 justin_smith: it's based on the request parameters, form parameters, etc.

13:19 Bruce_Wayne: I wrapped it in the middle ware

13:19 but a map isn’t being returned

13:20 it is still just a string with the file name

13:20 justin_smith: Bruce_Wayne: print out the full contents of :multipart-params

13:20 Bruce_Wayne: I am trying

13:20 let me show you the flow

13:22 https://gist.github.com/jtackett/d91a295cbd01c1fb20de

13:24 justin_smith: Bruce_Wayne: change the route to reference the full request so you can see the contents of :multipart-params, I assure you the upload data is in there somewhere

13:24 Bruce_Wayne: ok how would i do that?

13:26 change the rout to reference the ful request that is

13:26 justin_smith: Bruce_Wayne: (POST "/your-pdf" request (fn [request] (prn (:multipart-params request))))

13:26 Bruce_Wayne: can you literally write the word request?

13:26 justin_smith: wait, sorry

13:27 Bruce_Wayne: no worries

13:27 justin_smith: Bruce_Wayne: (POST "/your-pdf" request (prn (:multipart-params request)))

13:27 gawd I hate macro magic sometimes

13:27 yes, literally the word request, and pass the whole request and all its data

13:27 https://github.com/weavejester/compojure/wiki/Routes-In-Detail

13:28 the [file] syntax in that context is a shortcut for getting at (-> request :params :file)

13:30 Bruce_Wayne: got ya

13:30 I’m getting an empty map with that

13:30 one sec

13:31 justin_smith: I'm off to shower and get a coffee myself, but feel free to share whatever in the meantime, I just won't be here to respond right away

13:31 Bruce_Wayne: ok

13:31 I can see the whole request now, but there doesn’t seem to be a file

13:31 just the file path

13:31 which only is the name of the file

13:45 mi6x3m: does anyone know if I have to include a copy of EPL 1.0 if I release something under it?

13:45 or a link is sufficient?

13:53 icelesstea: mi6x3m: Usually you need to include the full license, though with really small pieces of software, a summary and a link to the full license would be enough, I suppose. However, better to include the full thing though, just to be on the safer side.

13:53 mi6x3m: icelesstea: true

14:07 justin_smith: $mail Bruce_Wayne minimal working file upload example https://www.refheap.com/92336

14:07 ahh, lazybot is out too :P

14:08 but anyway, that's the smallest intelligible example I could make of a file upload in a compojure app, if anyone cares

14:12 mi6x3m: hey everyone, I finished that try-let macro I was working on

14:12 https://gist.github.com/MIvanchev/5bad28baad02167fbece

14:13 mmeix: If anyone would be so kind to have a look at https://www.refheap.com/92334 - I just would like to know if it's written in good style ... thanks.

14:14 justin_smith: mmeix: blank lines inside defns aren't usually done

14:15 mmeix: and especially with the longer comments, do a full line comment on the line above with ;; rather than an end of line comment that wraps

14:16 also, your last three bindings could be one line: [before cand after] primes-triple

14:16 ,(let [[before cand after] [1 2 3]] after)

14:16 clojurebot: 3

14:18 justin_smith: in fact, I would just do (let [... [before cand after] (take-last 3 primes)] ...)

14:18 jeffterrell: mi6x3m: that's nifty. Seems like a good bit of syntactic sugar.

14:19 Shambles_: Does anyone know of a function in Clojure that does what this does? https://lodash.com/docs#at If not, do you know of what it would be popularly called? There has to be something better than "at".

14:19 justin_smith: mi6x3m: catching throwable has some really bad corner cases

14:20 Shambles_: select-keys maybe?

14:20 ,(select-keys '[a b c d e] [0 2 4])

14:20 clojurebot: {4 e, 2 c, 0 a}

14:20 justin_smith: that's not quite it...

14:20 ahh, map :)

14:21 ,(map '[a b c d e] [0 2 4])

14:21 clojurebot: (a c e)

14:21 justin_smith: yes, in clojure "at" is called "map" :)

14:22 only works with vectors / sets / hash-maps that way though

14:22 Shambles_: justin_smith: Hmm, I hadn't gotten used to thinking of map that way since data structures aren't functions in most Lisp-likes.

14:22 justin_smith: Shambles_: fair point, yeah :)

14:22 Shambles_: select-keys is most of the way to a good name though.

14:23 justin_smith: ,(map #(get '[a b c d e] %) [0 2 4])

14:23 clojurebot: (a c e)

14:23 justin_smith: the verbose version, that's what that map is really doing anyway

14:23 Shambles_: I'm actually trying to implement something in another language, and I'm desperately trying to avoid coming up with my own names, for fear of bad naming (and "at" is a pretty terrible name).

14:23 justin_smith: Shambles_: sample

14:23 Shambles_: Yeah the mapping get thing occurred to me already.

14:24 justin_smith: I think sample is a good name for it - taking individual points out of a larger continuum

14:24 Shambles_: Okay, here's what I'm doing... I've found a way to implement functional programming (sort-of) in a programming language that doesn't support it, but there is a feature that can be abused to create 'function objects' (values that act like functions). The problem is that there is no "lambda", and thus no "let".

14:25 justin_smith: ouch

14:25 Shambles_: All my functions built at run time get one array (for all of them) to hold the arguments of the function object (which may contain quite a lot of code).

14:26 mmeix: justin_smith thanks for hints - hadn't thought about this possibility: (let [... [before cand after] (take-last 3 primes)] ...). Improved version https://www.refheap.com/92334 . Help appreciated as always :-)

14:26 justin_smith: Shambles_: have you considered an env-map - a hashmap holding bindings of keys to values? lambda and let can be made in terms of this if you at least have function objects

14:26 Shambles_: I've implemented function objects that act like curry and comp (or compose in some Lisp-likes), and I've gotten pretty decent at abusing the @#$* out of them and certain combinators. Juxt seems to be particularly handy to pass values 'past' a function to a function 'behind' it.

14:27 But I wanted this thing to slice up the big array of arguments into little ones, for use with juxt, for use with curried applys! ;)

14:28 I'm not sure how such an env-map would work, short of passing an extra value to every function, which isn't possible for functions that already exist (e.g. built-in ones).

14:28 justin_smith: mmeix: also, if you know it's a vector (as you do thanks to the scope of binding) use peek rather than last

14:28 (doc last)

14:28 clojurebot: "([coll]); Return the last item in coll, in linear time"

14:28 justin_smith: (doc peek)

14:28 clojurebot: "([coll]); For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil."

14:29 mmeix: because it's faster?

14:29 or more idiomatic?

14:29 justin_smith: both I'd say

14:29 mmeix: ok

14:29 thanks

14:30 justin_smith: mmeix: a cool thing is that peek / conj always pair up, whether using lists or vectors

14:30 (not for queues though)

14:31 mmeix: because they work from the same end, respectively, as far as I understand

14:31 justin_smith: right

14:31 mmeix: ok

14:31 justin_smith: peek /conj / pop all treat the argument as a stack

14:33 (except with queues, then they treat it as a queue)

14:33 mmeix: peek/pop I understood, but not the symmetry with conj - good insight, thanks

14:33 lot of things to be learned, but it's getting better, slowly ... :)

14:34 justin_smith: yup, it's worth it

14:35 Shambles_: justin_smith: Does "select-indexes" seem okay for a name?

14:36 justin_smith: sure, though I like sample better still

14:37 Shambles_: I Googled for things using that and index, and it seems that's popularly used to take random samples from arrays, so I thought it would be misleading.

14:38 justin_smith: random sampling isn't the only kind, but if that's really a common thing, that's a good point

14:40 mmeix: P.S.: I did some experiments with modeling musical structures, and clojure's way is a really great fit, I found, so I plan to use it for an ear training and music theory environment (I'm a music theory teacher). There is a long tradition of using LISPs for that, which brought me to Clojure ... (and I like the fact that Rich Hickey started out as a musician.

14:43 Shambles_: I think I'll go with that for the name. Thanks for the help justin_smith.

14:44 justin_smith: mmeix: on the synthesis side of things, I'm interested in what pink might grow into

14:44 mmeix: yup ...

14:45 I'm mostly thinking about modeling the deep and multi-layered structures of harmony and counterpoint

14:45 thinking in Clojure helps clarifying that et vice versa, I found

14:46 justin_smith: cool

14:47 mmeix: so now I'm learning Clojure as fast as I can, really motivated :-)

14:49 justin_smith: mmeix: just noticed one more thing in your refheap (if (= cand n) (= cand (/ (+ before after) 2)) false) can be rewritten as (and (= cand n) (= cand (/ (+ before after) 2)))

14:49 and I think the latter is clearer

14:49 oh wait!

14:50 mmeix: the first is a check, if cand is really a prime

14:50 justin_smith: (= cand n (/ (+ before after) 2))

14:50 mmeix: sure, but that's how and works

14:50 if the first one fails, it fails

14:50 mmeix: of course

14:50 great

14:51 justin_smith: but anyway, we have multi-arg =, and that's the simplest thing here :)

14:51 because really you just want "are these three things equal"

14:52 creese: I'm having trouble inserting into a mysql table using jdbc. The error is: "java.sql.BatchUpdateException: Incorrect string value: '\xAC\xED\x00\x05sr...' for column 'title' at row 1"

14:52 mmeix: ah! [light bulb]

14:52 creese: Does that look familiar to anyone?

14:52 justin_smith: creese: what kind of crazy input are you feeding that poor db connection?

14:53 Renato_Ferreira: could it be encoding?

14:53 justin_smith: (joking)

14:54 creese: encoding sounds right, I'm just not sure of the fix or why it's needed

14:56 mmeix: justin_smith but now my test case (nth (filter balanced-prime? (range)) 15) gives me a "NullPointerException", not sure why...

14:56 justin_smith: mmeix: hmm

14:57 mmeix: ( https://www.refheap.com/92334 updated )

14:57 justin_smith: mmeix: with the version currently in refheap?

14:57 mmeix: just now

14:58 [testing ...]

14:58 justin_smith: mmeix: ahh, the destructuring will make after be nil if primes is a two element list

14:58 Renato_Ferreira: creese: unfortunately i don't have a lot of experience with db in clojure, but is the database itself configured with the correct encoding, like some utf8 or something?

14:58 justin_smith: ,(let [[a b c] [1 2]] c)

14:58 clojurebot: nil

14:58 mmeix: ah...!

14:59 justin_smith: mmeix: I had not considered that difference between last and getting the third element

14:59 mmeix: I would never have thought of that

15:00 justin_smith: mmeix: what if the acc started with [2 3 5] would that be cheating?

15:00 mmeix: just had the same idea

15:00 justin_smith: otherwise you could revert the binding change, of course

15:00 Renato_Ferreira: there should also be an encoding for the connection itself, like 'set names' in mysql

15:01 mmeix: (checking, if 2, 3 and 5 are/aren't "balanced primes" - then it woouldn't be cheating)

15:02 creese: Renato_Ferreira: the character set is utf8 for that column, more like I'm doing the batch update wrong

15:02 Renato_Rerreira: elsewhere, I do the single insert and it works

15:03 zand`: hey folks - does anyone know how to specify the version of a leiningen template to use with new?

15:03 example: I have two versions of a template installed in .m2 and it keeps using the older one

15:04 SagiCZ1: i managed to make the safe-assoc implementation 15% faster and 50% less readable, any ways to make it faster? https://www.refheap.com/92337

15:04 creese: (sql/insert! db :tag [:title] [tags]) ... the value of tags is [[foo bar]] from println

15:04 zand`: e.g. lein new liberagent:0.1.5-SNAPSHOT foo

15:04 (that doesn't work btw ^^^)

15:05 justin_smith: zand`: I don't think lein templates have that power

15:05 zand`: that's what I thought - no mentions of versions in the docs...

15:05 SagiCZ1: maybe i should use transients

15:05 zand`: thanks.. I'll manually delete the other dir in ~/.m2 and see what happens

15:07 hmmm... that doesn't seem to work (lein new just goes to clojars to download the older version)

15:09 mmeix: justin_smith ok: http://en.wikipedia.org/wiki/Balanced_prime 5 is the first "balanced prime", so this works ... (map balanced-prime? (range 1 6) gives (false false false false true) - so your improved binding works correctly (and I learned a new trick ;) . Updated refheap: https://www.refheap.com/92334

15:10 (quite a learning experience ...)

15:12 Renato_Ferreira: creese: hmm, yeah my knowledge with this api is rather limited. shouldn't tags be a simple array? it is it indeed nested?

15:20 zand`: anyone know what the current best practice is for installing and using a library from github?

15:21 zoldar: zand`: one way I know is cloning and doing lein install to put it into local maven repository

15:22 creese: Renato_Rerreira: (insert! db-spec table col-name-vec col-val-vec & col-val-vecs :transaction? true :entities identity)

15:22 zoldar: but I don't know if this is the best practice actually...

15:23 creese: I take this to mean col-name-vec is [:title] following by separate args for each row to insert (foo) (bar) (etc)

15:23 zand`: @zoldar: thanks - I did lein install but the library I'm using is a template and when I do "lein new template-name foo" it still goes to clojars and gets the old (broken) version...

15:24 Renato_Ferreira: creese: oh sorry you're right, it's nested, because there could me multiple columns. so yeah, i'm not sure what the problem is =P

15:24 creese: so now I've got: ({:password 1234, :subprotocol mysql, :user stuff_user, :subname //localhost:3306/stuff} :tag [:title] (foo) (bar)) ... which I feed into the insert using an apply

15:24 zoldar: zand`: that's weird.. if versioning is right, the one from local repo should be fetched

15:24 zand`: is the version from the repo actually hight?

15:24 higher*?

15:25 zand`: @zoldar - yes, it's higher 0.1.4 vs 0.1.5-SNAPSHOT

15:25 creese: The traceback says: java.lang.IllegalArgumentException: insert called with columns but no values

15:25 zand`: it's possible the problem is user error :-) I'll give it another go here...

15:25 Renato_Ferreira: hm...

15:26 justin_smith: zand`: try taking -SNAPSHOT out of the version string

15:26 zoldar: zand`: wait, one more thing you ma have to do is to put it into your local profile in ~/.lein/

15:26 justin_smith: zoldar: that should not be relevant for a template

15:27 zand`: @zoldar: I'll try again and report back...

15:27 zoldar: justin_smith: okay, but maybe adding it to profiles.clj under :user :plugins would override the problem with the snapshot release?

15:28 justin_smith: zoldar: maybe...

15:28 zoldar: justin_smith: I recall that I had to do it when testing out my own template

15:28 SagiCZ1: is loop-recur rebinding preffered to swaping an atom?

15:28 Renato_Ferreira: creese: and how does that code relate to the single example that works? in this line of code I don't see the rows being wrapped together, although I might be interpreting this wrong

15:28 Bronsa: SagiCZ1: what do you mean?

15:28 justin_smith: SagiCZ1: when applicable, yes - if it's something used locally by said loop, just rebind rather than using an atom

15:29 creese: the example that works is one row, the batch insert has a different argument list (its also a different table)

15:29 SagiCZ1: justin_smith: yes it is used locally.. ok i will use loops.. atoms are so tempting though

15:30 Bronsa: SagiCZ1: they are entirely different things, you shouldn't think of atoms as a substitute for the mutable variables you use in other langs

15:30 SagiCZ1: Bronsa: they do substitute them though

15:30 from my POV

15:31 creese: Renato_Ferreira: trying this now --> (sql/insert! db :tag (map #(hash-map :title %) tags))

15:31 Bronsa: SagiCZ1: well you should change your POV when programming in clojure then :)

15:32 justin_smith: SagiCZ1: you could also do something evil with string and System/setProperty / System/getProperty - but it still isn't what these things are for

15:32 SagiCZ1: justin_smith: i wonder what are atoms for then

15:32 Bronsa: justin_smith: you shouldn't go around suggesting that >:(

15:33 justin_smith: Bronsa: I was hoping it would sound silly enough to clearly be wrong

15:33 how about filenames and spit / slurp, that could replace mutable variables too (yuck)

15:33 Bronsa: SagiCZ1: they are reference types implementing a CAS mechanism. they have significant more overhead than "normal" mutable vars

15:34 SagiCZ1: justin_smith: what great ideas!

15:34 Bronsa: justin_smith: brb I'm rewriting all my functional code into procedural using that

15:34 SagiCZ1: Bronsa: thank you for elaborating

15:35 creese: Using apply now with this: ({:password 1234, :subprotocol mysql, :user stuff_user, :subname //localhost:3306/stuff} :tag {:title foo} {:title bar}) --> java.lang.IllegalArgumentException: insert called with columns but no values

15:35 Renato_Ferreira: creese: but that will yield one sequence of row maps, instead of multiple row map arguments, won't it?

15:35 creese: a sequence of rows maps is another interface that should work

15:36 (insert! db-spec table row-map & row-maps :transaction? true :entities identity)

15:36 justin_smith: creese: that would work with apply maybe

15:36 Bronsa: SagiCZ1: it's not that you *cannot* use them to substitute variables, it's that clojure pushes strongly towards functional programming w/ immutable values and offers a lot of niceties to work that way, using atoms to circumvent that is silly and probably inefficient

15:36 creese: like this? --> (apply sql/insert! (concat [db :tag] (map #(hash-map :title %) tags)))

15:37 it doesn't seem to

15:37 justin_smith: Bronsa: SagiCZ1: thus my even sillier and even more ineffecient suggestions

15:37 creese: don't use concat there

15:37 creese: what's wrong with concat

15:37 justin_smith: ,(apply + 1 2 [3 4 5])

15:37 clojurebot: 15

15:37 justin_smith: it's not needed

15:37 but anyway, if your last N args are in a collection, apply is the right way to handle it

15:38 Renato_Ferreira: we have to unwrap them using apply, if i get it right. the function doc seems to indicate that

15:38 oops, exactly

15:39 SagiCZ1: Bronsa: justin_smith: Could you have a quick look at this and suggest a way to get rid of the atom? i have rewritten this so many times im completely blind to the solution, note that "consume" returns updated version of creature

15:39 https://www.refheap.com/92339

15:40 creese: (apply sql/insert! db :tag (map #(hash-map :title %) tags)) <-- java.lang.IllegalArgumentException: insert called with columns but no values

15:40 justin_smith: SagiCZ1: (reduce (fn [creates event] (map #(consume % event) creatures)) creatures queue)

15:41 Bronsa: SagiCZ1: that looks like a reduce

15:41 justin_smith: yeah, definitely a reduce

15:41 s/creates/creatures above of course

15:41 SagiCZ1: oh... are you suggesting that ignoring reduce and refusing to learn about it was a mistake?

15:41 justin_smith: SagiCZ1: pretty much :)

15:41 reduce is awesome

15:42 SagiCZ1: no wonder i couldnt figure this out, thank you very much

15:42 justin_smith: SagiCZ1: whenever you want to repeatedly punch a new transformation based on a sequence of data onto some state, a reduce does that handily

15:43 and all the mutation is moved to the arguments of the reducing function, so no more atom or mutable variable needed

15:43 "mutation"

15:45 SagiCZ1: thats amazing.. better then loops

15:45 justin_smith: SagiCZ1: it abstracts and makes simpler a particular common usage of loops

15:46 also, for extra credit: there is also reduced, for when you realize you are done and don't need to access the rest of the sequence

15:46 (doc reduced)

15:46 clojurebot: "([x]); Wraps x in a way such that a reduce will terminate with the value x"

15:46 mmeix: (it is a recursive loop under hoods, right?)

15:46 SagiCZ1: justin_smith: yeah that makes sense.. thats why i had a feeling im looping the same way every time

15:47 justin_smith: mmeix: well, eventually you get down to loops, but there are a few protocols / interfaces it specializes on with different impls

15:47 mmeix: of course

15:47 SagiCZ1: justin_smith: i guess it's blazing fast too right?

15:47 Bronsa: SagiCZ1: much faster than mutating an atom in a loop

15:48 Renato_Ferreira: creese: silly question, but have you tried a minimal example without relying on other values, just hard coding it for, say, two columns?

15:48 justin_smith: Bronsa: SagiCZ1: and thanks to the specialized protocols, likely faster than looping with first / rest / accumulator too

15:48 Renato_Ferreira: (sql/insert! db :tag {:title "t1"} {:title "t2"})

15:49 Bronsa: justin_smith: definitely

15:49 mmeix: (mmeix stares at the source of "reduce")

15:49 Bronsa: there's not much there :)

15:49 mmeix: ja, just found out by myself ...

15:49 Raynes: mmeix: Look at the source for doseq lol

15:49 It's like staring at the sun.

15:49 Bronsa: Raynes: you monster.

15:50 mmeix: "clojure.core.protocols/coll-reduce" seems to be the magic spell ...

15:50 ok

15:50 Bronsa: IIRC the source for `for` is even worse

15:51 mmeix: ok: understanding doseq source would take me three days, indeed ;)

15:51 justin_smith: yeah, for is a monster

15:51 Bronsa: mmeix: there's an intricate amount of protocols/interfaces that play into different implementations for reduce

15:51 some are in clojure, some in java

15:52 mmeix: ah

15:52 I see

15:52 justin_smith: "never trust a macro you couldn't read out loud in one breath"

15:52 mmeix: LOL!

15:52 like one musical phrase ...

15:53 (if that's the right word in english)

15:53 justin_smith: I don't actually suggest that standard, but I thought it sounded nice :)

15:53 I use for / doseq all the time

15:53 Bronsa: mmeix: there's nothing much interesting in the impl of `for` anyway it's mostly parsing boilerplate & chunked-seq handling

15:54 SagiCZ1: that reduce is the shizz

15:54 creese: (sql/insert! db :tag {:title "foo1"} {:title} "bar1") <-- this works at the repl

15:55 mmeix: [defers studying clojure source] :-)

15:56 skratl0x1: say I have an existing chan, and I want one with a transducer on it applied, before I'm not in control of the chan creation, what function do I use for this?

15:56 creese: so does this -> (apply sql/insert! db :tag (map #(hash-map :title %) tags))

15:56 justin_smith: mmeix: speaking of musical stuff have you seen this? http://calebhugo.com/musical-games-interact-with-sound/2048-circle-of-fifths/ it's like 2048 but with the circle of fifths instead of powers of two

15:57 creese: I assume '{:title} "bar1"' was a typo

15:57 mmeix: ah! great stuff! this goes straight on my teacher's web page :-) Thanks!

15:57 creese: justin_smith: yeah, I copied the wrong one

15:58 skratl0x1: it surprises I can't find any example of this

15:58 Renato_Ferreira: wait, wasnt the second one giving the illegal argument stuff?

16:01 SagiCZ1: how could i make some random java collection implement sequencible, so i could use it in clojure?

16:02 justin_smith: SagiCZ1: if (seq r) doesn't work, try getting an iterator on it

16:02 or if it has a .toArray or .asList method or whatever

16:02 SagiCZ1: what class?

16:02 SagiCZ1: ArrayBlockingQueue

16:02 seq seems to work

16:03 creese: justin_smith: so the insert works, the problem was another one further down

16:10 SagiCZ1: justin_smith: so yeah.. seq works on blocking queue, but the implementation is different then what i would like, what can i do about it? maybe i could rework it into lazy-seq which internaly uses the blocking queue, but maybe there is a better way?

16:12 justin_smith: SagiCZ1: if the queue is being used as an actual queue I would just use the interop methods to put / poll / take

16:12 SagiCZ1: since the semantics of the queue are probably important for program correctness and you don't want an abstraction that messes with that

16:12 SagiCZ1: justin_smith: thats what i do, but then i cant reduce over it :(

16:12 justin_smith: well, you can't reduce period because you don't know the size ahead of time

16:13 things can get added to the end while you use it

16:13 SagiCZ1: it would block the thread that is reducing

16:13 justin_smith: you may be able to use iterate such that it can be treated as a lazy seq instead

16:13 SagiCZ1: so yeah, you *can* reduce, but that seems less than ideal

16:13 it's the wrong semantics - you can't just replace every loop with reduce

16:14 sometimes you need iterate, or map, or ever so rarely, loop :)

16:15 gfredericks: ~loop is a macro of last resort

16:15 clojurebot: In Ordnung

16:18 SagiCZ1: justin_smith: i didnt realize that was important in my example, could you have a look at how to get rid of the atom in case i need to use the interop .take method? https://www.refheap.com/92344

16:18 justin_smith: SagiCZ1: you can add creatures as a second arg to loop

16:19 and then add the updated creatures (result of the map) to the recur call

16:19 SagiCZ1: okay.. so then it would be just one loop, that gets a new event and updated list of creatures at the same time

16:20 justin_smith: or you can use the reduce version, with (repeatedly #(.take queue)) as the sequence to reduce on

16:20 SagiCZ1: right

16:20 SagiCZ1: thanks, that will work

16:20 justin_smith: the (repeatedly #(.take queue)) version with reduce is nicer to my eyes actually

16:21 ~loop

16:21 clojurebot: loop is https://www.refheap.com/90332

16:21 justin_smith: oh, I remember doing that one, lol

16:22 SagiCZ1: justin_smith: wait so i can do repeatedly and use reduce?

16:22 justin_smith: right, using that repeatedly call in the reduce version instead of directly using the queue should work

16:22 SagiCZ1: sounds great

16:27 justin_smith: works fine, really good idea

16:27 justin_smith: glad it worked

16:35 ro6: I'm looking for recommendations and best practices on the best way to add functionality to an application I've deployed on a remote machine. The application is modular and different clients might have different combinations/versions of modules. There is a server component that stores and manages the configurations of all these clients, but I'm not sure the

16:35 best way to realize the configuration on a client when it starts up.

16:37 I've read a lot about classloaders, but that seems like dangerous territory. It's acceptable to restart the application anytime it needs new modules, but the entire process of loading/unloading functionality needs to be triggered and controlled from the server.

16:38 So far, the simplest way seems to be just dropping new jars into the classpath and restarting, but I wanted to see if there is a more idiomatic way to achieve this that's safe/reliable/simple

16:38 justin_smith: ro6: is this a rest service?

16:39 or wait, drop the rest part, I assume this is an http service of some kind?

16:39 ro6: justin_smith: the server is a rest api

16:40 justin_smith: OK, two things to consider would be: using tomcat, and using different wars for subpaths, and redeploying or adding wars, this can be done at runtime without a restart

16:40 there is also immutant, built on jboss

16:40 which can do fancier things with coordinating services

16:40 ro6: justin_smith: the client machines are basically just desktop computers where I have no ability to control what ports are open, etc

16:41 justin_smith: ro6: yeah, this is all server side that I am talking about

16:42 ro6: justin_smith: yeah, the server side isn't where I need the modularity, because I control that environment. I understand how to deploy there, it's the client that I'm not sure about

16:42 justin_smith: oh, OK, now I get it

16:42 yeah, so you want to be able to export new features to the client end

16:43 ro6: justin_smith: exactly, and potentially different features for different clients

16:43 justin_smith: is the client also built using clojure? if so something like component could be used to bring up new parts of the app, or insert new ones

16:44 plus there is alembic/still for simple updates of the app to pull in a new mvn dep at runtime

16:44 (still/distill [[some/dep "version"]]) same syntax as in project.clj

16:44 ro6: justin_smith: right, so I've been looking at Trapperkeeper, which seems to support a similar idea to component

16:44 justin_smith: I know those guys but haven't taken a close look at Trapperkeeper yet...

16:45 ro6: justin_smith: so that would imply running our own maven repo?

16:45 justin_smith: ro6: or shipping the artifacts and having the client look for them locally - running an actual repo may be more straightforward

16:45 ro6: Justin_smith: my own research led me there too, I don't want to reinvent dependency management.

16:46 justin_smith: yeah, maven is pretty well understood and you are likely using it already :)

16:46 or using it's api via pomegranate / lein at least

16:47 ro6: justin_smith: of course!

16:48 justin_smith: thanks, I think I'll continue down that road. Just wanted to see if anybody had run into issues with that or could suggest some Clojure magic to do it dynamically at runtime with no risk...

16:48 justin_smith: ro6: I use pallet/alembic to load deps at runtime, it is pretty straightforward

16:48 or you can use the lower lefel pomegranate libs that alembic is built on

16:49 ro6: justin_smith: have you ever had two versions of a service running in the same jvm at the same time?

16:49 justin_smith: no, that sounds scary

16:50 that's the kind of thing osgi was designed for though - but at that point a second jvm may be simpler, dunno - unknown territory for me

16:50 ro6: justin_smith: ultimately I think this may start looking like a microservice architecture, we may even eventually have our services running alongside 3rd party stuff, so managing interdependencies could get tricky

16:51 justin_smith: just trying to design for extensibility at the start

16:51 creese: thanks for the assist all

16:52 justin_smith: ro6: if I had to do this, I would start with immutant http://immutant.org/

16:52 kenrestivo: ro6: there's also leaven,

16:52 ro6: kenrestivo: I haven't heard of that one

16:53 kenrestivo: ro6: and system https://github.com/danielsz/system/ leaven is here https://github.com/palletops/leaven

16:53 i'm still trying to get my brain around the difference between all these frameworks

16:53 it sure would be nice if there were a rosetta stone with a simple diff comparing them all

16:54 in the meantime i'm just going to use components in raw form until i understand *why* people created all these wrappers for it

16:54 ro6: The other twist is that the whole thing will be wrapped up in a service wrapper (yajsw) because it has no be cross-platform and restart automatically as a daemon if the client crashes

16:54 Right

16:55 Thanks for the thoughts both of you

16:55 kenrestivo: i think it comes down to: one does thing the pallet way, one does things the puppet way, and one does things some other way

16:56 justin_smith: kenrestivo: I think it would be awesome to get a good number of people together, and make a bracket system, where small teams build something using each of these componenty libs, and then do one on one showdowns in conference with another team, until the two best wrappers make it to the final stand off

16:56 ro6: Ha

16:56 kenrestivo: well, in open source there isn't such a thing.... otherwise we'd all be using emacs :-)

16:57 justin_smith: wait, we aren't all using emacs?

16:57 (joking)

16:58 ro6: I've already mind-melded too deeply with the vi bindings

16:58 kenrestivo: i'm actually bilingual, i use emacs and vi constantly, and for some reason very rarely get mixed up between them.

16:58 ro6: I don't even think up or down anymore, all there is is k and j

16:59 gfredericks: VI stands for Vendor lock-In

16:59 ro6: Maybe someday I'll try the os known as emacs

16:59 justin_smith: gfredericks: while emacs is all about EMbrACes and extendS

17:00 gfredericks: emacs is an excellent operating system lacking only nounah teduc.uchnhuonu nonnoooouth.m

17:00 mearnsh: i switched to emacs after 3 years of vim recently, no bother

17:00 i prefer it

17:00 justin_smith: mearnsh: did you use evil mode?

17:00 mearnsh: nope not even

17:01 justin_smith: (I used viper when I first switched from vi)

17:01 ro6: I bet if I write my client in elisp I can just deploy emacs and use the package manager to solve everything!

17:01 justin_smith: oh god the emacs package management is craptastic

17:01 TimMc: kenrestivo: Or as a friend of mine calls it, bitextual.

17:02 ro6: Or as some call it, promiscuity

17:02 justin_smith: TimMc: they say it's all good, but they find out you used ed, just once, and for life you're branded as "that guy who uses ed"

17:03 TimMc: :-)

17:03 "Johnny Ed-user"

17:03 kenrestivo: know what really throws me off? word. or libreoffice, or in-browser editors. or eclipse/intellij. can't use em, keep instinctively trying emacs keybindings.

17:04 ro6: I actually use a chrome extension that applies vi bindings to browsing

17:05 Really fast once you get used to it. I usually end up crashing my browser by opening too many tabs too fast.

17:06 Anytime editors come up I can't help but think of this: http://xkcd.com/378/

17:06 TimMc: Shambles_: You're talking about PHP, right?

17:07 ro6: I think of http://www.loper-os.org/wp-content/editors.png

17:07 Shambles_: TimMc: No, but something about as bad.

17:31 justin_smith: TimMc: that Vi one from that picture is actually a cool way to make working sunglasses

17:32 TimMc: justin_smith: Not just sunglasses -- it actually focuses as well.

17:33 SagiCZ1: kenrestivo: intellij has predefined profile with emacs bindings i believe..

17:43 justin_smith: SagiCZ1: the problem with "emacs bindings" is nothing ever implements *my* emacs bindings

17:43 though I hear there may finally be a web browser that lets you use iswitchb to select a tab, which sounds awesome

17:47 TimMc: justin_smith: I'm imagining a parallel universe where keybindings could be managed cooperatively and editors could actually share a buffer. Imagine IntelliJ contextual help and autocompletion + Emacs keybindings and structural manipulation.

17:49 justin_smith: TimMc: maybe a modular "content" server that displays the shared (similar to how google wave did things?) and then you connect to it with various tools (emacs, vi, intellij) that send update commands.

17:55 SagiCZ1: justin_smith: yeah.. well intellij is nothing like emacs, so i guess it could only help with some transitioning

17:56 justin_smith: SagiCZ1: fair enough - but I use emacs for the features, and merely tolerate the keybindings :)

17:57 TimMc: I use emacs solely for paredit-convolute-sexp.

18:17 technomancy: <3

18:19 andrewhr: emacs people: do you use emacs for IRC too?

18:19 amalloy: that would be great marketing material. "Google Wave, but for editing text!"

18:20 * gfredericks is using emacs for irc

18:20 andrewhr: gfredericks erc?

18:20 gfredericks: yeah

18:20 justin_smith: amalloy: I liked wave as a collaboration tool

18:20 amalloy: andrewhr: some do, but not all. i'd guess it's something like 60/40 one way or another

18:20 justin_smith: andrewhr: I use erc too

18:21 andrewhr: nice

18:21 * justin_smith watches andrewhr follow up gathering this info with the 0day gnustab exploit

18:21 andrewhr: I want to get more emacsy… despide using Cursive for work (didn’t manage cider to work with cljs)

18:22 justin_smith: org mode is awesome for tracking tasks and organizing ideas

18:22 andrewhr: justin_smith NOES YOU DESTROYED MY HOPES

18:22 u.u

18:22 gfredericks: I started hating work-communication a lot less once I figured out how to use hipchat from emacs

18:23 andrewhr: I have emacs + evil running here, soo… mwahahahaha

18:23 still wondering about remmapping vs using god-mode

18:25 justin_smith: gfredericks: something bitlbee based? or jabber.el?

18:25 gfredericks: bitlbee

18:25 justin_smith: gfredericks: next best thing to convincing everyone to use IRC I guess

18:26 gfredericks: that's a lot of people to convince

18:28 justin_smith: gfredericks: is universal human consensus really that much to ask?

18:29 gfredericks: yes

18:30 SagiCZ1: justin_smith: you could almost start convincing americans to use metric system

18:31 gfredericks: then daylight savings time

18:32 justin_smith: SagiCZ1: did you know that there is a holiday, World Standards Day, and the day we celebrate it in the US is different from the day any other country celebrates it?

18:32 SagiCZ1: justin_smith: hardly surprising ;)

18:33 andrewhr: justin_smith: are you kidding? lol

18:33 justin_smith: http://en.wikipedia.org/wiki/World_Standards_Day

18:33 gfredericks: also we spell "metre" differently even though we don't use it

18:33 andrewhr: your wikipedia-fu was faster than mine

18:34 SagiCZ1: gfredericks: i thought that was british spelling

18:34 gfredericks: wikipedia claims it's co-USA

18:34 justin_smith: andrewhr: you gotta be where the puck is *gonna* be, not where it is now

18:35 gfredericks: is co-USA the same s BIPM?

18:35 gfredericks: what

18:36 justin_smith: "The metre (BIPM spelling), or meter (American spelling)"

18:36 http://en.wikipedia.org/wiki/International_Bureau_of_Weights_and_Measures

18:36 gfredericks: "co-USA" == every country except USA

18:37 justin_smith: got it

18:37 gfredericks: you've probably heard the one about the mathematician that opened a grocery store, and simplified the produce section, replacing coconuts with nuts

18:39 gfredericks: now I have

18:39 kenrestivo: i.e. reading a logfile? and i ultimately want to turn it into an async channel.

18:39 dumb java question here: what InputStreamThing would i use to stream data off of a file, \n terminated, where the file is constantly being updated?

18:41 justin_smith: kenrestivo: maybe take a look at what this does? http://commons.apache.org/proper/commons-io/apidocs/src-html/org/apache/commons/io/input/Tailer.html

18:41 or use it via interop

18:41 kenrestivo: justin_smith: cool, thanks!

18:42 justin_smith: oh, wrong file, one minute

18:42 oh wait, it has the source, it's just really weirdly formatted

18:43 kenrestivo: like 395 looks to be where the real magic is

18:43 kenrestivo: yep, that's the hard part

18:45 justin_smith: I am sure we can make something much nicer with clojure- maybe with core.async and have it put lines on a channel and drop that whole sleep / check cycle

18:46 kenrestivo: i was just going to pull that in via interop, and have the listener fn dump the stuff into a channel

18:47 justin_smith: that works too :)

18:48 kenrestivo: just because i'm not a java guy. for system stuff, i can do things so fast in bash or c, when i hit java it's like running into a wall of molasses for me

18:48 SagiCZ1: when clojure throws stackoverflow error, how can i determine what part of my code causes it?

18:50 gfredericks: by looking at the stacktrace?

18:50 SagiCZ1: the stack trace just has thousands calls to clojure.core or clojure.lang functions

18:51 gfredericks: what sorts of functions?

18:51 there's usually a handful that are repeating over and over again

18:51 so figuring out what the cycle looks like can help a lot

18:52 SagiCZ1: gfredericks: https://www.refheap.com/92347

18:53 gfredericks: that looks like you called map a whole bunch of times

18:53 such as

18:54 ,(reduce #(map (partial + %2) %1) (range 10) (range 100000))

18:54 clojurebot: #<StackOverflowError java.lang.StackOverflowError>

18:54 gfredericks: contrast with:

18:54 ,(reduce #(mapv (partial + %2) %1) (range 10) (range 100000))

18:54 clojurebot: [4999950000 4999950001 4999950002 4999950003 4999950004 ...]

18:55 gfredericks: there are a few scenarios where laziness can end up eating your whole stack once you try to realize something

18:55 SagiCZ1: i have something like (loop [c creatures n 0] (recur (map update creatures) (inc n)) is that wrong?

18:56 amalloy: SagiCZ1: it'll be a problem if you never do anything but update them, yes. if you actually inspect the results of updating, you'll be okay

18:56 gfredericks: I'm having a hard time explaining to myself why this doesn't come up more often

18:56 SagiCZ1: amalloy: yes i just found out exactly what you said, but can you elaborate why is that the case?

18:56 gfredericks: I don't think I've ever seen this specific kind of thing brought up before

18:57 amalloy: SagiCZ1: because you end up with (map update (map update (map update ...)))

18:57 gfredericks: SagiCZ1: do you know how map's laziness works?

18:57 amalloy: none of which does any computation at all; it's all deferred

18:58 and then when you finally ask for an element of that list, a zillion things all collapse into one deep stack

18:58 SagiCZ1: amalloy: i see, thats interesting... when i realize the map in each loop it works fine

18:58 thank you

18:59 gfredericks: SagiCZ1: mapv would also do fine

18:59 ~a zillion things |all collapse| into one deep stack

18:59 clojurebot: Alles klar

19:00 SagiCZ1: gfredericks: mapv returns vector instead of lazy-seq, so and vector cant be lazy, right?

19:00 gfredericks: exactly

19:01 Dragon-ball: http://tinyurl.com/ogzbb82 Buy Dvd Movies Here

19:04 AeroNotix: +b

19:04 mods

19:04 kenrestivo: ~guards

19:04 clojurebot: SEIZE HIM!

19:21 justin_smith: ~goards

19:21 clojurebot: Huh?

19:22 justin_smith: ~gourds

19:22 clojurebot: SQUEEZE HIM!

20:26 Bruce_Wayne: still having trouble with uploading a file

20:26 llasram: Bruce_Wayne: Have you tried it as Batman instead?

20:26 Bruce_Wayne: I have

20:27 llasram: Cool. Now that I have that out of the way...

20:27 Bruce_Wayne: I took it to the batcave and ran science on it

20:27 haha

20:27 * llasram unfortunately has nothing constructive to offer about Web programming

20:27 Bruce_Wayne: damn alright

20:35 justin_smith: Bruce_Wayne: I uploaded a minimal example of file upload working in a compojure app

20:35 Bruce_Wayne: thank you

20:35 what’s the link?

20:36 justin_smith: https://www.refheap.com/92336

20:36 other than that one file, it is a default compojure project made with lein new compojure

20:37 you click a button to select a file, click on the submit button, then the file shows up as plaintext

20:53 azeirah: Where can I find a list of clojure libraries?

20:54 justin_smith: azeirah: clojars.org hosts many of them, and has search functionality

20:54 azeirah: @justin_smith, thanks

20:54 justin_smith: there is also the toolbox site http://www.clojure-toolbox.com/

20:55 also, if you are trying to do a particular thing, it doesn't hurt to check in here and ask what people have tried / if there is an awesome lib for that task that you may have missed

20:55 azeirah: Yeah, I was looking for readable, a library to make lisps a lot more readable

20:56 Can't find it on clojars nor toolbox unfortunately

20:56 Bruce_Wayne: :justin_smith does this work if the file is a pdf?

20:56 justin_smith: does this work if the file is a pdf

20:56 azeirah: It made my introduction to lisps a lot more bearable

20:56 Bruce_Wayne: maybe that is my problem

20:56 justin_smith: Bruce_Wayne: you would want to get a handle to the file rather than slurp it

20:56 Bruce_Wayne: I am

20:56 I use pdfbox and other apache libraries to read it

20:56 I can read it locally

20:56 justin_smith: OK

20:57 Bruce_Wayne: and i have code that works now

20:57 just trying to wire it up for a user on my webapp

20:58 justin_smith: azeirah: oh, so one of those frontends that uses indentation based syntax and then converts it to sexps?

20:58 Bruce_Wayne: when i print out the request ther are not multipart params

20:58 just an empty map

20:58 azeirah: @justin_smith Yeah, as well as a few other small things. It was great imho

20:58 justin_smith: Bruce_Wayne: then your form is wrong, or you aren't using the middleware properly

20:58 azeirah: I remember seeing something like that once, it didn't really catch on

20:59 azeirah: Made lisp a little more python-ish

20:59 I'm talking about this one: http://readable.sourceforge.net/

20:59 Bruce_Wayne: (wrap-multipart-params public-routes)

20:59 seems simple enough

20:59 llasram: azeirah: In my experience you just get used to it, and even prefer it

21:00 justin_smith: azeirah: yeah, I forget the name, it's out there somewhere

21:00 llasram: <3 paredit

21:00 Bruce_Wayne: justin_smith: just like you did it (wrap-multipart-params public-routes)

21:00 azeirah: Hmm, I don't know why parentheses everywhere is preferable :p

21:00 justin_smith: Bruce_Wayne: check out the html I am using for the form, in particular the enctype parameter

21:00 llasram: azeirah: Clojure doesn't use them "everywhere". Generally only for function(-like) application

21:00 justin_smith: Bruce_Wayne: my demo sent me an empty multipart-params map until I set that

21:01 Bruce_Wayne: alright got ya

21:01 llasram: azeirah: Things which are not such (including binding forms and argument parameter lists) use vectors with `[]` istead

21:01 Bruce_Wayne: any chance you know how to set that in hiccup?

21:01 llasram: Explicit maps use '{}' etc

21:01 azeirah: Oh well, I liked it, I'd just like to use it on clojure

21:02 justin_smith: Bruce_Wayne: something like [:form {:enctype "multipart/form-data" ...} [:input ...]]

21:22 Bruce_Wayne: thanks justin

21:22 works like a charm

21:23 justin_smith: awesome!

21:23 funny, after all taht, it was the html form

22:28 loliveira: How to use stuartsierra’s component library with compojure?

22:30 justin_smith: loliveira: compojure is a routing library, the key is integrating component with ring, which is the server library

22:30 loliveira: this gist has a decent example https://gist.github.com/bowmanb/8560704

22:32 loliveira: justin_smith: but this example misses the routing part. =/

22:33 how do I pass the dependencies to my hanlders?

22:34 justin_smith: loliveira: reloading the namespace will suffice to reset the routes, and then restarting the server should make it use the new route definitions. Though I guess you could also define a component that sets up the routes I guess.

22:34 loliveira: what is there in a route that needs to be stopped / started?

22:35 maybe I don't understand what you are doing

22:39 loliveira: justin_smith: I have a system that have 2 compoments, a http-server and a db connection. In the view, I have a function called show-db-data. The route is defined as follows: (defroutes routes (GET "/show" [] (show-db-data)))

22:40 justin_smith: How show-db-data has access to the db component?

22:41 justin_smith: The doc says that I should never pass the system as argument...

22:41 justin_smith: loliveira: in that case, make a component for the db that associates it's connection and any other needed config into the component it returns

22:42 loliveira: see under Usage in this link, with (assoc component :connection ...) https://github.com/stuartsierra/component

22:42 then, another component can hand the db information to the handler creation function

22:43 (by getting that same :connection key out of the component)

22:43 loliveira: justin_smith: hum… so I should not use defroutes?

22:43 justin_smith: you would, but you would invoke it inside the start for that component, I think

22:44 loliveira: wait, actually I was a bit off

22:44 associating :connection is for the component to get it back later, maybe not to share with other components

22:45 but that page I linked shows how to make one component use data from another

22:45 via component/system-map

22:46 loliveira: justin_smith: ok, I will give a try. ty. =)

22:52 justin_smith: loliveira: it's been a while since I checked out the docs for component, I actually like them a lot now

22:52 (inc stuartsierra)

22:52 $ping

22:52 lazybot is down :(

22:52 loliveira: justin_smith: pong

22:53 justin_smith: I was pinging lazybot, who tracks karma, because I was trying to up stuartsierra's karma

22:53 loliveira: justin_smith: oh… =)

22:54 newbie here. =)

22:55 justin_smith: loliveira: yeah, your nick looked unfamiliar

22:56 loliveira: we also have another bot, who is mainly for demonstrating one liners to help explain how clojure works

22:57 ,(map inc (range 10))

22:57 clojurebot: (1 2 3 4 5 ...)

22:57 loliveira: ,(println “hello world”)

22:57 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: “hello in this context, compiling:(NO_SOURCE_PATH:0:0)>

22:57 justin_smith: loliveira: smart quotes!

22:58 your irc client is too smart for your own good

22:58 loliveira: lol

22:58 justin_smith: ,(= \" \“)

22:58 clojurebot: false

22:59 loliveira: I can’t find how to disable them.


23:02 ,(println "Hello world!”)

23:02 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

23:02 justin_smith: loliveira: now it's the other quote on the end I think

23:02 loliveira: ,(println "Hello world!")

23:02 clojurebot: Hello world!\n

23:02 loliveira: viva!!!

23:09 justin_smith: It worked! I https://www.refheap.com/92350

23:09 justin_smith: very nice, I'll make a note of that for when I really try component out

23:12 loliveira: thank you for the help

23:12 justin_smith: np

23:13 so check this - someone who designed a mcdonalds playing piece does not know math http://i.imgur.com/wNEZjrx.jpg

23:13 I decided to calculate that number using clojure...

23:14 https://www.refheap.com/92351

23:14 actually this view is more impressive https://www.refheap.com/92351/raw

23:14 427913 digit number

23:16 TimMc: :-)

23:19 justin_smith: in other news, 427913 digit numbers slow your repl buffer down a little when printed

23:23 loliveira: justin_smith: i don’t get it.

23:23 justin_smith: which part?

23:26 m00nlight: The java interop of java.util.Date in clojure does not contain the time-zone information as Java did?

23:26 justin_smith: ,(java.util.Date.)

23:26 clojurebot: #inst "2014-10-27T03:25:32.548-00:00"

23:26 justin_smith: the time zone is at the end

23:26 the -00:00 part

23:26 m00nlight: Yes

23:26 The output of Java is :Tue Aug 12 22:46:54 SGT 2014

23:26 loliveira: what is a mcdonalds playing piece?

23:27 m00nlight: while the clojure is : #inst "2014-08-12T14:46:54.000-00:00"

23:27 justin_smith: loliveira: oh, here in the US we have a game, mcdonalds monopoly, where you collect playing pieces for prizes

23:27 loliveira: now it makes sense

23:28 m00nlight: So it seems that the java change the utc time to local time-zone, while the clojure interop of java.util.Date does not

23:28 justin_smith: m00nlight: it's the same object, clojure just has a different default printed representation, you can use a formatter to get the rep you like

23:30 ,(.toString (java.util.Date.))

23:30 clojurebot: "Mon Oct 27 03:29:34 UTC 2014"

23:30 justin_smith: m00nlight: if you use that form, it will show your local time zone

23:30 clojurebot is using UTC natively

23:30 m00nlight: justin_smith: Thanks, it seems the .getHour methods return the hour in local time zone

23:31 justin_smith: m00nlight: explicitly calling .toString gets the same default printed rep that java gives

23:31 m00nlight: clojure should not be doing anything java isn't when it comes to constructing Date with 0 args

23:31 (nor should it fail to anything java would do in that case)

23:32 m00nlight: justin_smith: Yes, got it

Logging service provided by n01se.net