#clojure logs

2014-10-26

00:14ghadishaybanman i went down the rabbit hole today
00:15ghadishaybanstarted hacking on clojure.lang.Range (CLJ-1515), decided to revive it as a deftype
00:15ghadishaybandeftype doesn't support java transient fields, so I added that to the compiler
00:16ghadishaybanthen I rejiggered core.clj to load range after deftypes and protocols have been definied
00:16ghadishaybanand now it's time to see if it performs
00:24amalloyghadishayban: what on earth did you need a transient field for in implementing Range?
00:25amalloyanyway, just reimplementing clojure.lang.Range in clojure sounds like a dead end: the future is transducers
00:26ghadishaybanamalloy: hash codes are supposed to be transient
00:26ghadishaybanamalloy: I don't know why, just regurgitating
00:27ghadishaybanthis enables range to work better better with transducers
00:27amalloyi mean, it's clear why: you don't want to waste space on disk caching something that's easily recomputable
00:28ghadishaybansay more words re: dead end?
00:28ghadishaybannot sure I follow you
00:30amalloyghadishayban: 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
00:30amalloyif 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
00:31ghadishaybangosh you are hating so fast
00:32ghadishaybanthere is existing work, tagged for 1.7 to revive c.l.Range (CLJ-1515)
00:32ghadishaybanTim's current impl has a tiny downside, in that it has a 5x performance penalty for existing seq usages of range
00:33ghadishaybanthat is because it doesn't use chunked seqs
00:33ghadishaybanI saw the Range ticket a while back, it is really nice, didn't realize it's yours.
00:33ghadishaybankudos
00:34ghadishaybanI decided to do something similar but with Iterable & IReduce
00:34ghadishaybanas well as CollReduce (this duplication is slightly annoying)
00:35amalloywell, 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
00:35amalloymy windmill-tilting was *invited* and still made no progress
00:35ghadishaybanRange as a transducer doesn't make sense because a transducer isn't a source, but a transformation
00:35ghadishaybanyeah it may be wasted effort
00:36ghadishaybantrying to maintain existing seq usages and also reducible usages is a total PITA
00:37ghadishaybanpersonally I'd rather clojure.core.reducers/range
00:37ghadishayban(that also implemented iterable)
00:38ghadishaybanoh yeah also being a java.util.List
00:38bbloomghadishayban: why can't first/next/more/seq/etc from ISeq and ISeqable, as implemented on a Range object, just implement chunking?
00:38ghadishaybanin core i mean
00:38ghadishaybantotally can
00:38amalloyghadishayban: yeah, being j.u.List was the worst part by far
00:39bbloom,(-> (range) class supers)
00:39clojurebot#{clojure.lang.Obj clojure.lang.Sequential clojure.lang.IPersistentCollection clojure.lang.IMeta java.io.Serializable ...}
00:39bbloomlooking at the full list locally seems quite doable manually
00:39ghadishaybanbbloom: waiting on Tim to see if he updates the patch
00:39amalloybbloom: if you call next, it has to allocate an object; the point of chunking is to avoid that allocation
00:39amalloyi don't see how you can "make next implement chunking"
00:40ghadishaybangimme a second to push up what I have
00:41bbloomamalloy: just saying that the result of next should itself be chunked, in case somebody does (map f (next (range) ....
00:41amalloybbloom: for sure
00:42bbloomamalloy: 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
00:42ghadishaybanmy patch doesn't account for someone doing (rest (range))
00:42ghadishaybanas in it falls back to the regular chunked-seq
00:43bbloomghadishayban: do you have a RangeSeq object?
00:43bbloomor an anon class or whatever
00:43ghadishaybanalthough that could be improved. spent enough time reimplementing fucking grade school counting
00:43bbloomi'd just make a RangeSeq(start, stop, step) and return that from first/next/more
00:43ghadishaybanbbloom: I delegate to the existing range seq impl
00:44ghadishaybanbbloom: now private as range-seq*
00:44bbloomsure ok
00:44bbloomanyway, i'm pretty confident w/ a little elbow grease that patch can be a good perf win and get accepted
00:44rritochWhat 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.
00:45ghadishaybanbbloom: yeah it should be possible to add chunking
00:45bbloomrritoch: evolution
00:45ghadishaybanbbloom: though the one thing I add to it is Long arith, rather than Number
00:45bbloomrritoch: http://clojure.org/lazier
00:45bbloomrritoch: very old page
00:46rritochbbloom: Thanks, checking it now...
00:46ghadishaybanhttps://github.com/ghadishayban/clojure/commit/906cd6ed4d7c624dc4e553373dabfd57550eeff2
00:47quizmehi, can somebody help me with a class loading problem? http://pastebin.com/PukYbX5e I'm really stuck.
00:47ghadishaybanbbloom: amalloy: commit message covers it mostly. feedback would be awesome
00:48bbloomghadishayban: sorry man, i've stared at too much code today. off to bed
00:49bbloommaybe bug me later in the week :-)
00:49ghadishaybanha yeah grade school counting is so interesting though
00:52amalloyghadishayban: i have range PTSD after clj-993. not much interest in reading through it, i'm afraid
00:53ghadishaybanno worries.
00:53ghadishaybantotally understand the patch ptsd
00:54justin_smith,((juxt rest next) [1]) ;; rritoch
00:54clojurebot[() nil]
00:54justin_smiththey aren't always the same
00:56rritochjusting_smith: Thanks, that's a good example though I'm not sure I understand the reasoning behind this particular difference
00:56rritoch,(type (next '(1 2 3 4)))
00:56clojurebotclojure.lang.PersistentList
00:56rritoch,(type (rest '(1 2 3 4)))
00:56clojurebotclojure.lang.PersistentList
00:57rritoch,(type (rest (map identity '(1 2 3 4))))
00:57clojurebotclojure.lang.LazySeq
00:57rritoch,(type (next (map identity '(1 2 3 4))))
00:57clojurebotclojure.lang.Cons
00:57rritochWhy would next be returning a cons?
00:58justin_smithrritoch: the difference is explained in detail in the article bbloom shared, next is about being lazier
00:58ghadishaybanrritoch: ,(source map)
00:58ghadishayban,(source map)
00:58clojurebotSource not found\n
00:58ghadishaybanmap is introducing the cons
00:59rritoch,(type (map identity '(1 2 3 4)))
00:59clojurebotclojure.lang.LazySeq
00:59rritochI specifically used map just to get a lazyseq to see the difference as per the docs about lazyness
01:00rritochBut if next is supposed to be lazier why is rest the one returning a lazyseq?
01:00justin_smithrritoch: look at the source of map, it has lazy seq wrapping cons
01:02dopamean_is there a way to have leiningen check a github repo for the source of a dependency ?
01:02dopamean_i wrote i library id like to use and its not on clojars or anything
01:03justin_smithdopamean_: you can use lein install to make it available locally, or lein push to put it on clojars
01:03dopamean_cool. thanks.
01:03justin_smithdopamean_: for super advanced usage there is also setting up your own maven repo
01:03rritochjustin_smith: Ok, I guess the better question is, why does seq unwrap a lazy sequence?
01:04rritoch,(type (lazy-seq (cons 1 '())))
01:04clojurebotclojure.lang.LazySeq
01:04rritoch,(type (seq (lazy-seq (cons 1 '()))))
01:04clojurebotclojure.lang.Cons
01:05rritochIt would seem to me that rest is lazier since it maintains the lazy type.
01:06justin_smithrritoch: 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
01:06justin_smithyeah, rest is lazier
01:06justin_smiththe source of my confusion is that rest used to do what next does now iirc
01:08rritochjustin_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?
01:08rritochjustin_smith: But in cases where filter functions don't utilize bound variables, rest is bettee
01:09rritocherr, better
01:09justin_smithrritoch: well, next is not eager
01:09justin_smithit's just slightly more eager
01:10justin_smith,(do (rest (map println (iterate inc 0))) nil)
01:10clojurebot0\n
01:10justin_smith,(do (ext (map println (iterate inc 0))) nil)
01:11clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ext in this context, compiling:(NO_SOURCE_PATH:0:0)>
01:11justin_smith,(do (next (map println (iterate inc 0))) nil)
01:11clojurebot0\n1\n
01:11justin_smithit realizes 1 more element than rest does
01:16rritochjustin_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
01:17rritochjustin_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.
01:19TEttingerI wonder if a standardized version of (first (filter ....)) called something like "search" would be a good idea
01:19TEttingeror even take-when
01:19TEttingeras a counterpart to take-while
01:21justin_smithgimme, as counterpart to get
01:22ghadishaybanTEttinger: sometimes the predicate can be rewritten with some
01:22TEttingerright, I usually forget some
01:23justin_smith,(some even? (range))
01:23clojurebottrue
01:23justin_smith,(some #(and (even? %) %) (range))
01:23clojurebot0
01:23ghadishaybanthing is some returns the result of the predicate
01:23ghadishaybanrather than the element that satisfied it
01:23justin_smithyeah, a version that just returns the thing would be handy
01:24justin_smith(though the workaround is not all that onerous)
01:24ghadishaybanit can't be done.
01:24ghadishayban^ that's the batsignal for someone to prove me wrong
01:24justin_smithhaha
01:28dysfunis there a non-horrible way of automatically memoizing file contents at the point of use unless the file has been updated since last read?
01:28dysfunevery way i can think of would not count as 'non-horrible'
01:30TEttingerdysfun, sounds fairly OS-specific
01:31dysfunnot really. i'm quite happy for it to hit the disk every time i call
01:31dysfunbut only to check metadata
01:31justin_smithdysfun: I made one in my spawning-grounds lib that is OS agnostic https://github.com/caribou/spawning-grounds
01:31TEttingernice, justin_smith
01:31dysfunoh, *you're* the guy behind caribou
01:32justin_smithdysfun: just a hired hand
01:32justin_smithnot the founder
01:32TEttingeris it guy or guys behind caribou?
01:32dysfunah right
01:32justin_smiththough I am the only one working on it now that we all got layed off
01:32dysfuni really wanted to like caribou
01:32TEttingercaribou looks good. what happened with layoffs?
01:32justin_smithdysfun: me too :(
01:33justin_smithTEttinger: the company got bigger, moved up to clients that are bigger, thus: have they own stack, their own devs, etc.
01:33dysfunthe least-worst option i've found was luminus. but only because i used half of those things anyway
01:33justin_smithgreat for the company, bad for our attempts to use clojure
01:39rritochSo, 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?
01:42rritochI 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.
01:42rritochOr something like that, I'm too lazy to check the actual code right now.
01:44rritochOk, just looked it up, I'm using LinkedBlockingQueue but it seems I could use the sequeue function on it.
01:50justin_smithrritoch: maybe you want clojure.lang.PersistentQueue/EMPTY
01:50dysfuni'd be inclined to use a PersistentQueue of promises to get blocking
01:54rritochdysfun: 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.
01:55dysfunheh
01:55dysfunperhaps atom notifications?
01:56justin_smithcore.async is a fun way to do workers on queues
01:57dysfunawait-for looks handy
02:06rritochdysfun: 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.
02:08rritochdysfun: 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.
02:09justin_smithrritoch: in core.async this is done via alts! or alts!!
02:10rritochjustin_smith: I don't have the option of async processing
02:10justin_smithone channel will return a "stop everything" message, the other your result, and then you act on the first one that gives you a value
02:11justin_smithrritoch: not even bounded async with a timeout?
02:11rritochjustin_smith: I think I already mentioned this, but I tried to add asynchronous processing and the code was all removed by my boss.
02:11justin_smithoh, I did not see that
02:11rritochIt was a few days ago that I mentioned it
02:12rritochMy work constraints are severe when dealing with code in common libraries, and this queue is in a common library.
02:14rritochI'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
02:15bodie_anyone played much with clojurescript reactjs libs like Om? I'm just picking what to start in on and looking for input :)
02:15dysfunom is pretty cool
02:16dysfunand it's been made really efficient too
02:16dysfunit's faster than pure reactjs
02:17bodie_yeah it seems a little more featureful than the other cljs react options
02:17bodie_from what I've seen anyway, which could be good or not
02:18dysfunyou'll either love it or hate it, but if you love clojure, probably love it
02:18bodie_:D
02:19bodie_if I hate it, I'll check myself before I wreck myself and take a look at Reagent
02:19dysfunbe aware there's a reasonable learning curve because it's still fairly new and the docs aren't there yet
02:24rritochIt seems agent doesn't directly provide a means to interrupt the processes
02:25rritochBut 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.
02:25justin_smithrritoch: 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
02:26justin_smithrritoch: there is also (shutdown-agents) if you are not using that already
02:27justin_smithoh, now I see you mentioned it already above
02:27rritochjustin_smith: I am, but shutdown-agents doesn't call interrupt, so it doesn't cause the blocking request to the queue to return.
02:29dysfunwhat you need there you see is transactions
02:29dysfunor at least some way of indicating responsibility for the job
02:29dysfunrabbitmq has some awkward acknowledgement dance
02:29rritochThere 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.
02:30dysfunbut 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
02:31dysfunso 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
02:31rritochdysfun: I understand that, but these are blocking because there is no data in the queue
02:33rritochdysfun: 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
02:33dysfunseems to me you could poll quite infrequently and it would be fine
02:33dysfunhave you investigated a back-off algorithm?
02:34rritochdysfun: I'm polling at 22ms to ensure that to the end user it appears to be instant.
02:34dysfunright. 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.
02:35justin_smithrritoch: 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
02:35dysfunbonus: you can very easily construct a lazy list of the times and iterate through them
02:36dysfuna nil sentinel value seems like an easy fix
02:36rritochjustin_smith: Now that is an awesome solution that we haven't considered
02:36TEttinger(inc justin_smith); again
02:36lazybot⇒ 104
02:36rritochjustin_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.
02:37justin_smithrritoch: fair enough - and if that is already a non-sto-case then you could use ::stop-drop-and-roll
02:37justin_smithor whatever
02:38dysfun:please-dont-accidentally-create-a-keyword-with-this-name-or-bad-things-will-happen
02:38rritochWell, either way. I still think there should be a means of interrupting agents
02:38justin_smithdysfun: well that's what the extra : helps with :)
02:39rritochBut for this particular case putting nils, or some other "stop" instruction into the queue would solve the issue.
02:39dysfun::ugly-hack-pretend-i-dont-exist :)
02:39dysfunoh, you could namespace it
02:40dysfun:queue-sentinel/SHUTDOWN
02:40TEttinger,(keyword ": : : \u0000")
02:40clojurebot:: : :
02:40TEttingerbetter,
02:40justin_smithrritoch: 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))
02:40TEttinger,(keyword ":\u0000:")
02:40clojurebot::
02:40justin_smith,(.isInterrupted (Thread/currentThread))
02:40clojurebotfalse
02:40justin_smithdysfun: dude, that is what ::kw does
02:40justin_smith,::kw
02:40clojurebot:sandbox/kw
02:41dysfunoh, right
02:41justin_smithrritoch: 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
02:42justin_smithit's not a clojure limitation, but a jvm one
02:43rritochjustin_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.
02:44rritochEither 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.
02:46dysfunhrm, now that SHA-1 is broken, what should we use to hash files to detect corruption SHA-256?
02:46dysfuni suspect SHA-1 is probably 'good enough' for these purposes
02:49justin_smithdysfun: if your enemy is simple entropy, sha-1 should be good enough
02:49justin_smithbut if you have reason to suspect tampering, then you need to work a bit harder
02:50rritochSHA-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)
02:52rritochAnother agent issue I've run into is the need to know if all agents are blocking
02:52rritochThis again I've solved with polling
02:53rritochBut 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.
02:56rritochIf 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.
02:57TEttingerXeon/PHI, eh?
02:57rritochYeah, they're pushing out about 3 teraflops
02:57RaynesTEttinger: Motherf*cker. I've been pinging you for two weeks.
02:58RaynesWe gonna have to take this outside?
02:59rritochRight 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.
03:00dysfunjustin_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
03:00arrdemwhat are we breaking out the PHIs for?
03:00TEttingerRaynes, hey
03:00rritochR9 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
03:00RaynesTEttinger: Does you has a bot running on quakenet in a rougelike channel that periodically posts to refheap?
03:00TEttingeryes
03:01RaynesOkay.
03:01TEttingerwhy?
03:01clojurebotwhy is the ram gone
03:01rritochThis is related to my comment that SHA-256 will probably have a collission within the next 10 years.
03:01RaynesJust trying to confirm it's you. I originally thought it was spam because some of it was rape jokes and other unsavory shit.
03:01RaynesBut it's a totally reasonable usage of refheap, so ++ :P
03:01TEttingeryeah we try to quotegrab people saying bad things so they realize it's on the web forever
03:02RaynesBadass.
03:02TEttingerit's steadily improved the channel
03:02arrdemballin
03:02RaynesThat's what I dreamed refheap would be used for.
03:02dysfunyou've written a bot to try and shame people into being decent?
03:02arrdemI'll bet it has...
03:02RaynesYou're a scholar and a gentleman.
03:02rritochI 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
03:02Raynesamalloy: ^ The mystery is solved.
03:02TEttingerdysfun, no I wrote it to replace the previous bot that left
03:03rritochEither way, 2 teraflops with 4 teraflop "spikes" is more than enough for anything I need to do.
03:03TEttingerthere are still unsavory sorts in the channel, but they're getting less attention
03:03rritochBut theses PHI's having intel architecture do have my attention
03:03TEttingernihilanth in particular has become a veritable computer business professional
03:04dysfunbecause when i think of gaming, i immediately think of professionalism
03:04rritochI 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.
03:05TEttingerrritoch: the $1700 price tag seems quite heavy for such early tech
03:05TEttingerthen again, if they do take off, wowza
03:05arrdemtable top gaming is very professional until the dice start rolling :P
03:05rritochTEttinger: That isn't much more than what i paid for the 2X 280X's
03:05dysfunrritoch: how awesome would it be to have one under your desk and just send work off to it as needed?
03:06justin_smithdysfun: bonus - also a foot-warmer
03:06rritochWell, 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.
03:06dysfunback when i had a dog, he was a pretty good foot-warmer too
03:07rritochBut as I said, I still haven't located any documentation for it so I don't know what it can or can't do.
03:07dysfunbut i'm thinking something about the size of the new mac pro with all the cpu resource you'd ever need in it
03:07RaynesTEttinger: Could you give it an actual user account though?
03:07TEttingerif you could get hardware virtualization support for those Phis, create 57 VMs on one machine, hot diggity...
03:07TEttingeruh, sure, how would I do that with a lazybot?
03:08Raynes&(range 1000)
03:08lazybot⇒ (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
03:08RaynesOKAY WELL I'M SPESHUL.
03:08rritochTEttinger: Better yet, rewriting the leiningen compile process to use separate JVM's for each file and we'd have nearly instant compiles *evilgrin*
03:08RaynesTEttinger: You can pass an API Key. I believe the docs show you how to do that.
03:09TEttingerI haven't modified that part of lazybot, I'll take a look
03:09dysfunrritoch: did someone say "worker thread problem waiting to happen" ? :)
03:09RaynesTEttinger: Wait, there's no plugin that captures bad things and posts them to refheap
03:09RaynesYou had to write that yourself lol.
03:10TEttingerI use the existing refheap paste of the clojure eval
03:10rritochdysfun: 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
03:10TEttingerand when I did it, it was... a year ago or more
03:10RaynesOh
03:10RaynesI see
03:11dysfunrritoch: not everything about the jvm is sweetness and light.
03:11RaynesTEttinger: I'll add a tthing.
03:11Raynesthing*
03:11TEttingerRaynes, 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)
03:12Raynes<3
03:12RaynesI started at like 14 though.
03:12dysfunthe internet has gotten a lot more helpful since i started programming
03:12TEttingeryeah, I guessed around then
03:12TEttingerminecraft is definitely better documented for kids and total beginners than clojure was at the very start, I would think
03:13TEttingerI also mentioned the Oak quote about "Java is designed with average programmers in mind"
03:15rpauloI dislike that generalism about programming languages
03:16dysfuni don't think that's subjective. it was designed to ensure a certain type of safety that the average programmer may find helpful
03:16rpauloif a programming language makes you think less about concurrency issues, would it be fair to say "designed with average programmers in mind"?
03:16TEttingerrpaulo, well it was the author of the language that became java who said it...
03:16TEttingerit was on his mind, certainly
03:16dysfunyou don't design java if you're looking to implement something like clojure
03:16rpauloyes, but it needs context and the context is in comparison to C
03:17TEttingeralthough they did nab one of the scheme designers to do java's generics, IIRC
03:17rpaulothese days I suppose it's harder to say that about java
03:17TEttingeryeah, java is good for beginners because of the wealth of resources, but the same could be said for C#
03:17dysfunbecause they've added so much to the language?
03:18dysfuni don't think java is that good for beginners. it's huge
03:19dysfunthe reason i like clojure and i don't like java is that clojure is actually a reasonably small language to do most things
03:19dysfunit only gets sketchy where java gets involved imo
03:20TEttingertbh, 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.)
03:21dysfunthis 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
03:21TEttingerclojure would be overwhelming at the start for me, even though it comes very smoothly now
03:21Renato_Ferreirafor 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
03:21TEttinger(doc map)
03:21clojurebot"([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."
03:22dysfunyeah, but when you learned clojure, you already knew other languages that suggest OO approaches to you
03:22TEttingerdysfun, actually I had learned a bit of haskell first
03:22dysfuni'm teaching a friend clojure tomorrow. he's never programmed before. this should be interesting
03:22TEttingerdysfun, you may need to start with just "how to run leiningen"
03:23rpaulodysfun: 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
03:23dysfunyup
03:23TEttingerand before that, "this is the terminal, use cd to change directory"
03:23rritochdysfun: 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.
03:23dysfuni 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
03:23rpaulodysfun: he found it interesting, but I don't think he followed up on it
03:24TEttingerdysfun, yeah lighttable is great, when you aren't using limited thread things like swing or LWJGL
03:24Renato_Ferreirais it worth to use lighttable instead of sublime?
03:24TEttingeryes.
03:24dysfunrpaulo: 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)
03:25TEttingerI personally use NightCode because I can't effectively use the instarepl in LightTable with an OpenGL game
03:25dysfunTEttinger: he wants to build a webapp. and have you experienced the horror of javafx and nrepl yet? that was tedious to work around
03:26TEttingerI'm not going near JavaFX, it looks like a nightmare of meat and clowns
03:26dysfunwell 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
03:26dysfunwell, if you're going to swap one back in, anyway
03:26TEttingergeez...
03:27dysfunby that time i'd spent half a week figuring out how to make it all work together
03:27rritochHave any of you tried libGDX via clojure? That is the direction I'm considering heading since JavaFX is still bug-soup.
03:27TEttingerrritoch, yes, I use it
03:27TEttingerplay-clj is an excellent binding
03:28TEttingerlibgdx is highly reliable at this point, though updating is occasionally a hassle
03:30dysfuni think most of my problem with lighttable at this point is that i haven't mapped a lot of keybindings i use in emacs
03:30rritochCool, 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.
03:30vmarcinkohello 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?
03:30vmarcinkosince it doesnt have syntax such as
03:31vmarcinko(defmethod mymulti :somevalue (fn [..] ...))
03:31Renato_Ferreirarritoch: I have only used it with Java so far, but on the forums there's a pretty popular game made with clojure
03:31vmarcinkobut (defmethod mymulti :somevalue [...] ...))
03:32Renato_Ferreirai think it's called Bounce Away
03:34rritochWell, 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.
03:35TEttingerrritoch, yeah libgdx has something called scene2d.ui that's quite good once you figure out how to make custom skins
03:35rritochOriginally 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.
03:36rritochWhat 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.
03:36TEttingerdayumn!
03:37justin_smithlibGDX as an OSGi bundle really sounds like another mess waiting to happen
03:37TEttingeryou 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
03:37TEttingerlibgdx currently uses gradle with maven artifacts to distribute
03:37TEttingerit has native code as well
03:38rritochjustin_smith: which is exactly why I'm waiting to add libGDX support, having two giant messes to deal with concurrently would be nearly impossible.
03:39TEttingerwhen 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"
03:39rritochBut 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.
03:40TEttingergood idea. libgdx itself uses a lot of abstractions to better support touch-based UIs on android
03:40TEttinger(you can treat a touch like a mouse click with no hover)
03:56rritochIs there an easy way to catenate the columns of 2 lists? ex. (somefunc '(("A" "B" "C") ("a" "b" "c"))) => ("Aa" "Bb" "Cc")
03:58rritochI 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.
03:59rritochI'm thinking this must be an ideal case for zipmap
04:00Raynes&(apply map str '(("A" "B" "C") ("a" "b" "c")))
04:00lazybot⇒ ("Aa" "Bb" "Cc")
04:01rritochOk that is clearly awesome
04:02rritochRaynes: Thanks.
04:02Raynes8^)
04:27dysfunthe 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?
04:33borkdudehas anyone ever made an animation or visualization of the shared tree structure of persistent data structures in a small program?
04:37zoldardysfun: 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
04:38zoldardysfun: the approach with var would be needed if code and tests were mixed together in the same directory
04:39dysfunyes, that's exactly what i want to do
04:39zoldarah
04:40dysfunso 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)
04:40dysfunbut it's a fugly solution and midje documents this variable you can bind but doesn't say how
04:40zoldardysfun: maybe this will help: https://groups.google.com/forum/#!topic/clojure/mJBRPQct9x4 - last answer by Phil
04:41zoldarouch, even this didn't work, just read rest of the answer myself
04:42dysfuni found that *load-tests* is the comparable clojure.test variable, but i haven't seen a means to setting that either
04:43TEttinger(inc Raynes); for good measure
04:43lazybot⇒ 52
04:43dysfunbrilliant
04:43dysfuni'm just going to stick with my macros
04:43llasramdysfun: Are you using Leiningen?
04:44TEttingerborkdude, I saw one in an explanation of them as part of a talk someone gave... no idea where it was
04:44dysfunyes, i'm using leiningen
04:44borkdudeTEttinger I've seen the article of hyPiRion. But maybe someone made a "live" visualization of in memor instances
04:45TEttingerhyPiRion: do you still have the sources used to generate the images in that talk, if there were any?
04:45llasramdysfun: You might be able to use https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L251-L256
04:46llasramAlthough that may only work for vars the core Clojure runtime defines...
04:46dysfunwhich this isn't
04:47llasramRight
04:48dysfunthese are my fugly macros: https://www.refheap.com/92321
04:49dysfunuse 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
04:50llasramdysfun: If you have a core "configuration" type namespace,
04:51llasramyou could do the same sort of "environment" detection there and `alter-var-root` the relevant var(s)
04:51dysfuni'm not convinced that's any better
04:51dysfunit's less easily reusable
04:51llasramReally? It could be a tiny lib you just depend on in every namespace
04:52llasramSo it's a bit of out-of-project code, with only the `require`ment as repetition
04:52dysfuni.e. i'd be able to get rid of the macro invocation at the top level
04:54llasramAnd the per-ns definition of the `nil-macro`s
04:54dysfunokay, i'll have a look at that now. thanks.
04:55dysfunhrm. can i exclude midje during production build through lein and still use ns/:require to include it?
04:55llasramEr, no
04:56llasramThis approach means you'd be depending on it. Otherwise the vars wouldn't exist to set.
04:56dysfunhrm. that's a different kind of evil
04:57dysfunon the other hand, it's not that big and disk and bandwidth are cheap
04:57dysfunactually, there's another approach
04:57llasramOr you could always have out-of-line tests like a normal person ;-)
04:58dysfunif 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
04:58dysfunso i'm depending on something much smaller in production
04:59llasramYeah, you could do that... It seems unexpected that you'd need to
04:59llasramDoes marick document how he does in-line tests?
04:59llasramI thought that he dogfooded that feature
04:59dysfunonly that i should bind a specific variable
05:00llasramSeems simplest to just do it however he does, or maybe communicate with him and e.g. pitch the midje-dummy approach
05:00dysfunpersonally i'm thinking that he should just detect the environment from leiningen
05:01piranhahi 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?
05:01llasramIt seems relatively benign here, although in my experience that way ultimately leads only to madness and death
05:01dysfunheh
05:02llasramJust 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
05:03dysfunthis being an open source project that deals in PII, i don't think so :)
05:03llasramdysfun: fair enough
05:03llasrampiranha: not quite following. Can you be more concrete?
05:03dysfunhow fortunate to skip that particular variant of hell
05:04piranhallasram: 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. :)
05:05piranharight now I'm using FixedThreadPool, which seemed as a simplest way
05:05piranhabut it seems I have to build some locks or maybe use a separate library...
05:05dysfunthis is actually the perfect use of a lock
05:06piranhayeah, but the thing is that I need to wait until latest notification
05:06piranhado I just sleep in my thread? :\
05:06dysfunthat was the question i was just typing :)
05:06piranha:-))
05:06llasrampiranha: Use a Clojure agent
05:06piranhahm!
05:06piranhanever used them, they are not present in cljs and I'm mostly doing that :)
05:06piranhathanks, I'll look at that
05:07piranhaare they like ThreadPool as well? :)
05:07dysfunagents are allocated from a thread pool
05:07llasrampiranha: Clojure agents provide uncoordinated serialized access to a piece of state
05:07llasramYou can queue up any number of operations against the state, which then run and update it one-at-a-time
05:08piranhallasram: hmm... can I tell them to run just the last one?
05:08piranhaI don't really need all the intermediate results...
05:08piranhaand it's going to be making a lot of queries against dropbox api
05:10piranhamaybe it's better to use http://clojurequartz.info/ in the end?
05:11piranhait seems their jobs have keys and I guess if you supply same job few times last one is going to win
05:13dysfunan atom and a map seems like a simple solution
05:14dysfunyou'll r
05:14dysfunun at most one extra job in the time it takes to run a job
05:14llasramYeah, it seems like you want effectively just producer/consumer with the consumer taking the batch of all available messages whenever it runs
05:15llasramI 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
05:16piranhahm
05:17piranhaok, I'll experiment a bit then
05:18borkdudeis there something like difform for clojurescript?
05:22SagiCZ1can i get class object just from the class name as in java's "classname.class" ?
05:29borkdudeSagiCZ1 just the class name gives the class object, like java.util.Date
05:29borkdude(let [class-obj java.util.Date] ...)
05:32SagiCZ1borkdude: do i have to use fully qualified names?
05:32borkdudeSagiCZ1 only if you have not imported them
05:34SagiCZ1thank you
05:43piranhallasram: regarding agents: what would I use their state for? :)
05:43piranhai.e. I'm not exactly sure how to model my jobs, they are for side-effects only
05:48dysfunyou use the piece of state to represent the identity of eg. a file
05:49piranhahmm
05:49dysfunso an agent becomes representative of that file
05:49piranhaso I have to have like hundreds agents?
05:49dysfunergo the serialisation happens on a per file basis
05:49dysfunagents aren't particularly heavy
05:49dysfunthey're only running when something has to do something
05:50piranhaso maybe I should have an atom of agents?
05:50piranhawhere I add new agents when I have to download new stuff
05:51piranhaand agents themselves then will remove from there when they are done?
05:51piranhaor is this bad idea? :)
05:51dysfunhang on, you shouldn't do i/o in agents
05:51piranhahm, where do I do i/o?
05:52dysfunyou could use a future with an agent
05:53dysfunhrm, i'd have to think
05:54piranhaheh, that sounded like a quite simple thing to me initially, and now it seems like it is not :)
05:56dysfunno, rereading the clojure documentation, i'm wrong. io is fine in agents, but you'll want to use send-off
05:59SagiCZ1how can i programatically acheive the same thing as is "load file in repl" ?
05:59dysfunyou're going to have to expand on that
06:02SagiCZ1ok, 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
06:03dysfunyou can't do that. but you can require that namespace in your defmulti file and then (def foo other-ns/foo) for them
06:03llasrampiranha: 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
06:04dysfunor at least that *might* work
06:05dysfunbut it'd probably be easier just to include the defmulti file from the defmethod file
06:05dysfunpossibly reexporting
06:05llasramI think their problem is the other way around
06:05llasramSagiCZ1: There isn't any magic. You just `require` the implementation namespaces somewhere
06:06llasrame.g. your entry-point namespace should `require` all the implementation namespaces you'll need
06:06SagiCZ1yeah the defmulti file could require all the defmethods right
06:07llasramWell, you probably shouldn't do that
06:07llasramThe implementation namespaces depend on the interface namespace, so that would introduce a circular dependency
06:07llasramBut you can have yet another namespace which requires all of them
06:08SagiCZ1llasram: mm.. thats not very pretty
06:09llasramI'm not sure what else you'd want
06:09llasramIn OO languages you don't expect loading a parent class to load every subclass that's defined anywhere else ever
06:09llasramPretty much the same deal here
06:10SagiCZ1well there is one namespace with multiple defmultis.. and multiple files which group the implementations of the defmulti via defmethods
06:10SagiCZ1so when i add a new file with new implementations, i should require it from the entry-point namespace right?
06:11llasramYes
06:12SagiCZ1llasram: ok and is there a way to require all namespaces which start with com.example.* or do i have to list them all?
06:12llasramYou *could* do something where you enumerate resource paths starting with a certain prefix then load all the corresponding namespaces
06:13llasramIt'd be fiddly though
06:14SagiCZ1and the question above?
06:14llasramI pre-answered it -- they're the same thing
06:15SagiCZ1and can i require it but not refer any symbols?
06:15llasramI'm afraid I don't follow
06:15SagiCZ1well all it takes now is to tell my editor to load the file in repl.. thats not the same as what require does
06:16llasramUm. Yes it is
06:16llasram(doc require)
06:16clojurebot"([& 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
06:16llasram(doc load)
06:16clojurebot"([& 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."
06:16SagiCZ1oh.. i apologize
06:17llasram~guards
06:17clojurebotSEIZE HIM!
06:17SagiCZ1so my main entry function could get a list of the namespaces (implementations) that it needs to require and just call require on each one
06:17llasramIf you've got a large number of them you want to be always loaded, then that seems like a not-unreasonable solution
06:18SagiCZ1there could be about 20-30 of them
06:21llasramOOC why some many?
06:21llasrams,some,so,
06:22SagiCZ1the defmulti is called update.. and the thirty implementations represent thirty different ways to update something
06:22SagiCZ1im not sure if i should separate them into different namespaces
06:23llasram`update` a datastructure, like `update-in`?
06:24SagiCZ1yeah
06:24SagiCZ1more like assoc
06:26SagiCZ1is that a bad design idea?
06:29llasramWell, depends on why you need it :-)
06:29llasramThere's certainly precedence in e.g. Common Lisp
06:30llasramAnd ClojureScript implements most such core operations in terms of protocols, so they are extensible to other datastructures which have near-enough semantics
06:31SagiCZ1yeah 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
06:32llasramWhat are the actual things you are implementing this for?
06:36SagiCZ1trading 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
06:37piranhallasram: 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 :)
06:38llasramSagiCZ1: Ahhh, ok. That makes sense.
06:38llasrampiranha: cool beans
06:39SagiCZ1llasram: good to hear, thanks for help
06:39llasramnp and good luck!
07:00otfrom,(= {:foo 0.1} {:bar 0.1})
07:00clojurebotfalse
07:00otfromthat is not what I expected
07:00otfrom,(= [0.1 0.2] [0.1 0.2])
07:00clojurebottrue
07:00otfrom,(= ["foo" 0.1] ["bar" 0.1])
07:00clojurebotfalse
07:01otfromhmm... googling for this is going to be hard. Any suggestions?
07:01SagiCZ1whats the issue?
07:02SagiCZ1how could the map be the same when they have different keys?
07:03SagiCZ1,(= (map values [{:foo 0.1} {:bar 0.1}]))
07:03clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: values in this context, compiling:(NO_SOURCE_PATH:0:0)>
07:03SagiCZ1,(= (map vals [{:foo 0.1} {:bar 0.1}]))
07:03clojurebottrue
07:03SagiCZ1there u go
07:05hyPiRionTEttinger: I don't have animation, but I certainly have visualisation. It's in C though: https://github.com/hyPiRion/persistencia/tree/master/persistent-vector
07:05hyPiRionBut if there's interest, I can probably make something for Clojure.
07:05TEttinger(inc hyPiRion)
07:05lazybot⇒ 53
07:06TEttingerthat's neat
07:06otfromsorry, I should go back to sleep really.
07:06TEttingerborkdude, any interest?
07:07borkdudeyeah :)
07:08borkdudeI was thinking something in ClojureSCript with React
07:09borkdudeif I had more time on my hands I would try it myself, but not so in the coming few weeks
07:10hyPiRionI 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.
07:11hyPiRionIf not, I'd have to learn tree layout algorithms and how to draw in the browser.
07:13borkdudehyPiRion could also keep it simple and just render a png and show that
07:13hyPiRionyeah, that'd work too
07:14borkdudesvg
07:14SagiCZ1hyPiRion: if you think about drawing in browser, checkout html5 and svg
07:15borkdudehmm https://code.google.com/p/canviz/
07:23rritochUnder windows is there a hotkey to kill a repl command that's in an infinite loop?
07:25rritochI'm trying to see if there's any advantage to seque vs (future (dorun ...)) and ctrl-c won't stop a (repeatedly #(or 5))
07:25rritochAmazingly it has maxxed all my cores also
07:26rritochAnyhow, I just killed the shell
07:27borkdudectrl-d maybe? dunno
07:27rritochborkdude, thanks I'll try that next time
07:33rritochIs there a bug in seque? When I ran (def a (seque 5 (repeatedly #(or (println ".") 5)))) it output 6 dots, when I expected 5?
07:37rritochborkdude: ctrl-d didn't work either, but anyhow
07:40rritochHere's an example that simply doesn't make sense to me
07:41rritoch,(let [a (atom 0) b (seque 5 (repeatedly #(swap! a inc)))] @a)
07:41clojurebot0
07:41rritochHmm
07:41rritochIn mine it returned 7
07:42rritoch,(let [a (atom 0) b (seque 5 (repeatedly #(swap! a inc)))] (Thread/sleep 500) @a)
07:42clojurebot0
07:43rritochVery odd, but I get 7 every time locally as long as I sleep
07:45llasramrritoch: seque is pretty weird and old. I've never seen it used in "real" code myself
07:47rritochOk, well either way it seems insanely broken, even with a take 500 I'm still getting 7 as a result
07:47rritoch,(let [a (atom 0) b (seque 5 (repeatedly #(swap! a inc)))] (take 500 b) (Thread/sleep 500) @a)
07:47clojurebot0
07:51rritoch,(let [a (atom 0) b (repeatedly #(swap! a inc))] (future (dorun 500 b)) (Thread/sleep 500) @a)
07:51clojurebot#<SecurityException java.lang.SecurityException: no threads please>
07:51llasramMaybe lazybot allows futures... do not recall
07:52llasram&@(future :maybe?)
07:52lazybotjava.lang.SecurityException: You tripped the alarm! future-call is bad!
07:52llasramnope
07:52llasramToo dangerous
07:52rritochWell, either way, ^^^ returns 501 locally, which is much closer to what I expected
07:53rritochBut dorun is still running 1 too many times
07:55llasramrritoch: It's a bit counter-intuitive, but `dorun` notes that it forces the "successive nexts"
07:55rritochActually, I guess it matches the docs, but doesn't make sense
07:55llasramOTOH, using lazy-seqs for side-effects is generally a bad idea
07:56llasramWhat's your ultimate goal?
07:56rritochYeah, I'm just doing it for testing purposes to see if there is any benefit to seque vs running dorun in a future
07:56rritochseque seems to use an agent to fill the queue so fundamentally it's similar
07:56llasramSure, but what's your goal then?
07:57rritochAt the moment, just to improve my clojure coding skills :)
07:57rritochThere were a lot of functions in clojure.core that I wasn't familiar with
07:57llasramAh
07:59rritochI 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.
08:00llasramI really don't think it is useful, honestly
08:01llasramBetween directly accessing the j.u.c APIs and core.async, seque just seems error-prone and weird
08:05mi6x3mhey clojure, is it a good idea to use eval in macros to evaluate forms in the context of let bindings?
08:05mi6x3mlike for instance I have something similar
08:05mi6x3m(let [x 5] (first (lazy-seq (println x))))
08:05llasrammi6x3m: it is pretty much the opposite of a good idea
08:05llasramIn fact, it is not actually possible, if I understand you correct
08:06llasram*correctly
08:06mi6x3mwell the idea would be to eval println x in the context of x = 5 in this case
08:06llasramYes, 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'
08:07mi6x3mllasram: ignore it's a macro for a moment
08:07mi6x3mlet's concnrete on the upper example
08:07mi6x3mI want 5 to be printed
08:07llasrammi6x3m: Then how is that different from what the compiler does anyway?
08:08mi6x3mllasram: well I thought the lazy-seq won't be touched until run time
08:09mi6x3mactually it won't indeed
08:09mi6x3mbut when it's evaluated it's not considering the bindings
08:09mi6x3m, (let [x 5] (first (lazy-seq (println x))))
08:09clojurebot5\n
08:10mi6x3mwhat
08:10Bronsami6x3m: println returns nil
08:10llasramWhat did you expect to happen?
08:10Bronsa,(let [x 5] (first (lazy-seq (doto x println))))
08:10clojurebot5\n#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>
08:10Bronsa^
08:10mi6x3mnevermind, it works correctly, I was confused by the nil println returns
08:10mi6x3mlol
08:11mi6x3mthanks Bronsa
08:14rritochIn relation to mi6x3m's question. What if your dealing with dynamically bound variables, will a ((bound-fn ...)) expose bound variables to lazy sequences?
08:14llasramrritoch: If I understand your question correctly, then yes -- that's what `bound-fn` is for
08:14mi6x3mrritoch: should I guess, there's not much other context imaginable :)
08:15rritochex: instead of (doall (filter my-var-dep-fn '(1 2 3 4)) using (filter (bound-fn my-var-dep-fn) '(1 2 3 4))
08:15llasram&(def ^:dynamic v 0)
08:15lazybotjava.lang.SecurityException: You tripped the alarm! def is bad!
08:15llasram,(def ^:dynamic v 0)
08:15clojurebot#'sandbox/v
08:16llasram,(binding [v 1] (first (repeatedly #(-> v))))
08:16clojurebot1
08:16llasram,(binding [v 1] (first (repeatedly (bound-fn [] v))))
08:16clojurebot1
08:16llasramOh, hah
08:17llasramHelps to make it do what I'm trying to actually do
08:17llasram,(def ^:dynamic v 0)
08:17clojurebot#'sandbox/v
08:17llasram,(take 2 (binding [v 1] (repeatedly #(-> v))))
08:17clojurebot(0 0)
08:17llasram,(take 2 (binding [v 1] (repeatedly (bound-fn [] v))))
08:17clojurebot(1 1)
08:17llasramThere we go
08:18llasramrritoch: Oh, that's different
08:18llasramActually, nm, it's not
08:18llasramWell, maybe
08:18llasramrritoch: Did you mean `my-var-dep-fn` to be itself a dynamically bound var, or a function which depends on a dynamically bound var?
08:22rritoch,(take 2 (binding [v 5] (filter (bound-fn #(< % v)) '(1 2 3 4 5 6 7 8))))
08:22clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve var: v in this context, compiling:(NO_SOURCE_PATH:0:0)>
08:23llasramrritoch: you want bound-fn* there
08:23llasramOh, and to re-def v :-)
08:23llasramclojurebot resets itself every so often
08:27rritochAah, ok. I get it now
08:30rritoch,(take 2 (binding [v 5] (filter (bound-fn [x] (< x v)) '(2 3 4 5 6 7 8))))
08:30clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve var: v in this context, compiling:(NO_SOURCE_PATH:0:0)>
08:30rritoch,(def ^:dynamic v)
08:30clojurebot#'sandbox/v
08:30rritoch,(take 2 (binding [v 5] (filter (bound-fn [x] (< x v)) '(2 3 4 5 6 7 8))))
08:30clojurebot(2 3)
08:31rritochEither way, that is exactly what I was hoping for so I can get rid of most of my doall's
08:32rritochBut I'll normally need the (bound-fn*) version
08:46SagiCZ1is there an assoc-like function that throws an exception if i try to alter a non-existent key?
08:46SagiCZ1(assoc-like map :non-existent-key value) ---> exception
08:49SagiCZ1,(assoc {:a 0} :b 3)
08:49clojurebot{:b 3, :a 0}
08:58mi6x3mok I will need all the help I can get
08:58mi6x3mgiven this code http://pastebin.com/7RA8ZS7W
08:58mi6x3mwhy is fis = nil when InputStreamReader is being constructed?
08:59mi6x3mfis is correctly bound to the FileInputStream instance
08:59mi6x3mbut somehow it's not visible when the lazy seq is evaluated
08:59mi6x3mBronsa: this is related to my previous question
08:59mi6x3mit's what confused me originally
09:03mi6x3mfor some dreadful reason fis is not visible in the lazy-seq :/
09:04SagiCZ1mi6x3m: thats some funky indenting
09:04mi6x3mSagiCZ1: there's a reason for that :) I'm sorry
09:04mi6x3mI forgot to reformat
09:06mi6x3mI am sure there's a simple reason for that, but I can't locate any apparent reason
09:10mi6x3mokay everyone, I managed to get it down to a 1 liner
09:10mi6x3m,(let [x nil l (lazy-seq (cons (println x) ())) x 5] (first l))
09:10clojurebotnil\n
09:10mi6x3mbut clearly it should be 5
09:10mi6x3malso skipping x nil is an error
09:11mi6x3m,(let [l (lazy-seq (cons (println x) ())) x 5] (first l))
09:11clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)>
09:12SagiCZ1mi6x3m: wish i could help but i don't think i understand lazy-seq enough to explain this
09:13mi6x3mSagiCZ1: I appreciate :)
09:13mi6x3mSagiCZ1: I nailed it down, lazy-seq creates a function
09:14mi6x3m,(macroexpand-1 '(lazy-seq (cons (println x) ())))
09:14clojurebot(new clojure.lang.LazySeq (fn* [] (cons (println x) ())))
09:20rritochSagiCZ1: I have a solution for your assoc issue which seems to work, though I don't think the clojure core contains anything similar
09:20mi6x3mSagiCZ1: well, nothing is lazier than eval I guess
09:21mi6x3mllasram: why would it be the opposite of a good idea?
09:21rritoch,(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))
09:21clojurebot#<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))>
09:21rritoch,(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))
09:21clojurebot{:a 2}
09:22SagiCZ1rritoch: looks complicated
09:22rritochI'm not sure how tomake that nicer
09:22SagiCZ1thank you though.. i will look into it
09:22rritochIt use keep-indexed on the k-v args to pull out all of the keys
09:23rritochThan asserts on every key being contained in the map
09:23rritochWhich I believe is basically what your looking for, enforcing that only certain keys are used
09:26SagiCZ1rritoch: cant we just call contains? and then either assoc or throw exception?
09:27jeffterrellmi6x3m: Maybe you figured this out already, but I think your (first) one-liner should return nil because println returns nil.
09:27rritochassoc allows multiple k-v's
09:28mi6x3mjeffterrell: it's not that, lazy-seq doesn't consider the current binding context at runtime
09:28mi6x3mbecause it creates a function at compile time
09:29rritoch,(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))
09:29clojurebot{:a 2}
09:29rritochThat's a little cleaner, but not much
09:29jeffterrell,(let [x 3, l (lazy-seq (cons x nil)), x 5] (first l)) ; testing…
09:29clojurebot3
09:29SagiCZ1rritoch: thank you
09:31mi6x3mdamn eval doesn't consider bindings also
09:31jeffterrellmi6x3m: 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.
09:31jeffterrell,(let [x (atom 3), l (lazy-seq (cons @x nil))] (reset! x 5) (first l))
09:31clojurebot5
09:31mi6x3mI am really not interested in creating atoms for a simple iterative macro
09:32llasrammi6x3m: What are you actually trying to achieve?
09:32mi6x3mllasram: I'm writing an iterative version of try-let
09:32llasramIterative?
09:32mi6x3mbuilding up the bindings vector dynamically
09:33llasramClojure doesn't really work that way
09:33SagiCZ1llasram: you dont have any idea if clojure has an 'assoc-like' function wont accept update for non-existent keys?
09:34llasramSagiCZ1: It does not
09:34mi6x3mllasram: I can stop right now if the original version had ANY licensing info attached to it
09:34llasrammi6x3m: Have you asked the author of the original version to provide a license?
09:35mi6x3mllasram: no, I have not :)
09:35rritochIs 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.
09:35mi6x3mbut I could, yes
09:36mi6x3mlet me do so right now llasram:
09:37llasramrritoch: 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)
09:37llasramActually, *thinking*
09:37llasramtake-nth
09:37llasram,(take-nth 2 (range 10))
09:37clojurebot(0 2 4 6 8)
09:38jeffterrellrritoch: Are you wanting even values or even indexes?
09:38rritochEven indexes
09:39llasramYeah, then take-nth is your function
09:39jeffterrellNice one llasram, didn't know take-nth could do that.
09:40jeffterrell(doc take-nth)
09:40clojurebot"([n] [n coll]); Returns a lazy seq of every nth item in coll. Returns a stateful transducer when no collection is provided."
10:03SagiCZ1,(type (take-nth 5))
10:03clojurebotclojure.core$take_nth$fn__4684
10:03SagiCZ1i thought i would get a transducer
10:05BronsaSagiCZ1: you are
10:05BronsaSagiCZ1: a transducer is just a regular function
10:05Bronsathere's no "transducer type"
10:14Paperboyhttp://itch.io/games/genre-puzzle Free Games Here
10:16icelessteaProgramming is the best puzzle game there is.
10:18gfredericksexcept it's not always clear when you've beaten the level
10:19icelessteaThe uncertainty and the sudden moments of clarity and understanding are partly the reason why it is so great.
10:24mi6x3mis gensym global global
10:24mi6x3mor global only to the calling macro?
10:24mi6x3mi.e. context
10:24Bronsaglobal
10:25mi6x3mso `(x#) `(x#) is safe Bronsa ?
10:26mi6x3minside the same macro
10:26Bronsayes
10:27mi6x3malright
10:27gfredericksif "safe" means "I get two different gensyms"
10:29beepbeep_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:32AimHereIn what way do you want to 'group' stuff?
10:37llasrambeepbeep_: 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:38beepbeep_llasram, that might be it, gonna check it out
10:45mbacin 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:45mbacclojure says y/cmd conflicts with x/cmd. wah?
10:45llasrammbac: You want `:require` not `:use`
10:46llasramthe latter `refer`s all the symbols from the namespace into the referencing namespace
10:46llasramonly one thing can be bound to `cmd` in your `core` namespace
10:47mbacoh
10:50mbacthank you!
11:15SagiCZ1this is my implementation of safe-assoc https://www.refheap.com/92331 any obvious mistakes or slow-downs?
11:17SagiCZ1so far it is about 10 times slower than regular assoc :(
11:19SagiCZ1not sure i really want safe assoc anymore
11:21llasramSagiCZ1: That approach is doing quite a few additional allocations
11:22SagiCZ1llasram: in the assert?
11:22llasramSagiCZ1: It'd be much faster to just `recur` over the kv-pairs and check `contains?` before applying each
11:23llasramyes
11:23llasramWell, all over the place
11:24SagiCZ1what else the (every?) function does?
11:24llasramYou've got one for each element from the `take-nth`, one for the #() argument to `every?`, and one for the `partial`
11:25llasramPlus you aren't even checking if `key` is in the `map`
11:25llasramFYI (apply (partial ...) coll) is the same as (apply ... coll)
11:26Bronsathat partial is not only useless, but will also slow things doen
11:26Bronsadown*
11:26SagiCZ1how am i not checking if the key is in the map?
11:27llasramSagiCZ1: Because you only verify that every other `kvs` is the map, and `kvs` does not include `key` or `val`
11:30SagiCZ1kvs is a list of (key value key value key value) by taking every second, i get a list of all keys, dont i?
11:31SagiCZ1,(take-nth 2 [:key 5 :key2 10 :key3 0])
11:31clojurebot(:key :key2 :key3)
11:31BronsaSagiCZ1: you have key val & kvs, you're checking for the keys in kvs but not for `key`
11:31SagiCZ1Bronsa: snap!
11:31SagiCZ1got it now
11:40gfredericks,(inc (partial 41))
11:40clojurebot42
11:41Bronsagfredericks: you had me wat-ing for a second there
11:42gfredericks$findfn 41 41
11:42gfrederickshrmph.
11:42gfredericks,(deliver inc 41)
11:42clojurebot42
11:43jeffterrell(doc deliver)
11:43clojurebot"([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:43jeffterrellAh, interesting.
11:43gfredericksyou could do a whole WAT lightning talk on clojure GIGO
11:44llasram,('+ 3 2 1)
11:44clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: Symbol>
11:44llasram,('+ 1 1)
11:44clojurebot1
11:44llasramThere we go
11:44gfredericks,(#'and true false true)
11:44clojurebottrue
11:45llasramhah
11:45llasramSO GOOD
11:45jeffterrellYou guys are making me feel dizzy. Like the ground is shifting underneath me.
11:46llasram,(get :anything {} :haha)
11:46clojurebot:haha
11:46gfredericks,(get 42 43 44)
11:46clojurebot44
11:46llasramActually, maximum wat-looking:
11:46llasram,(get :key {:key :foo} :bar)
11:46clojurebot:bar
11:48gfredericks,(->> "foo bar" keyword vector pr-str read-string reverse)
11:48clojurebot(bar :foo)
11:48gfredericksnot too weird
11:48llasramha
11:48llasramfun though
11:48jeffterrell,(keyword "foo bar")
11:48clojurebot:foo bar
11:49justin_smith,(((get get get get) get get get) {:a 42} :a)
11:49clojurebot42
11:49jeffterrelllol
12:00ourkidhi - what are the equivalents of clojure's PDS classes in Java
12:02llasramPDS?
12:02gfrederickspersistent data structuer
12:03gfredericksourkid: 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:03ourkidyeah - PDS as in persistent data structure
12:03ourkidi mean given that PDS's are quite sensible, why were Java's collections written as they were ?
12:04gfrederickswell mutable collections are faster generally
12:04gfredericksI don't think PDS's were popular until quite recently
12:05ourkidThey weren't popular because there wasn't so much multithreading until recently?
12:05justin_smiththere was a point where we finally had enough RAM that pds were generally usable
12:05gfredericksthey're still not *actually* popular; i.e., I don't think anywhere near the majority of programmers use them
12:05justin_smiththis point was well after java was designed
12:05ourkidAh - so it's a memory efficiency issue then?
12:05gfredericksyeah that's part of it
12:06gfredericksPDS requires a lot of GC
12:06ourkidSo I guess if Java were starting from scratch then the PDS approach would be high on the feature list.
12:07gfredericksunclear what "java starting from scratch" would mean really
12:07SagiCZ1ourkid: i don't think so
12:08ourkidI guess I mean any new language would look to use PDS's if it also supported threads
12:08SagiCZ1java's principles revolve around mutable and stateful classes, pds wouldn't help there
12:08hyPiRionourkid: Actually, the PDS Clojure uses weren't invented when the datastructures in java.util were implemented.
12:08hyPiRionJava is almost 25 years old, so there's that as well.
12:08ourkidRight I see - Java is a mutable basket case; I think that is understood.
12:09ourkidDoes Scala implement PDS like collections?
12:09jeffterrellHeh, "a mutable basket case", I like that.
12:09hyPiRionI wouldn't be too surprised if Java came with PDS if it work on it started today.
12:09gfredericks~java is a mutable basket case
12:09clojurebotRoger.
12:09hyPiRionourkid: yes, Scala has roughly the same collection types as Clojure
12:10gfredericksmy memory is that scala doesn't have nearly the emphasis though
12:11ourkidSo Scala's map can be safely shared among threads?
12:11gfrederickswell it has mutable maps too
12:12ourkidYes, 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:13hyPiRionWell, the transients are unique as far as I know.
12:14hyPiRionAnd they share a common interface.
12:14hyPiRionBut apart from that, there's no reason any other language can't implement them.
12:15ourkidOK understood - thanks all.
12:15hyPiRion(roughly speaking)
12:15hyPiRionnp
12:15gfrederickshello hyPiRion
12:16hyPiRionhello gfredericks
12:17justin_smithhyPiRion: they do require gc though, don't they?
12:18gfredericksif 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:18hyPiRionjustin_smith: yes, hence the roughly speaking part. And they should have hashing functions on elements
12:19justin_smithgfredericks: 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:19llasramgfredericks: Hmm... Interesting. I guess you could ref-count the components and explicitly discard instances
12:19hyPiRiongfredericks: it's possible with RC, but then you'd have to detect cycles. And the reference count has to be thread safe.
12:19gfredericksjustin_smith: isn't the point of reference counting that you don't need a general-purpose GC?
12:20llasramProbably easier to just run a garbage collector. You can actually write garbarge-collected C with e.g. http://www.hboehm.info/gc/
12:20gfrederickshyPiRion: wherein might you create a cycle?
12:21justin_smithgfredericks: the point of a good gc is that you don't need to reference count :P
12:21hyPiRiongfredericks: that's sort of depending on the language, but (let [a (atom nil) b [a]] (reset! a b) b) creates one
12:22gfredericksjustin_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:22hyPiRionllasram: that's what I did for my master's thesis. Worked out surprisingly well (can't comment on the boehm GC perf though)
12:23gfredericksI don't think I have the energy to figure out if I'm crazy atm
12:23llasramhyPiRion: nice. I've never had reason to try that, but it's good to know it works :-)
12:23llasramgfredericks: Still working on that algebra lib?
12:24llasramgfredericks: I've been thinking of doing one just for monoids
12:24llasramSo simple, yet so useful
12:24gfredericksllasram: that'd be easy to add to mine
12:24gfredericksyou just need + amirite?
12:24llasramurrite
12:24gfrederickswait I already have it
12:25llasramwell then maybe my work is done
12:25gfredericksI think I only had it as in impl for groups/rings/fields
12:25gfredericksbut it still works
12:25gfredericksllasram: https://github.com/gfredericks/lib-4395/blob/master/src/com/gfredericks/lib_4395.clj#L18-25
12:27llasramCool. Hmm
12:27justin_smithgfredericks: 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:29gfrederickshoo ray!
12:31justin_smithgfredericks: reference counting and graph algos don't mix very nicely though
12:31justin_smith(but of course we have adjacency list representation for that)
12:31gfredericksjustin_smith: graph algos meaning the sort where you get cycles?
12:32justin_smithgfredericks: yeah, graphs in general are allowed to have cycles
12:32gfredericksright but any pure PDS use will not have cycles
12:32justin_smithand weird tricky to work with kinds if you consider the layers of indirection before you see the cycle
12:32gfredericksyou gotta incorporate references to get them
12:32justin_smithright
12:35justin_smithgfredericks: 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:36gfredericksman computers
12:37justin_smithgfredericks: one nice thing about idiomatic clojure is how rarely updates to data in one thread will touch anything another thread can even see
12:37justin_smithCPUs like that
12:38gfredericksoh goodness this quantum stuff is so slow; I'll be lucky if I can factor 15
12:40justin_smithidea: "low pass filter" toggle on youtube, to eliminate the high pitched whine in quad-copter vids
13:01justin_smithgfredericks: another neat thing: tcl values are immutible, and it uses reference counting
13:02gfredericksjustin_smith: good to know
13:03Bruce_WayneHey, anyone know the best way in a web app to have a user upload a file?
13:04Bruce_WayneI need the user to be able to use the open-file-dialog box to give me the full path to the file
13:04Bruce_Waynethat way I can read it in and work with it
13:04justin_smithBruce_Wayne: well, the path doesn't do you any good - it's on the user's computer
13:05justin_smithbut you can use an input type="file"
13:05justin_smiththen the contents of the file they use will come in with the request when they submit the form
13:06andyfjustin_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:06justin_smithandyf: we were talking about reference counting gc and pds
13:07justin_smithandyf: and that was a bit of trivia I encountered when looking at the issues involved
13:07Bruce_WayneI was trying to use the hiccup implementation of upload file
13:07gfredericksandyf: never once in my life
13:07Bruce_Waynehttps://github.com/weavejester/hiccup/blob/31c06bec7eec038c6d3bfc051f4033362f142ffb/src/hiccup/form.clj
13:08justin_smithandyf: 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:08Bruce_WayneI thought: https://gist.github.com/jtackett/14ea479e0e3260b9ef4f
13:08Bruce_Waynewould work
13:08Bruce_Waynethrough hiccup library
13:08Bruce_Wayneany advice?
13:08justin_smithandyf: instead of mutation, you work with data transformations, so it is almost functional in that sense
13:09gfredericksanybody know of an efficient bit-vector impl? i.e., should be PDS-like
13:09andyfjustin_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:09justin_smithBruce_Wayne: if the name is nil, how will you collect the data from the request?
13:09Bruce_Waynewhen i post the form to the url all it seems toreturn is the file name
13:10Bruce_Waynethe name isn’t nil
13:10Bruce_Waynethat is just the last arg past
13:10Bruce_Wayne the name is the param passed in
13:10Bruce_Waynehttps://gist.github.com/jtackett/236f06b8bb10b6ee9d64
13:10justin_smithandyf: 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:11justin_smithBruce_Wayne: OK, you should be getting the file contents as an input stream inside the request body
13:12justin_smithBruce_Wayne: it simplifies things a lot if you use the wrap-multipart-params middleware in ring
13:12Bruce_Wayneso when I post that to the url how do I capture the file contents?
13:13justin_smithBruce_Wayne: the file contents will be inside the request body
13:13Bronsa1.7.0-beta3 is out
13:13Bronsaerr, alpha3
13:13justin_smithBruce_Wayne: http://ring-clojure.github.io/ring/ring.middleware.multipart-params.html
13:14justin_smithyou will have a :params key on the request, and you can look up the file contents under that map
13:14Bruce_Waynealright
13:14Bruce_Wayneso when i do the file upload
13:14Bruce_Wayneit will return the name of the file along with it’s contents
13:15Bruce_Waynebut i need to use the multipart-params to get to the file content
13:15justin_smithwrap-multipart-params makes it easier
13:15Bruce_Wayneis there another way?
13:15justin_smithit's going to be in the request either way
13:16justin_smithBruce_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:16Bruce_Wayneugh ok
13:16Bruce_WayneI’ll use the wmp middleware
13:17Bruce_Waynestrange that the normal param just returns the name of the file when printed
13:17justin_smithBruce_Wayne: it sends the filename and the contents, they are both in there
13:17justin_smithsomewhere
13:18Bruce_Waynebut when you prn the params of the post
13:18Bruce_Wayneit is the file name
13:18justin_smithright, it's not in the params
13:18justin_smithyou need a middleware before anything ends up in :params of the request
13:19justin_smiththe :params key is not part of what comes from the client, it is created server side to simplify your handler logic
13:19Bruce_Waynealright
13:19justin_smithit's based on the request parameters, form parameters, etc.
13:19Bruce_WayneI wrapped it in the middle ware
13:19Bruce_Waynebut a map isn’t being returned
13:20Bruce_Wayneit is still just a string with the file name
13:20justin_smithBruce_Wayne: print out the full contents of :multipart-params
13:20Bruce_WayneI am trying
13:20Bruce_Waynelet me show you the flow
13:22Bruce_Waynehttps://gist.github.com/jtackett/d91a295cbd01c1fb20de
13:24justin_smithBruce_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:24Bruce_Wayneok how would i do that?
13:26Bruce_Waynechange the rout to reference the ful request that is
13:26justin_smithBruce_Wayne: (POST "/your-pdf" request (fn [request] (prn (:multipart-params request))))
13:26Bruce_Waynecan you literally write the word request?
13:26justin_smithwait, sorry
13:27Bruce_Wayneno worries
13:27justin_smithBruce_Wayne: (POST "/your-pdf" request (prn (:multipart-params request)))
13:27justin_smithgawd I hate macro magic sometimes
13:27justin_smithyes, literally the word request, and pass the whole request and all its data
13:27justin_smithhttps://github.com/weavejester/compojure/wiki/Routes-In-Detail
13:28justin_smiththe [file] syntax in that context is a shortcut for getting at (-> request :params :file)
13:30Bruce_Waynegot ya
13:30Bruce_WayneI’m getting an empty map with that
13:30Bruce_Wayneone sec
13:31justin_smithI'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:31Bruce_Wayneok
13:31Bruce_WayneI can see the whole request now, but there doesn’t seem to be a file
13:31Bruce_Waynejust the file path
13:31Bruce_Waynewhich only is the name of the file
13:45mi6x3mdoes anyone know if I have to include a copy of EPL 1.0 if I release something under it?
13:45mi6x3mor a link is sufficient?
13:53icelessteami6x3m: 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:53mi6x3micelesstea: true
14:07justin_smith$mail Bruce_Wayne minimal working file upload example https://www.refheap.com/92336
14:07justin_smithahh, lazybot is out too :P
14:08justin_smithbut anyway, that's the smallest intelligible example I could make of a file upload in a compojure app, if anyone cares
14:12mi6x3mhey everyone, I finished that try-let macro I was working on
14:12mi6x3mhttps://gist.github.com/MIvanchev/5bad28baad02167fbece
14:13mmeixIf 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:14justin_smithmmeix: blank lines inside defns aren't usually done
14:15justin_smithmmeix: 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:16justin_smithalso, your last three bindings could be one line: [before cand after] primes-triple
14:16justin_smith,(let [[before cand after] [1 2 3]] after)
14:16clojurebot3
14:18justin_smithin fact, I would just do (let [... [before cand after] (take-last 3 primes)] ...)
14:18jeffterrellmi6x3m: that's nifty. Seems like a good bit of syntactic sugar.
14:19Shambles_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:19justin_smithmi6x3m: catching throwable has some really bad corner cases
14:20justin_smithShambles_: select-keys maybe?
14:20justin_smith,(select-keys '[a b c d e] [0 2 4])
14:20clojurebot{4 e, 2 c, 0 a}
14:20justin_smiththat's not quite it...
14:20justin_smithahh, map :)
14:21justin_smith,(map '[a b c d e] [0 2 4])
14:21clojurebot(a c e)
14:21justin_smithyes, in clojure "at" is called "map" :)
14:22justin_smithonly works with vectors / sets / hash-maps that way though
14:22Shambles_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:22justin_smithShambles_: fair point, yeah :)
14:22Shambles_select-keys is most of the way to a good name though.
14:23justin_smith,(map #(get '[a b c d e] %) [0 2 4])
14:23clojurebot(a c e)
14:23justin_smiththe verbose version, that's what that map is really doing anyway
14:23Shambles_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:23justin_smithShambles_: sample
14:23Shambles_Yeah the mapping get thing occurred to me already.
14:24justin_smithI think sample is a good name for it - taking individual points out of a larger continuum
14:24Shambles_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:25justin_smithouch
14:25Shambles_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:26mmeixjustin_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:26justin_smithShambles_: 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:26Shambles_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:27Shambles_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:28Shambles_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:28justin_smithmmeix: also, if you know it's a vector (as you do thanks to the scope of binding) use peek rather than last
14:28justin_smith(doc last)
14:28clojurebot"([coll]); Return the last item in coll, in linear time"
14:28justin_smith(doc peek)
14:28clojurebot"([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:29mmeixbecause it's faster?
14:29mmeixor more idiomatic?
14:29justin_smithboth I'd say
14:29mmeixok
14:29mmeix thanks
14:30justin_smithmmeix: a cool thing is that peek / conj always pair up, whether using lists or vectors
14:30justin_smith(not for queues though)
14:31mmeixbecause they work from the same end, respectively, as far as I understand
14:31justin_smithright
14:31mmeixok
14:31justin_smithpeek /conj / pop all treat the argument as a stack
14:33justin_smith(except with queues, then they treat it as a queue)
14:33mmeixpeek/pop I understood, but not the symmetry with conj - good insight, thanks
14:33mmeixlot of things to be learned, but it's getting better, slowly ... :)
14:34justin_smithyup, it's worth it
14:35Shambles_justin_smith: Does "select-indexes" seem okay for a name?
14:36justin_smithsure, though I like sample better still
14:37Shambles_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:38justin_smithrandom sampling isn't the only kind, but if that's really a common thing, that's a good point
14:40mmeixP.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:43Shambles_I think I'll go with that for the name. Thanks for the help justin_smith.
14:44justin_smithmmeix: on the synthesis side of things, I'm interested in what pink might grow into
14:44mmeixyup ...
14:45mmeixI'm mostly thinking about modeling the deep and multi-layered structures of harmony and counterpoint
14:45mmeixthinking in Clojure helps clarifying that et vice versa, I found
14:46justin_smithcool
14:47mmeixso now I'm learning Clojure as fast as I can, really motivated :-)
14:49justin_smithmmeix: 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:49justin_smithand I think the latter is clearer
14:49justin_smithoh wait!
14:50mmeixthe first is a check, if cand is really a prime
14:50justin_smith(= cand n (/ (+ before after) 2))
14:50justin_smithmmeix: sure, but that's how and works
14:50justin_smithif the first one fails, it fails
14:50mmeixof course
14:50mmeixgreat
14:51justin_smithbut anyway, we have multi-arg =, and that's the simplest thing here :)
14:51justin_smithbecause really you just want "are these three things equal"
14:52creeseI'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:52mmeixah! [light bulb]
14:52creeseDoes that look familiar to anyone?
14:52justin_smithcreese: what kind of crazy input are you feeding that poor db connection?
14:53Renato_Ferreiracould it be encoding?
14:53justin_smith(joking)
14:54creeseencoding sounds right, I'm just not sure of the fix or why it's needed
14:56mmeixjustin_smith but now my test case (nth (filter balanced-prime? (range)) 15) gives me a "NullPointerException", not sure why...
14:56justin_smithmmeix: hmm
14:57mmeix( https://www.refheap.com/92334 updated )
14:57justin_smithmmeix: with the version currently in refheap?
14:57mmeixjust now
14:58mmeix[testing ...]
14:58justin_smithmmeix: ahh, the destructuring will make after be nil if primes is a two element list
14:58Renato_Ferreiracreese: 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:58justin_smith,(let [[a b c] [1 2]] c)
14:58clojurebotnil
14:58mmeixah...!
14:59justin_smithmmeix: I had not considered that difference between last and getting the third element
14:59mmeixI would never have thought of that
15:00justin_smithmmeix: what if the acc started with [2 3 5] would that be cheating?
15:00mmeixjust had the same idea
15:00justin_smithotherwise you could revert the binding change, of course
15:00Renato_Ferreirathere should also be an encoding for the connection itself, like 'set names' in mysql
15:01mmeix(checking, if 2, 3 and 5 are/aren't "balanced primes" - then it woouldn't be cheating)
15:02creeseRenato_Ferreira: the character set is utf8 for that column, more like I'm doing the batch update wrong
15:02creeseRenato_Rerreira: elsewhere, I do the single insert and it works
15:03zand`hey folks - does anyone know how to specify the version of a leiningen template to use with new?
15:03zand`example: I have two versions of a template installed in .m2 and it keeps using the older one
15:04SagiCZ1i 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:04creese(sql/insert! db :tag [:title] [tags]) ... the value of tags is [[foo bar]] from println
15:04zand`e.g. lein new liberagent:0.1.5-SNAPSHOT foo
15:04zand`(that doesn't work btw ^^^)
15:05justin_smithzand`: I don't think lein templates have that power
15:05zand`that's what I thought - no mentions of versions in the docs...
15:05SagiCZ1maybe i should use transients
15:05zand`thanks.. I'll manually delete the other dir in ~/.m2 and see what happens
15:07zand`hmmm... that doesn't seem to work (lein new just goes to clojars to download the older version)
15:09mmeixjustin_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:10mmeix(quite a learning experience ...)
15:12Renato_Ferreiracreese: hmm, yeah my knowledge with this api is rather limited. shouldn't tags be a simple array? it is it indeed nested?
15:20zand`anyone know what the current best practice is for installing and using a library from github?
15:21zoldarzand`: one way I know is cloning and doing lein install to put it into local maven repository
15:22creeseRenato_Rerreira: (insert! db-spec table col-name-vec col-val-vec & col-val-vecs :transaction? true :entities identity)
15:22zoldarbut I don't know if this is the best practice actually...
15:23creeseI take this to mean col-name-vec is [:title] following by separate args for each row to insert (foo) (bar) (etc)
15:23zand`@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:24Renato_Ferreiracreese: 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:24creeseso 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:24zoldarzand`: that's weird.. if versioning is right, the one from local repo should be fetched
15:24zoldarzand`: is the version from the repo actually hight?
15:24zoldarhigher*?
15:25zand`@zoldar - yes, it's higher 0.1.4 vs 0.1.5-SNAPSHOT
15:25creeseThe traceback says: java.lang.IllegalArgumentException: insert called with columns but no values
15:25zand`it's possible the problem is user error :-) I'll give it another go here...
15:25Renato_Ferreirahm...
15:26justin_smithzand`: try taking -SNAPSHOT out of the version string
15:26zoldarzand`: wait, one more thing you ma have to do is to put it into your local profile in ~/.lein/
15:26justin_smithzoldar: that should not be relevant for a template
15:27zand`@zoldar: I'll try again and report back...
15:27zoldarjustin_smith: okay, but maybe adding it to profiles.clj under :user :plugins would override the problem with the snapshot release?
15:28justin_smithzoldar: maybe...
15:28zoldarjustin_smith: I recall that I had to do it when testing out my own template
15:28SagiCZ1is loop-recur rebinding preffered to swaping an atom?
15:28Renato_Ferreiracreese: 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:28BronsaSagiCZ1: what do you mean?
15:28justin_smithSagiCZ1: when applicable, yes - if it's something used locally by said loop, just rebind rather than using an atom
15:29creesethe example that works is one row, the batch insert has a different argument list (its also a different table)
15:29SagiCZ1justin_smith: yes it is used locally.. ok i will use loops.. atoms are so tempting though
15:30BronsaSagiCZ1: they are entirely different things, you shouldn't think of atoms as a substitute for the mutable variables you use in other langs
15:30SagiCZ1Bronsa: they do substitute them though
15:30SagiCZ1from my POV
15:31creeseRenato_Ferreira: trying this now --> (sql/insert! db :tag (map #(hash-map :title %) tags))
15:31BronsaSagiCZ1: well you should change your POV when programming in clojure then :)
15:32justin_smithSagiCZ1: you could also do something evil with string and System/setProperty / System/getProperty - but it still isn't what these things are for
15:32SagiCZ1justin_smith: i wonder what are atoms for then
15:32Bronsajustin_smith: you shouldn't go around suggesting that >:(
15:33justin_smithBronsa: I was hoping it would sound silly enough to clearly be wrong
15:33justin_smithhow about filenames and spit / slurp, that could replace mutable variables too (yuck)
15:33BronsaSagiCZ1: they are reference types implementing a CAS mechanism. they have significant more overhead than "normal" mutable vars
15:34SagiCZ1justin_smith: what great ideas!
15:34Bronsajustin_smith: brb I'm rewriting all my functional code into procedural using that
15:34SagiCZ1Bronsa: thank you for elaborating
15:35creeseUsing 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:35Renato_Ferreiracreese: but that will yield one sequence of row maps, instead of multiple row map arguments, won't it?
15:35creesea sequence of rows maps is another interface that should work
15:36creese(insert! db-spec table row-map & row-maps :transaction? true :entities identity)
15:36justin_smithcreese: that would work with apply maybe
15:36BronsaSagiCZ1: 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:36creeselike this? --> (apply sql/insert! (concat [db :tag] (map #(hash-map :title %) tags)))
15:37creeseit doesn't seem to
15:37justin_smithBronsa: SagiCZ1: thus my even sillier and even more ineffecient suggestions
15:37justin_smithcreese: don't use concat there
15:37creesewhat's wrong with concat
15:37justin_smith,(apply + 1 2 [3 4 5])
15:37clojurebot15
15:37justin_smithit's not needed
15:37justin_smithbut anyway, if your last N args are in a collection, apply is the right way to handle it
15:38Renato_Ferreirawe have to unwrap them using apply, if i get it right. the function doc seems to indicate that
15:38Renato_Ferreiraoops, exactly
15:39SagiCZ1Bronsa: 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:39SagiCZ1https://www.refheap.com/92339
15:40creese(apply sql/insert! db :tag (map #(hash-map :title %) tags)) <-- java.lang.IllegalArgumentException: insert called with columns but no values
15:40justin_smithSagiCZ1: (reduce (fn [creates event] (map #(consume % event) creatures)) creatures queue)
15:41BronsaSagiCZ1: that looks like a reduce
15:41justin_smithyeah, definitely a reduce
15:41justin_smiths/creates/creatures above of course
15:41SagiCZ1oh... are you suggesting that ignoring reduce and refusing to learn about it was a mistake?
15:41justin_smithSagiCZ1: pretty much :)
15:41justin_smithreduce is awesome
15:42SagiCZ1no wonder i couldnt figure this out, thank you very much
15:42justin_smithSagiCZ1: whenever you want to repeatedly punch a new transformation based on a sequence of data onto some state, a reduce does that handily
15:43justin_smithand all the mutation is moved to the arguments of the reducing function, so no more atom or mutable variable needed
15:43justin_smith"mutation"
15:45SagiCZ1thats amazing.. better then loops
15:45justin_smithSagiCZ1: it abstracts and makes simpler a particular common usage of loops
15:46justin_smithalso, 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:46justin_smith(doc reduced)
15:46clojurebot"([x]); Wraps x in a way such that a reduce will terminate with the value x"
15:46mmeix(it is a recursive loop under hoods, right?)
15:46SagiCZ1justin_smith: yeah that makes sense.. thats why i had a feeling im looping the same way every time
15:47justin_smithmmeix: well, eventually you get down to loops, but there are a few protocols / interfaces it specializes on with different impls
15:47mmeixof course
15:47SagiCZ1justin_smith: i guess it's blazing fast too right?
15:47BronsaSagiCZ1: much faster than mutating an atom in a loop
15:48Renato_Ferreiracreese: silly question, but have you tried a minimal example without relying on other values, just hard coding it for, say, two columns?
15:48justin_smithBronsa: SagiCZ1: and thanks to the specialized protocols, likely faster than looping with first / rest / accumulator too
15:48Renato_Ferreira(sql/insert! db :tag {:title "t1"} {:title "t2"})
15:49Bronsajustin_smith: definitely
15:49mmeix(mmeix stares at the source of "reduce")
15:49Bronsathere's not much there :)
15:49mmeixja, just found out by myself ...
15:49Raynesmmeix: Look at the source for doseq lol
15:49RaynesIt's like staring at the sun.
15:49BronsaRaynes: you monster.
15:50mmeix"clojure.core.protocols/coll-reduce" seems to be the magic spell ...
15:50mmeixok
15:50BronsaIIRC the source for `for` is even worse
15:51mmeixok: understanding doseq source would take me three days, indeed ;)
15:51justin_smithyeah, for is a monster
15:51Bronsammeix: there's an intricate amount of protocols/interfaces that play into different implementations for reduce
15:51Bronsasome are in clojure, some in java
15:52mmeixah
15:52mmeixI see
15:52justin_smith"never trust a macro you couldn't read out loud in one breath"
15:52mmeixLOL!
15:52mmeixlike one musical phrase ...
15:53mmeix(if that's the right word in english)
15:53justin_smithI don't actually suggest that standard, but I thought it sounded nice :)
15:53justin_smithI use for / doseq all the time
15:53Bronsammeix: there's nothing much interesting in the impl of `for` anyway it's mostly parsing boilerplate & chunked-seq handling
15:54SagiCZ1that reduce is the shizz
15:54creese(sql/insert! db :tag {:title "foo1"} {:title} "bar1") <-- this works at the repl
15:55mmeix[defers studying clojure source] :-)
15:56skratl0x1say 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:56creeseso does this -> (apply sql/insert! db :tag (map #(hash-map :title %) tags))
15:56justin_smithmmeix: 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:57justin_smithcreese: I assume '{:title} "bar1"' was a typo
15:57mmeixah! great stuff! this goes straight on my teacher's web page :-) Thanks!
15:57creesejustin_smith: yeah, I copied the wrong one
15:58skratl0x1it surprises I can't find any example of this
15:58Renato_Ferreirawait, wasnt the second one giving the illegal argument stuff?
16:01SagiCZ1how could i make some random java collection implement sequencible, so i could use it in clojure?
16:02justin_smithSagiCZ1: if (seq r) doesn't work, try getting an iterator on it
16:02justin_smithor if it has a .toArray or .asList method or whatever
16:02justin_smithSagiCZ1: what class?
16:02SagiCZ1ArrayBlockingQueue
16:02SagiCZ1seq seems to work
16:03creesejustin_smith: so the insert works, the problem was another one further down
16:10SagiCZ1justin_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:12justin_smithSagiCZ1: if the queue is being used as an actual queue I would just use the interop methods to put / poll / take
16:12justin_smithSagiCZ1: since the semantics of the queue are probably important for program correctness and you don't want an abstraction that messes with that
16:12SagiCZ1justin_smith: thats what i do, but then i cant reduce over it :(
16:12justin_smithwell, you can't reduce period because you don't know the size ahead of time
16:13justin_smiththings can get added to the end while you use it
16:13SagiCZ1it would block the thread that is reducing
16:13justin_smithyou may be able to use iterate such that it can be treated as a lazy seq instead
16:13justin_smithSagiCZ1: so yeah, you *can* reduce, but that seems less than ideal
16:13justin_smithit's the wrong semantics - you can't just replace every loop with reduce
16:14justin_smithsometimes you need iterate, or map, or ever so rarely, loop :)
16:15gfredericks~loop is a macro of last resort
16:15clojurebotIn Ordnung
16:18SagiCZ1justin_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:18justin_smithSagiCZ1: you can add creatures as a second arg to loop
16:19justin_smithand then add the updated creatures (result of the map) to the recur call
16:19SagiCZ1okay.. so then it would be just one loop, that gets a new event and updated list of creatures at the same time
16:20justin_smithor you can use the reduce version, with (repeatedly #(.take queue)) as the sequence to reduce on
16:20justin_smithSagiCZ1: right
16:20SagiCZ1thanks, that will work
16:20justin_smiththe (repeatedly #(.take queue)) version with reduce is nicer to my eyes actually
16:21justin_smith~loop
16:21clojurebotloop is https://www.refheap.com/90332
16:21justin_smithoh, I remember doing that one, lol
16:22SagiCZ1justin_smith: wait so i can do repeatedly and use reduce?
16:22justin_smithright, using that repeatedly call in the reduce version instead of directly using the queue should work
16:22SagiCZ1sounds great
16:27SagiCZ1justin_smith: works fine, really good idea
16:27justin_smithglad it worked
16:35ro6I'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:35ro6best way to realize the configuration on a client when it starts up.
16:37ro6I'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:38ro6So 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:38justin_smithro6: is this a rest service?
16:39justin_smithor wait, drop the rest part, I assume this is an http service of some kind?
16:39ro6justin_smith: the server is a rest api
16:40justin_smithOK, 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:40justin_smiththere is also immutant, built on jboss
16:40justin_smithwhich can do fancier things with coordinating services
16:40ro6justin_smith: the client machines are basically just desktop computers where I have no ability to control what ports are open, etc
16:41justin_smithro6: yeah, this is all server side that I am talking about
16:42ro6justin_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:42justin_smithoh, OK, now I get it
16:42justin_smithyeah, so you want to be able to export new features to the client end
16:43ro6justin_smith: exactly, and potentially different features for different clients
16:43justin_smithis 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:44justin_smithplus there is alembic/still for simple updates of the app to pull in a new mvn dep at runtime
16:44justin_smith(still/distill [[some/dep "version"]]) same syntax as in project.clj
16:44ro6justin_smith: right, so I've been looking at Trapperkeeper, which seems to support a similar idea to component
16:44justin_smithI know those guys but haven't taken a close look at Trapperkeeper yet...
16:45ro6justin_smith: so that would imply running our own maven repo?
16:45justin_smithro6: or shipping the artifacts and having the client look for them locally - running an actual repo may be more straightforward
16:45ro6Justin_smith: my own research led me there too, I don't want to reinvent dependency management.
16:46justin_smithyeah, maven is pretty well understood and you are likely using it already :)
16:46justin_smithor using it's api via pomegranate / lein at least
16:47ro6justin_smith: of course!
16:48ro6justin_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:48justin_smithro6: I use pallet/alembic to load deps at runtime, it is pretty straightforward
16:48justin_smithor you can use the lower lefel pomegranate libs that alembic is built on
16:49ro6justin_smith: have you ever had two versions of a service running in the same jvm at the same time?
16:49justin_smithno, that sounds scary
16:50justin_smiththat'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:50ro6justin_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:51ro6justin_smith: just trying to design for extensibility at the start
16:51creesethanks for the assist all
16:52justin_smithro6: if I had to do this, I would start with immutant http://immutant.org/
16:52kenrestivoro6: there's also leaven,
16:52ro6kenrestivo: I haven't heard of that one
16:53kenrestivoro6: and system https://github.com/danielsz/system/ leaven is here https://github.com/palletops/leaven
16:53kenrestivoi'm still trying to get my brain around the difference between all these frameworks
16:53kenrestivoit sure would be nice if there were a rosetta stone with a simple diff comparing them all
16:54kenrestivoin the meantime i'm just going to use components in raw form until i understand *why* people created all these wrappers for it
16:54ro6The 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:54ro6Right
16:55ro6Thanks for the thoughts both of you
16:55kenrestivoi 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:56justin_smithkenrestivo: 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:56ro6Ha
16:56kenrestivowell, in open source there isn't such a thing.... otherwise we'd all be using emacs :-)
16:57justin_smithwait, we aren't all using emacs?
16:57justin_smith(joking)
16:58ro6I've already mind-melded too deeply with the vi bindings
16:58kenrestivoi'm actually bilingual, i use emacs and vi constantly, and for some reason very rarely get mixed up between them.
16:58ro6I don't even think up or down anymore, all there is is k and j
16:59gfredericksVI stands for Vendor lock-In
16:59ro6Maybe someday I'll try the os known as emacs
16:59justin_smithgfredericks: while emacs is all about EMbrACes and extendS
17:00gfredericksemacs is an excellent operating system lacking only nounah teduc.uchnhuonu nonnoooouth.m
17:00mearnshi switched to emacs after 3 years of vim recently, no bother
17:00mearnshi prefer it
17:00justin_smithmearnsh: did you use evil mode?
17:00mearnshnope not even
17:01justin_smith(I used viper when I first switched from vi)
17:01ro6I bet if I write my client in elisp I can just deploy emacs and use the package manager to solve everything!
17:01justin_smithoh god the emacs package management is craptastic
17:01TimMckenrestivo: Or as a friend of mine calls it, bitextual.
17:02ro6Or as some call it, promiscuity
17:02justin_smithTimMc: 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:03TimMc:-)
17:03TimMc"Johnny Ed-user"
17:03kenrestivoknow 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:04ro6I actually use a chrome extension that applies vi bindings to browsing
17:05ro6Really fast once you get used to it. I usually end up crashing my browser by opening too many tabs too fast.
17:06ro6Anytime editors come up I can't help but think of this: http://xkcd.com/378/
17:06TimMcShambles_: You're talking about PHP, right?
17:07TimMcro6: I think of http://www.loper-os.org/wp-content/editors.png
17:07Shambles_TimMc: No, but something about as bad.
17:31justin_smithTimMc: that Vi one from that picture is actually a cool way to make working sunglasses
17:32TimMcjustin_smith: Not just sunglasses -- it actually focuses as well.
17:33SagiCZ1kenrestivo: intellij has predefined profile with emacs bindings i believe..
17:43justin_smithSagiCZ1: the problem with "emacs bindings" is nothing ever implements *my* emacs bindings
17:43justin_smiththough I hear there may finally be a web browser that lets you use iswitchb to select a tab, which sounds awesome
17:47TimMcjustin_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:49justin_smithTimMc: 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:55SagiCZ1justin_smith: yeah.. well intellij is nothing like emacs, so i guess it could only help with some transitioning
17:56justin_smithSagiCZ1: fair enough - but I use emacs for the features, and merely tolerate the keybindings :)
17:57TimMcI use emacs solely for paredit-convolute-sexp.
18:17technomancy<3
18:19andrewhremacs people: do you use emacs for IRC too?
18:19amalloythat would be great marketing material. "Google Wave, but for editing text!"
18:20andrewhrgfredericks erc?
18:20gfredericksyeah
18:20justin_smithamalloy: I liked wave as a collaboration tool
18:20amalloyandrewhr: some do, but not all. i'd guess it's something like 60/40 one way or another
18:20justin_smithandrewhr: I use erc too
18:21andrewhrnice
18:21andrewhrI want to get more emacsy… despide using Cursive for work (didn’t manage cider to work with cljs)
18:22justin_smithorg mode is awesome for tracking tasks and organizing ideas
18:22andrewhrjustin_smith NOES YOU DESTROYED MY HOPES
18:22andrewhru.u
18:22gfredericksI started hating work-communication a lot less once I figured out how to use hipchat from emacs
18:23andrewhrI have emacs + evil running here, soo… mwahahahaha
18:23andrewhrstill wondering about remmapping vs using god-mode
18:25justin_smithgfredericks: something bitlbee based? or jabber.el?
18:25gfredericksbitlbee
18:25justin_smithgfredericks: next best thing to convincing everyone to use IRC I guess
18:26gfredericksthat's a lot of people to convince
18:28justin_smithgfredericks: is universal human consensus really that much to ask?
18:29gfredericksyes
18:30SagiCZ1justin_smith: you could almost start convincing americans to use metric system
18:31gfredericksthen daylight savings time
18:32justin_smithSagiCZ1: 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:32SagiCZ1justin_smith: hardly surprising ;)
18:33andrewhrjustin_smith: are you kidding? lol
18:33justin_smithhttp://en.wikipedia.org/wiki/World_Standards_Day
18:33gfredericksalso we spell "metre" differently even though we don't use it
18:33andrewhryour wikipedia-fu was faster than mine
18:34SagiCZ1gfredericks: i thought that was british spelling
18:34gfrederickswikipedia claims it's co-USA
18:34justin_smithandrewhr: you gotta be where the puck is *gonna* be, not where it is now
18:35justin_smithgfredericks: is co-USA the same s BIPM?
18:35gfrederickswhat
18:36justin_smith"The metre (BIPM spelling), or meter (American spelling)"
18:36justin_smithhttp://en.wikipedia.org/wiki/International_Bureau_of_Weights_and_Measures
18:36gfredericks"co-USA" == every country except USA
18:37justin_smithgot it
18:37justin_smithgfredericks: you've probably heard the one about the mathematician that opened a grocery store, and simplified the produce section, replacing coconuts with nuts
18:39gfredericksnow I have
18:39kenrestivoi.e. reading a logfile? and i ultimately want to turn it into an async channel.
18:39kenrestivodumb 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:41justin_smithkenrestivo: 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:41justin_smithor use it via interop
18:41kenrestivojustin_smith: cool, thanks!
18:42justin_smithoh, wrong file, one minute
18:42justin_smithoh wait, it has the source, it's just really weirdly formatted
18:43justin_smithkenrestivo: like 395 looks to be where the real magic is
18:43kenrestivoyep, that's the hard part
18:45justin_smithI 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:46kenrestivoi was just going to pull that in via interop, and have the listener fn dump the stuff into a channel
18:47justin_smiththat works too :)
18:48kenrestivojust 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:48SagiCZ1when clojure throws stackoverflow error, how can i determine what part of my code causes it?
18:50gfredericksby looking at the stacktrace?
18:50SagiCZ1the stack trace just has thousands calls to clojure.core or clojure.lang functions
18:51gfrederickswhat sorts of functions?
18:51gfredericksthere's usually a handful that are repeating over and over again
18:51gfredericksso figuring out what the cycle looks like can help a lot
18:52SagiCZ1gfredericks: https://www.refheap.com/92347
18:53gfredericksthat looks like you called map a whole bunch of times
18:53gfrederickssuch as
18:54gfredericks,(reduce #(map (partial + %2) %1) (range 10) (range 100000))
18:54clojurebot#<StackOverflowError java.lang.StackOverflowError>
18:54gfrederickscontrast with:
18:54gfredericks,(reduce #(mapv (partial + %2) %1) (range 10) (range 100000))
18:54clojurebot[4999950000 4999950001 4999950002 4999950003 4999950004 ...]
18:55gfredericksthere are a few scenarios where laziness can end up eating your whole stack once you try to realize something
18:55SagiCZ1i have something like (loop [c creatures n 0] (recur (map update creatures) (inc n)) is that wrong?
18:56amalloySagiCZ1: 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:56gfredericksI'm having a hard time explaining to myself why this doesn't come up more often
18:56SagiCZ1amalloy: yes i just found out exactly what you said, but can you elaborate why is that the case?
18:56gfredericksI don't think I've ever seen this specific kind of thing brought up before
18:57amalloySagiCZ1: because you end up with (map update (map update (map update ...)))
18:57gfredericksSagiCZ1: do you know how map's laziness works?
18:57amalloynone of which does any computation at all; it's all deferred
18:58amalloyand then when you finally ask for an element of that list, a zillion things all collapse into one deep stack
18:58SagiCZ1amalloy: i see, thats interesting... when i realize the map in each loop it works fine
18:58SagiCZ1thank you
18:59gfredericksSagiCZ1: mapv would also do fine
18:59gfredericks~a zillion things |all collapse| into one deep stack
18:59clojurebotAlles klar
19:00SagiCZ1gfredericks: mapv returns vector instead of lazy-seq, so and vector cant be lazy, right?
19:00gfredericksexactly
19:01Dragon-ballhttp://tinyurl.com/ogzbb82 Buy Dvd Movies Here
19:04AeroNotix+b
19:04AeroNotixmods
19:04kenrestivo~guards
19:04clojurebotSEIZE HIM!
19:21justin_smith~goards
19:21clojurebotHuh?
19:22justin_smith~gourds
19:22clojurebotSQUEEZE HIM!
20:26Bruce_Waynestill having trouble with uploading a file
20:26llasramBruce_Wayne: Have you tried it as Batman instead?
20:26Bruce_WayneI have
20:27llasramCool. Now that I have that out of the way...
20:27Bruce_WayneI took it to the batcave and ran science on it
20:27Bruce_Waynehaha
20:27Bruce_Waynedamn alright
20:35justin_smithBruce_Wayne: I uploaded a minimal example of file upload working in a compojure app
20:35Bruce_Waynethank you
20:35Bruce_Waynewhat’s the link?
20:36justin_smithhttps://www.refheap.com/92336
20:36justin_smithother than that one file, it is a default compojure project made with lein new compojure
20:37justin_smithyou click a button to select a file, click on the submit button, then the file shows up as plaintext
20:53azeirahWhere can I find a list of clojure libraries?
20:54justin_smithazeirah: clojars.org hosts many of them, and has search functionality
20:54azeirah@justin_smith, thanks
20:54justin_smiththere is also the toolbox site http://www.clojure-toolbox.com/
20:55justin_smithalso, 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:55azeirahYeah, I was looking for readable, a library to make lisps a lot more readable
20:56azeirahCan't find it on clojars nor toolbox unfortunately
20:56Bruce_Wayne:justin_smith does this work if the file is a pdf?
20:56Bruce_Waynejustin_smith: does this work if the file is a pdf
20:56azeirahIt made my introduction to lisps a lot more bearable
20:56Bruce_Waynemaybe that is my problem
20:56justin_smithBruce_Wayne: you would want to get a handle to the file rather than slurp it
20:56Bruce_WayneI am
20:56Bruce_WayneI use pdfbox and other apache libraries to read it
20:56Bruce_WayneI can read it locally
20:56justin_smithOK
20:57Bruce_Wayneand i have code that works now
20:57Bruce_Waynejust trying to wire it up for a user on my webapp
20:58justin_smithazeirah: oh, so one of those frontends that uses indentation based syntax and then converts it to sexps?
20:58Bruce_Waynewhen i print out the request ther are not multipart params
20:58Bruce_Waynejust an empty map
20:58azeirah@justin_smith Yeah, as well as a few other small things. It was great imho
20:58justin_smithBruce_Wayne: then your form is wrong, or you aren't using the middleware properly
20:58justin_smithazeirah: I remember seeing something like that once, it didn't really catch on
20:59azeirahMade lisp a little more python-ish
20:59azeirahI'm talking about this one: http://readable.sourceforge.net/
20:59Bruce_Wayne(wrap-multipart-params public-routes)
20:59Bruce_Wayneseems simple enough
20:59llasramazeirah: In my experience you just get used to it, and even prefer it
21:00justin_smithazeirah: yeah, I forget the name, it's out there somewhere
21:00llasram<3 paredit
21:00Bruce_Waynejustin_smith: just like you did it (wrap-multipart-params public-routes)
21:00azeirahHmm, I don't know why parentheses everywhere is preferable :p
21:00justin_smithBruce_Wayne: check out the html I am using for the form, in particular the enctype parameter
21:00llasramazeirah: Clojure doesn't use them "everywhere". Generally only for function(-like) application
21:00justin_smithBruce_Wayne: my demo sent me an empty multipart-params map until I set that
21:01Bruce_Waynealright got ya
21:01llasramazeirah: Things which are not such (including binding forms and argument parameter lists) use vectors with `[]` istead
21:01Bruce_Wayneany chance you know how to set that in hiccup?
21:01llasramExplicit maps use '{}' etc
21:01azeirahOh well, I liked it, I'd just like to use it on clojure
21:02justin_smithBruce_Wayne: something like [:form {:enctype "multipart/form-data" ...} [:input ...]]
21:22Bruce_Waynethanks justin
21:22Bruce_Wayneworks like a charm
21:23justin_smithawesome!
21:23justin_smithfunny, after all taht, it was the html form
22:28loliveiraHow to use stuartsierra’s component library with compojure?
22:30justin_smithloliveira: compojure is a routing library, the key is integrating component with ring, which is the server library
22:30justin_smithloliveira: this gist has a decent example https://gist.github.com/bowmanb/8560704
22:32loliveirajustin_smith: but this example misses the routing part. =/
22:33loliveirahow do I pass the dependencies to my hanlders?
22:34justin_smithloliveira: 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:34justin_smithloliveira: what is there in a route that needs to be stopped / started?
22:35justin_smithmaybe I don't understand what you are doing
22:39loliveirajustin_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:40loliveirajustin_smith: How show-db-data has access to the db component?
22:41loliveirajustin_smith: The doc says that I should never pass the system as argument...
22:41justin_smithloliveira: 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:42justin_smithloliveira: see under Usage in this link, with (assoc component :connection ...) https://github.com/stuartsierra/component
22:42justin_smiththen, another component can hand the db information to the handler creation function
22:43justin_smith(by getting that same :connection key out of the component)
22:43loliveirajustin_smith: hum… so I should not use defroutes?
22:43justin_smithyou would, but you would invoke it inside the start for that component, I think
22:44justin_smithloliveira: wait, actually I was a bit off
22:44justin_smithassociating :connection is for the component to get it back later, maybe not to share with other components
22:45justin_smithbut that page I linked shows how to make one component use data from another
22:45justin_smithvia component/system-map
22:46loliveirajustin_smith: ok, I will give a try. ty. =)
22:52justin_smithloliveira: it's been a while since I checked out the docs for component, I actually like them a lot now
22:52justin_smith(inc stuartsierra)
22:52justin_smith$ping
22:52justin_smithlazybot is down :(
22:52loliveirajustin_smith: pong
22:53justin_smithI was pinging lazybot, who tracks karma, because I was trying to up stuartsierra's karma
22:53loliveirajustin_smith: oh… =)
22:54loliveiranewbie here. =)
22:55justin_smithloliveira: yeah, your nick looked unfamiliar
22:56justin_smithloliveira: we also have another bot, who is mainly for demonstrating one liners to help explain how clojure works
22:57justin_smith,(map inc (range 10))
22:57clojurebot(1 2 3 4 5 ...)
22:57loliveira,(println “hello world”)
22:57clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: “hello in this context, compiling:(NO_SOURCE_PATH:0:0)>
22:57justin_smithloliveira: smart quotes!
22:58justin_smithyour irc client is too smart for your own good
22:58loliveiralol
22:58justin_smith,(= \" \“)
22:58clojurebotfalse
22:59loliveiraI can’t find how to disable them.
23:00loliveira
23:02loliveira,(println "Hello world!”)
23:02clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading string>
23:02justin_smithloliveira: now it's the other quote on the end I think
23:02loliveira,(println "Hello world!")
23:02clojurebotHello world!\n
23:02loliveiraviva!!!
23:09loliveirajustin_smith: It worked! I https://www.refheap.com/92350
23:09justin_smithvery nice, I'll make a note of that for when I really try component out
23:12loliveirathank you for the help
23:12justin_smithnp
23:13justin_smithso check this - someone who designed a mcdonalds playing piece does not know math http://i.imgur.com/wNEZjrx.jpg
23:13justin_smithI decided to calculate that number using clojure...
23:14justin_smithhttps://www.refheap.com/92351
23:14justin_smithactually this view is more impressive https://www.refheap.com/92351/raw
23:14justin_smith427913 digit number
23:16TimMc:-)
23:19justin_smithin other news, 427913 digit numbers slow your repl buffer down a little when printed
23:23loliveirajustin_smith: i don’t get it.
23:23justin_smithwhich part?
23:26m00nlightThe java interop of java.util.Date in clojure does not contain the time-zone information as Java did?
23:26justin_smith,(java.util.Date.)
23:26clojurebot#inst "2014-10-27T03:25:32.548-00:00"
23:26justin_smiththe time zone is at the end
23:26justin_smiththe -00:00 part
23:26m00nlightYes
23:26m00nlightThe output of Java is :Tue Aug 12 22:46:54 SGT 2014
23:26loliveirawhat is a mcdonalds playing piece?
23:27m00nlightwhile the clojure is : #inst "2014-08-12T14:46:54.000-00:00"
23:27justin_smithloliveira: oh, here in the US we have a game, mcdonalds monopoly, where you collect playing pieces for prizes
23:27loliveiranow it makes sense
23:28m00nlightSo it seems that the java change the utc time to local time-zone, while the clojure interop of java.util.Date does not
23:28justin_smithm00nlight: 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:30justin_smith,(.toString (java.util.Date.))
23:30clojurebot"Mon Oct 27 03:29:34 UTC 2014"
23:30justin_smithm00nlight: if you use that form, it will show your local time zone
23:30justin_smithclojurebot is using UTC natively
23:30m00nlightjustin_smith: Thanks, it seems the .getHour methods return the hour in local time zone
23:31justin_smithm00nlight: explicitly calling .toString gets the same default printed rep that java gives
23:31justin_smithm00nlight: clojure should not be doing anything java isn't when it comes to constructing Date with 0 args
23:31justin_smith(nor should it fail to anything java would do in that case)
23:32m00nlightjustin_smith: Yes, got it