#clojure logs

2014-10-25

00:26ddellacostajustin_smith: I guess it was an hour ago you mentioned it, but been using schema a lot lately and really liking it
00:26ddellacostawill be really happy if they provide some tools to dump out the (schema) type annotations into docs
00:26justin_smithI am literally putting it into the codebase this very moment to help track down errors I get on certain inputs
00:26justin_smithddellacosta: that would be an awesome feature for marginalia
00:26ddellacostanice
00:27ddellacostajustin_smith: yeah, right? would love to have that in there. I have to say, that has added a lot to the readability of my code. I didn't realize how crippled I was by not knowing what types are going in and out of my fns
00:27ddellacostadoing haskell has spoiled me there, that is a really nice thing about haskell libs and docs
00:28justin_smithddellacosta: I learned clojure by being dumped into a big ball of mud codebase, I had been doing a lot of ocaml before getting hired there - what I wouldn't have given to be able to declare enforced descriptions of the datatypes going into the tangled web of functions I was taking on
00:29ddellacostayeah, I can imagine that was a big shock!
00:29justin_smithddellacosta: instead, I wrote unit tests for each function as I was reading it, which was helpful, but not as concise or helpful as adding schema declarations would have been
00:30ddellacostajustin_smith: oh yeah, along those lines, been trying to integrate test.check lately too, but still at early stages with that
00:30justin_smithso it was iterative - read the funciton, guess what the hell it was doing, write unit tests, if they pass they describe the current behavior of the code... reverse engineering via tests
00:30ddellacostaoh man, I know that pattern *very* well
00:30justin_smithkind of tdd inside out
00:30justin_smithoh, I should have guessed it was a common thing :)
00:30technomancymarginalia-mode.el
00:30technomancyplease someone write this
00:31justin_smithis there a name for it? tdrc - test driven reading comprehension?
00:31justin_smithtechnomancy: that would rock so hard
00:31ddellacostayeah, kind of "big ball of mud de-complecting-DD" ;-)
00:31justin_smithtechnomancy: also, I should mention that after your persistence in bringing them up, I am finally really using multimethods in anger, and I am liking them
00:31justin_smiththanks
00:32justin_smithprismatic/schema even has its own wrapper for defmulti
00:32ddellacostaoh didn't know that, neat
00:32technomancyI knew being a cagey old hermit would pay off
00:32technomancycool
00:32ddellacostajustin_smith: also check out plumbing if you haven't--got some stuff above and beyond schema that makes it useful
00:33justin_smithyou can specify schema for method dispatch, or for the args
00:33justin_smithddellacosta: cool, I will add it to the list
00:33justin_smith(inc the clojure community)
00:33lazybot⇒ 1
00:36ddellacosta:-)
00:37ddellacostatechnomancy: I gotta bug you some time about not being able to figure out why checkouts aren't working for me...I must be doing something dumb. :-(
00:37technomancyjustin_smith: had you been doing ocaml professionally before, or just funsies?
00:37justin_smithtechnomancy: just funsies, but serious hours of funsies
00:37technomancycool, cool
00:37justin_smithtechnomancy: the clojure job was my first real tech job of any sort
00:38ddellacostayou cats see the comparison btw OCaml and SML that popped up recently?
00:38technomancyI guess "funsies" sounds dismissive
00:38justin_smithbeyond being payed to stare at some php for a couple weeks at a time
00:38technomancydidn't intend that
00:38justin_smithtechnomancy: it's all good
00:38technomancyddellacosta: definitely. hope to get a release out soon, so get a bug report in soon
00:38justin_smithddellacosta: no, whats the gist?
00:38ddellacostatechnomancy: yeah, I'll start with an issue...I'm not sure it's a bug our our own confusion here
00:38technomancycourse it's been "just around the corner" for a while now
00:39technomancywhile I spend my nights sanding and doing circuit design
00:40ddellacostajustin_smith: oh, was just comparing syntax, thought it was an interesting comparison. Trying to find it now...
00:40ddellacostahere it is: https://news.ycombinator.com/item?id=8497214
00:40ddellacostaand if you want to avoid HN entirely, the direct link: http://adam.chlipala.net/mlcomp/
00:41technomancyjustin_smith: you did find something after that caribou gig fell over, right?
00:41ddellacostasince I've been reading Bob Harper's stuff lately been poking a bit at SML, never touched OCaml before though. And I didn't realize F# was so closely related to OCaml (or, at least I've been made to believe so by someone's throw away comment on HN I guess...)
00:42justin_smithtechnomancy: I've been coasting on a retainer with the folks that hired me to do caribou, but I have some leads around town, just have to get off my lazy ass and brush up the resume
00:42justin_smithand actually apply etc.
00:42technomancyah, gotcha. good luck.
00:43ddellacostajustin_smith: if you have some devops experience and are in North America, we are looking for devops/clojure dev 50/50
00:43justin_smithtechnomancy: since it was my first tech job, I am used to a very spartan lifestyle, I saved a lot of money in a couple years, and its still tiding me over
00:43technomancygood on ya
00:43justin_smithddellacosta: yeah, I am at home on the cli with a linux box, can set up servers etc.
00:43technomancysome folks start drawing a paycheck and it all goes to their head
00:44justin_smithddellacosta: feel free to msg me more info if you like
00:57danneu[cljs] any obvious reason why (<! a-dropping-buffer) is throwing this console err: Uncaught Error: No protocol method ReadPort.take! defined for type cljs.core.async.impl.buffers/DroppingBuffer: [object Object]?
00:59justin_smithdanneu: that makes me think the protocol definition got re-evaluated but an instance of the old version of the protocol is still around
01:00justin_smithdanneu: or at least that happens in clj, dunno about cljs
01:01danneuoh wait, TIL that you pass {dropping,sliding}-buffer to the `chan` function
01:05arrdemwith test.check is there a good way to express special equality relationships between generated values?
01:05arrdemsay I want to ensure that behavior B exhibits only if two generators are equal and otherwise behavior A occurs
01:06justin_smithdanneu: ahh, reading fail on my part, I saw a-dropping-buffer and assumed chan-with-a-dropping-buffer
01:06arrdemI don't see a way to do this other than to have one test where I just use one generator for both values and ensure the equality case, and a second spec where I consider both cases using two possibly equal values
01:07reiddraperarrdem: nothing beyond just writing the if expression in your property
01:07arrdemreiddraper: okay. that's what I expected. thanks.
01:08reiddraperarrdem: and I think it'd be fine to have two properties, as you describe
01:08reiddraperkeeps each one nice and simple
01:08arrdemreiddraper: right that's what I'm doing, I just don't like that the "unequal" case is complected by the possibility of the two generators colliding
01:10reiddraperarrdem: right. In other quick checks you can 'discard' tests, but I haven't found a really compelling reason to implement that yet, but I wouldn't rule it out either
01:11arrdemreiddraper: honestly a pair generator where a and b are guranteed never to be equal would solve this for me...
01:12akhudekI wish clojure.data.xml had an option to preserve whitespace
01:12reiddraperArrdem: it would suffer the same caveats as such-that, which is we might have to spend a long time retrying to generate values that match the predicate
01:13reiddraperOr what if you accidentally: (gen/distinct-pair (gen/return 0) (gen/return 0))
01:13arrdemreiddraper: or you can construct a non-colliding relation between the two values..
01:13arrdemoh hice
01:13arrdem*nice
01:14reiddraperarrdem: that function doesn't exist, I'm just illustrating a pair that could never be unique
01:14arrdemreiddraper: generally sure. in the case at hand I can define such pairs reasonably.
01:15reiddraperarrdem: distinct-pair would be easy to write:
01:15reiddraperarrdem: (defn distinct-pair [a b] (gen/such-that (fn [[x z]] (not= x z)) (gen/tuple a b))
01:17reiddraperarrdem: just mind the such-that caveat: https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.clj#L268-L272
01:19arrdemreiddraper: I just want a distinct (char . char) pair. p >> 10% here :D
01:20reiddraperarrdem: i'd expect that with (gen/tuple gen/char gen/char)
01:20arrdem&(* 1/255 1/255)
01:20lazybot⇒ 1/65025
01:20reiddraper(if you're looking with gen/sample, make sure you sample enough values: gen/sample my-gen 100) or so
01:21arrdemvery tempted to add for-all -> \forall rewriting to my .emacs.d :P
01:22reiddraper:)
01:22reiddrapergen/char too should be fixed to support the full unicode range, but, it doesn't at the moment :|
01:22reiddraperas you mentioned, just 0-255 at the moment
01:23arrdemwell.. there's the clj-dev chatter about working with unicode chars..
01:23reiddraperif my stats are correct, you'll expect to see the same pair 1/256 times
01:24reiddraperso, fits your 10% just fine
01:26reiddraperanyway, past my bedtime
01:27arrdemg'night
01:27arrdemthanks
01:27arrdem(inc reiddraper)
01:27lazybot⇒ 4
01:31justin_smith(inc reiddraper)
01:31lazybot⇒ 5
01:31clojanglesheya clojurists. I'm going through joy of clojure. in the section about namespaces, it talks about renaming things. it seems to suggest I can do this:
01:31clojangles(ns joy.argh (:require [clojure.set :rename {intersection isxn}]))
01:32clojanglesbut I can't get at isxn, any hints or doc pages you recommend I read?
01:33justin_smithclojangles: clojure.set/isxn
01:33justin_smithclojangles: require does not do any remapping, unless you add the :as or :refer keys
01:33justin_smith(doc require)
01:33clojurebot"([& 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
01:33justin_smithit's a big doc string, better to read it online
01:34justin_smith$source require
01:34lazybotrequire is http://is.gd/cHBGH6
01:34clojanglesah nice, thank you justin_smith. I'll dig in
01:34justin_smithclojangles: in general, the clojure.repl/doc and clojure.repl/source functions are very helpful
01:35justin_smithmost clojure repls should make them immediately available, but you are learning right now how to require them if not :)
01:36clojanglesI'm using leiningen, so I'm good to go there :) I love that the source function is a thing
01:36justin_smithclojangles: ahh, and the source as reported by lazybot is an old version, but you can run (source require) in your own repl to see the version you have
01:37justin_smithclojangles: yeah, it makes exploring the language much easier
01:37justin_smiththough clojure.core code is highly optimized code, not idiomatic code you would use outside a tight loop (since core is in everyone's critical code)
01:40clojanglesjustin_smith: I can still use (source n) to browse libraries though for some examples of more idiomatic code?
01:41justin_smithclojangles: absolutely
01:42justin_smithmargenalia makes nice readable output from codebases too (via the lein marg plugin) - I recommend adding it to your :plugins in ~/.lein/profiles.clj
01:43justin_smithsome good projects for code browsing include flatland/useful and ring (imho), also anything by ztellman tends to be well written
01:43arrdem&(not= 1 2 4)
01:43lazybot⇒ true
01:44arrdem&(not= 1 2 1)
01:44lazybot⇒ true
01:44arrdemhum..
01:44justin_smith,(not= 1 1.0 1/1)
01:44clojurebottrue
01:45arrdemthere we go
01:46clojanglesjustin_smith: awesome, adding those to my list of clojure things. thank you again!
01:46justin_smitharrdem: were you checking for anything in particular?
01:47arrdemjustin_smith: https://github.com/oxlang/oxlang/blob/master/test/oxlang/parser_test.clj#L9-L14
03:04mearnshjustin_smith: hey i like noise, saw KD recently too :)
03:06justin_smithmearnsh: cool. I knew him in the mid '90s when I lived in Chicago, he's been a big influence.
03:07justin_smithmearnsh: cool thing - he was using a pedal I helped design
03:07mearnshah sweet
03:07justin_smith(but he did not realize until I pointed it out)
03:08justin_smithyou've maybe heard of 4ms pedals?
03:08mearnshi don't know much about gear so no
03:10justin_smithDan from 4ms is an old friend of mine, and I helped him design the first pedal that got him into the noise-pedal-making business (when I say help design I mean he was an engineer and I was just a dumb kid saying "I want a pedal that does blah blah blah")
03:12mearnshneat
03:16rritochIs there a reader macro to concatenate strings? To constrain sources to 80 characters/line (including spaces) I'm finding myself doing (str "blah." "blah.") which are functions which execute at compile time, but I suspect a reader-macro would be faster if there is one.
03:18justin_smithyou mean it would compile faster? there is no reader macro for string concatenation, no
03:18justin_smithstr uses a StringBuffer internally, can't do much better than that on the jvm
03:19rritochYeah, that is what I was hoping for, something like $("foo" "bar") or something like that.
03:20rritochanyhow, thanks. I have about 200 of these long strings to break up so it's going to be another boring day.
03:21justin_smithsounds like a good task for an editor macro
03:22justin_smith,*data-readers*
03:22clojurebot{}
03:22justin_smiththat will return all the readers currently in play that beyond the clojure defaults
03:22justin_smithyou could actually define your own reader btw, with data_readers.clj
03:23justin_smithI don't think it would do much in this case except maybe make your code look nicer
03:23justin_smithfairly comprehensive docs about the reader, including data_readers.clj is here http://clojure.org/reader
03:25rritochSounds like a good idea because this is a common problem, but I'd have to clear that with my boss. It's a schema (list of maps) and most of the decriptions are too long to fit in 80 chars.
03:27justin_smith,default-data-readers ; this is what I was looking for
03:27clojurebot{inst #'clojure.instant/read-instant-date, uuid #'clojure.uuid/default-uuid-reader}
03:27justin_smiththere are not many of them, wow
03:38dysfunso i've got a clojure protocol that i want java stuff to use. i know it's going to spit out an interface, but i presume i'll have to check for the java interface, not that it implements the protocol?
03:42justin_smith,(binding [clojure.core/*data-readers* {'s clojure.core/str}] (read-string "#s [a\n b\n c]")) ;; rritoch
03:42clojurebot"[a b c]"
03:42justin_smithrritoch: that works, the one weird thing is that it all needs to be inside parens or brackets - but you could write a function that is like str, except it removes brackets :)
03:45justin_smithdysfun: where would you be doing this checking?
03:46justin_smithdysfun: wouldn't the use case be that you write code that calls the interface methods, and then java passes something in? so you aren't checking for the interface, you are just calling a protocol function, as far as the clojure code is concerned. But if it implements the right interface on the java side it should just work.
03:47justin_smithotherwise, runtime error saying that the java object does not implement interface foo
03:47dysfunyes, that's basically the case
03:48dysfuncool. thanks
04:14rritochjustin_smith: I see, thanks. What a mess though
04:14justin_smithrritoch: the mess is only there so I can demonstrate evaluation inside the thread binding
04:14justin_smithrritoch: if you use data_readers.clj as intended, it will work for normal code
04:14rritochYou'll see what I mean in a sec
04:15justin_smith#s [whatever you want can go here]
04:15justin_smith(complete with line breaks, whatever)
04:15rritoch,(binding [clojure.core/*data-readers* {(symbol "s") (fn [& args] (apply str (read-string (apply str args))))}] (read-string "#s( \"a\" \"bc\" \"d\")"))
04:15clojurebot"abcd"
04:15arrdemjustin_smith: note that user defined data readers are _supposed_ to have namespace prefixes
04:15arrdemclearly this can be avoided however
04:15justin_smitharrdem: yeah, that was just for simplicity
04:16justin_smithrritoch: those symbols do not need to be in double quotes, not that in mine they were not
04:16justin_smithit works either way
04:16justin_smith*note that
04:17rritochOk, well I put them in quotes as I'd ultimatly want the source code to be #s("some text" "some text")
04:17rritochBut either way, it seems it will be faster compile time if I stick with the plain (str syntax.
04:18justin_smithyeah - you'll want string/join rather than apply str for that
04:18justin_smith(otherwise you get "some textsome text")
04:19justin_smithrritoch: to be clear, you wouldn't be using read-string in your code, read-string is just an easy way to demo it in the bot repl
04:19rritochjustin_smith: "some textsome text" is the expected output.
04:19justin_smithoh, OK
04:19rritochThe point of this would be to break the string into multiple lines, adding \n as needed.
04:20rritochBut the (str "some text" "some text") will probably be faster than the reader macro so I'm better off with that.
04:21borkdudewhy does clojurescript ISeq protocol not have "cons", like specified in the ISeq JVM interface? https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L251
04:21justin_smithgiven that this is only speeding up compilation time, it's a spit in the ocean given how slow clojure builds are
04:22rritochlol
04:23rritochIt's ok with me, I get most my breaks while waiting for builds to complete.
04:24rritochBut I think its mostly from leiningen and network latency
04:25rritochMy builds seem significally faster for apps with most deps on a lan based maven repository
04:25rritochFor my work all repositories are on amazon servers, which aren't always fast
04:26justin_smithdo you frequently clear your cache or change deps?
04:28rritochNot really, but I'm always building from snapshots
04:36dysfunjustin_smith: only because it takes so long to boot up the jvm
04:36dysfunand for the most part, autotest has fixed that
04:37dysfunbut clojure compilation really doesn't seem particularly slow. I think you'd have to have a lot of code
04:37dysfunthat said, starting up the jvm eats all four cores on this because it's not I/O bound (SSD)
04:38dysfunit's one of the things scala developers quite peeved by. it takes ages to compile scala
04:38dysfunthe jvm startup on top is just insult to injury
04:40justin_smith,(time (eval '(* 1000 1000)))
04:40clojurebot"Elapsed time: 1.095008 msecs"\n1000000
04:41justin_smith,(time (* 1000 1000))
04:41clojurebot"Elapsed time: 0.034647 msecs"\n1000000
04:42dysfunconsider that with autotest running, by the time i've hit save and looked at the terminal, my tests have rerun
04:47justin_smithdysfun: the jvm doesn't always load slowly - it depends on what classes you use (they are loaded on demand). The core of clojure, with the compiler, is very large.
04:47justin_smithdysfun: a hello world in java compiles and runs very quickly
04:48dysfunyes, but i'd hardly call java development 'interactive' in the way repl development is
04:48justin_smithright
04:49dysfunconsider that to use javafx from java, you have to build a jar to test it
04:49dysfunnot that deving javafx is a particularly smooth procedure in clojure either
04:50justin_smithbut look at what emacs does for other languages - there is usually a mode that periodically compiles your file as-is, and highlights any syntax errors or warnings. For most of us this would render our machine unusable if clojure mode did that.
04:51dysfunwell i hook C-c E to be "compile file to point in repl" (pastes it into the repl buffer and hits enter) and emacs doesn't stutter much most of the time
04:52dysfunit's utterly "fast enough"
04:52justin_smithdysfun: in flycheck, it's basically starting up the compiler from scratch every 15 seconds or so
04:53dysfunhuh, i don't have flycheck enabled for clojure mode
04:53justin_smithright, it doesn't exist, it wouldn't work
04:53justin_smith(because some things don't reload very cleanly, and starting from scratch every time would be rediculous)
04:53dysfunit would if it used grenchman
04:53dysfunor you did it with cider so you can use nrepl
04:54dysfunyeah, there comes a time when you have to restart your jvm, but it's fairly rare
04:55justin_smiththere are things that don't play nicely - changes to project.clj, changes to protocols or multimethods, changes to gen-class forms. These things can be worked around mostly, but it's not simple.
04:55dysfunwriting software rarely is
04:56dysfuni'm teaching a friend to program on monday. i wonder how well he'll do
05:06rritochdysfun_: Good luck with that. "You can lead a horse to water, but you can't make them drink", I've taught dozens of people to program, only about 10% actually become programmers and only about 5% are any good.
05:07amalloythose sound like pretty good success rates. how many people who learn to run go on to be runners?
05:09dysfunwell he has a very technical mindset, so i think he'll take to it quite well
05:09dysfuni don't anticipate he'll become a programmer though
05:10dysfunplus i've chosen clojure. it's kind of nice to teach someone lisp as their first language because they aren't set in OO ways already
05:10rritochdysfun: I think it's more a personality thing. Power hungry type A personalities that are willing to spend hours reading technical manuals (a painful experience) seem to be the ones that succeed.
05:11dysfunthat's a helluva stereotype
05:11dysfuni don't consider myself in the slightest bit 'power hungry'
05:12dysfunand i've been programming for getting on 20 years now
05:13dysfunthe patience for wading through docs i'll say is definitely a prereq though
05:15rritochdysfun: I suppose someone with a large amount of patience would also be good, but I've never met anyone like that. The hardest skill to teach is returning to projects after you've quit dozens of times .
05:15borkdudedoes anyone have a non React todo-mvc clojurescript app that doesn't re-render naively but has fine grained DOM updates?
05:16dysfunpersonally it comes in ebbs and flows. if i'm quite relaxed, i have a lot of tolerance for boredom. otherwise i'd better go do housework or something because there's no point sitting at a computer
05:16dysfuni must have picked up and put down some of my projects hundreds of times over the years
05:17rritochdysfun: You may be onto something there, I've written some of my most innovative code while intoxicated.
05:18rritochdysfun: But normally I find my solutions after a great deal of swearing.
05:18dysfunmy tolerance for boredom goes either way when intoxicated. sometimes great, sometimes not so much
05:19dysfuncreativity on the other hand, well...
05:19dysfunand makes people more inclined to write tests as well i find
05:29rritochdysfun: Well, it is an interesting project. I'm having my team learn Java before clojure because I'm not sure it is possible to understand clojure without understanding Java.
05:30dysfunprovided they've got experience in any comparable language, i don't agree
05:30dysfunand for the majority of clojure work, you need to know very little about java
05:30justin_smithrritoch: I pulled it off, I did need to learn how to read javadoc though, but you can learn that without learning all the ins and outs of java
05:30dysfuni'd contest there's more risk of breaking them into bad habits
05:37elegizeHow does one get started with clojure?
05:38rritochelegize: Depends on your experience, what other languages do you know?
05:40rritochelegize: If you know any other lisps, you can probably get away with the online documentation, otherwise I'd suggest the book "Clojure Programming" http://shop.oreilly.com/product/0636920013754.do
05:53rritochjustin_smith: How did you get started with clojure? I already knew LISP & CLISP so I was able to start programming in clojure with just that, but after the fact I was pointed to that book and it hepled a lot.
05:54rritochjustin_smith: Though honestly I never finished reading past the first section. It was more "brain-washing" than I wanted to deal with.
05:56justin_smithbrain washing?
05:57justin_smithI had experimented with a large number of languages, but just for hobby stuff. I was using scheme and ocaml mostly when a friend pulled me in to do programming professionally with clojure.
05:58nextosHello, newbie here. What would be the idiomatic way to build a stream processing pipeline, like the typical foo | bar | baz in parallel. I should use lazy sequences, but how to run each transformation in parallel?
06:00justin_smithnextos: there are a few approaches. Some of them don't even use laziness.
06:00justin_smithnextos: are the tasks CPU bound? IO bound?
06:01nextosjustin_smith: they are mostly CPU bound, and they call external programs via a shell
06:02nextosjustin_smith: i must note i would like to run all transformations in parallel and there's a ton of data, so probably i should use laziness?
06:03nextosjustin_smith: so i want the same semantics as in unix foo | bar | baz, where foo, bar & baz are reading from input streams in parallel
06:04justin_smithnextos: so foos output goes to bar etc?
06:05nextosjustin_smith: yes, and foo and bar are executing in parallel, so bar starts processing and outputting stuff as soon as it gets a bit of input from foo
06:06justin_smithI think core.async would work decently for that, but avoid IO in go blocks
06:08rritochnextos: If your just piping shell commands why not just have the shell handle the piping?
06:09nextosrritoch: well, there's very heavy processing of the shell commands which i do in clojure
06:10nextosrritoch: i'd be interested in seeing how this can be done in a simple fashion. If i have to use core.async, i would probably use something like lamina or even storm instead
06:13justin_smithnextos: reducers, or a transducer based replacement of them, could be an option here.
06:17rritochnextos: I honsetly have no idea how you'd do this in clojure idiomatic code, but I'd just use something like (.exec (Runtime/getRuntime)) and then bind *in* and *out* to my own readers/writers which pipe the data, though I don't remember right now the best way to pipe from a writer to a reader
06:22sdfdsfsfdsfdhi
06:26rritochnextos: Clojure readers/writers are BufferedReader/BufferedWriter so you'll probably want to pass a PipedReader to a BufferedReader, and a PipedWriter to a BuffereddWriter, for binding, if you choose to go in that direction.
06:27rritochnextos: But it is in no way "clojure idiomatic"
06:28nextosrritoch: yes, thats not idiomatic ;) but thanks
06:30justin_smithnextos: another option is futures that share queues, but that's just lighter weight core.async without the sugar
06:33nextosjustin_smith: ok, thanks!
06:35justin_smithnextos: java.util.concurrent has a few kinds of queues that are safe for usage across threads, or you can use clojure.lang.PersistentQueue/EMPTY inside an atom
06:35justin_smith,(def q (atom clojure.lang.PersistentQueue/EMPTY))
06:35clojurebot#'sandbox/q
06:35justin_smith(swap! q conj :a)
06:35justin_smith,(swap! q conj :a)
06:35clojurebot#<PersistentQueue clojure.lang.PersistentQueue@3c6f0c48>
06:36justin_smith,(into [] q)
06:36clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Atom>
06:36justin_smithoops
06:36justin_smith,(into [] @q)
06:36clojurebot[:a]
06:36justin_smith,(swap! q conj :b)
06:36clojurebot#<PersistentQueue clojure.lang.PersistentQueue@8de188a4>
06:36justin_smith,(into [] @q)
06:36clojurebot[:a :b]
06:36justin_smith,(swap! q pop)
06:36clojurebot#<PersistentQueue clojure.lang.PersistentQueue@3c6f0c0b>
06:36justin_smith,(into [] @q)
06:36clojurebot[:b]
06:37justin_smithwell I probably should have grabbed that value, but hopefully you get the idea
06:55ddfreyneHey peeps. I am having a bit of a difficult time wrapping my head around some Clojure behavior.
06:55ddfreyneFor instance, (:firstname nil) returning nil instead of an exception.
06:56ddfreyneI wrote down the problem that I’m facing: https://gist.github.com/ddfreyne/57efc45455fa5837b58e
06:56ddfreyneI have a strong feeling I am not using Clojure properly, or that I don’t understand Clojure’s philosophy here.
06:57justin_smithddfreyne: a keyword, symbol, hash-map, set, or vector when used as a function ends up calling get
06:58justin_smithddfreyne: get returns nil instead of throwing exceptions, but you can provide a not-found value to detect the difference between a nil value contained in the collection vs. the key you used being absent
06:59justin_smithddfreyne: (map #(:firstname % ::not-found) (:body response))
06:59justin_smiththen you can test for ::not-found
07:00justin_smith(which is namespaced, so it is extremely unlikely that it came in from elsewhere, but you can use a sentinel like (Object.) if you want something that will definitely be unique
07:00ddfreynejustin_smith: Hmm, good point. It seems that I’d be littering ::not-found throughout the code though; I’d likely want to replace (:body response) with (:body response ::not-found) then too.
07:01justin_smithddfreyne: sure, and you could make your own function for this, of course
07:01justin_smithit's not a complex bit of code, it's just not the default behavior
07:03justin_smithddfreyne: contains? will likely be useful if you want to do a proper assertion check
07:04justin_smith,((fn [place key] (assert (contains? place key)) (get place key)) {:b 0} :a)
07:04clojurebot#<AssertionError java.lang.AssertionError: Assert failed: (contains? place key)>
07:04ddfreynejustin_smith: I am also tempted to implement safe-get myself. Somewhat weird to have to reimpement it though.
07:05justin_smithI think the encouraged style of programming is one where not finding data in a datastructure isn't neccessarily an error
07:06justin_smithddfreyne: I have just started using prismatic/schema which allows defining specific shapes data should have, so it not only checks the data at runtime (optionally) but also allows what are essentially type annotations on arguments and return values (also optional)
07:07justin_smithso instead of throwing an error if you try to access :firstname and it isn't there, you throw an error if the input doesn't have :firstname in the right place
07:08ddfreynejustin_smith: Yeah, I was looking at prismatic/schema too. It’s definitely useful, although I am a bit confused as to why the language itself is a bit… lax.
07:09justin_smithddfreyne: I think part of it is that it's the lisp tradition
07:09ddfreynejustin_smith: As for having a style of programming where not finding data is not necessarily an error: there are plenty of cases where you _know_ some incoming data has a certain structure, and it’s good to verify those assumptions.
07:09justin_smithand really I think the laxness consists of get, first, and rest - it's just that so many things are implemented in terms of these three functions
07:10ddfreyneYeah, I believe so.
07:12ddfreyneI’ve had a bunch of failed deploys of Clojure services at wor, and the root cause for all of them turned out to be the same
07:12ddfreyneSo I definitely want to work on that.
07:13justin_smithI think schema is a bonus anyway, because not only does it help track down errors, but it also helps document what kind of input a function expects
07:13justin_smithwhich in some codebases can be kind of unclear
07:15ddfreyneYup. It is odd to add type information all over the place in a dynamic language though. Feels a bit schizophrenic.
07:16justin_smithddfreyne: well, it isn't quite type information: you are likely to specify one key you care about (and others may or may not be present in the same hash, or you may not need to specify a schema for other args to the function even)
07:18ddfreyneTrue. It’s alos more about structure rather than types.
07:18justin_smithyeah - though langs like OCaml can infer "the type that contains an int under key a" and enforce that just by analyzing your code
07:19justin_smithso really it is a type that we would call a shape :)
07:21justin_smithand in some ways both schema and ocaml overlap with what java does with interfaces (though java is much more strict and explicit about all of it)
07:36rritochddfreyne: Just to add my two cents to your second problem, map functions returning null's which populate sequences is a common problem that I run into and I get around it by filtering my lists by identity (filter identity (map #(:foo %) [{:bar "bar"}])) I don't know if it is the best solution, but it works.
07:37justin_smithrritoch: that's what keep is for
07:37rritochkeep?
07:37dysfunkeep is like filter identity . map
07:37justin_smith,(keep :foo [{:foo :a} {} {:foo :b}])
07:37clojurebot(:a :b)
07:38justin_smithdysfun: almost, it lets false through though, just drops the nils
07:38rritochchecking now ...
07:38justin_smithalso, #(:foo %) in that context is just :foo
07:38dysfunjustin_smith: yeah. not usually a problem here tbh. i'm generally using it with my own code and i know what that's going to return
07:39justin_smithdysfun: on the contrary, that's why it's *better* than filter identity - because false is not going to come in accidentally the way nil does
07:39dysfunoh i quite agree. i'm a fan of keep
07:40dysfuni'm not converted on () being true though
07:40dysfunchaining seq is a bit annoying
07:40rritoch,keep #(* 2) [1 2 3 4])
07:40clojurebot#<core$keep clojure.core$keep@14c5cb5>
07:40rritoch,(keep #(* 2) [1 2 3 4]))
07:40clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/eval71/fn--72>
07:40rritoch,(keep #(* 2 %) [1 2 3 4]))
07:40clojurebot(2 4 6 8)
07:40dysfun(partial * 2) also works
07:41rritochHmm, keep is my new best friend
07:41rritochIs there a keepv hiding somewhere?
07:41dysfuni cleaned up a lot of code when i found keep
07:42dysfunno, but you can (apply vector %)
07:42justin_smithdysfun: or better (into [] ...)
07:42dysfunis that 'better'?
07:42dysfunit's a couple of keystrokes shorter, but i try to avoid into generally
07:43rritochWhen I need to cast to vector I usually just (vec ...)
07:43justin_smithdysfun: check the source for vector, it does a bunch of consing
07:43justin_smithdysfun: so when you do (apply vector ...) it breaks up the collection into individual items, then uses cons to build a list, and then finally makes a vector from that list
07:43justin_smithinto is much more straightforward
07:46rritochIs there a benefit to using (into [] '(1 2 3)) vs (vec '(1 2 3)) ?
07:48dysfunjustin_smith: only the first few items?
07:49dysfunnot that i expect it matters much anyway. few programs crunch enough data that it'll make a noticeable difference. microbenchmarking is bad etc.
07:49rritochFrom looking at the source of vec and into the code behind is completely different, but it appears vec would be faster since it is done in one step as aposed to a loop?
07:49justin_smithrritoch: yeah, vec directly reuses the input as its basis
07:50justin_smithwhich, if you already had that collection, is a good thing iirc
07:51justin_smithrritoch: I think the fact that mapv uses either reduce and transients (which is what into uses internally) or just calls into is a clue
07:51justin_smitherr, wrong target there sorry
07:51justin_smithdysfun: ^^
07:52justin_smithdysfun: core tends to be pretty aggressive about micro scale performance stuff
07:52dysfunand terrible about documenting such things
07:52justin_smithdysfun: true that
07:53dysfun /me submitted a doc patch this week
08:03rritoch,(time (vec (keep (partial * 2) [1 2 3 4])
08:03clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
08:04rritoch,(time (vec (keep (partial * 2) [1 2 3 4])))
08:04clojurebot"Elapsed time: 0.703835 msecs"\n[2 4 6 8]
08:04rritoch,(time (filterv identity (mapv (partial * 2) [1 2 3 4])))
08:04clojurebot"Elapsed time: 3.346403 msecs"\n[2 4 6 8]
08:05rritochYep, keep is my new best friend
08:11rritochI guess I really need to read that refrence manual
08:13foodooand again, Clojure has showed me that I should look for the simple solution...
08:14dysfunrritoch: the cheatsheet is quite handy
08:15dysfunyou can 'golf' clojure. just in terms of complexity rather than code size (although it's often smaller)
08:15foodoobtw: What is currently the most-used unofficial documentation site for Clojure? clojuredocs.org? clojuredoc.org?
08:16dysfuncheatsheet goes to clojuredocs.org now, probably that.
08:34mmeixAgain a question to the wise: I just built two different versions of "fizzbuzz": https://www.refheap.com/92289 - which one would prefer, and why? (I consider the first one more readable...)
08:35mmeix(would you*)
09:05mfikesmmeix: Yes, am able to read the first one more rapidly owing to its use of data literals
09:07mmeixthanks - I guess core.match would be overkill in this case (in fact it is matching against a test pattern)
09:14mfikesmmeix: Yes, it made me think of pattern matching; I have no experience with core.match yet :)
09:15mmeixthe first example in https://github.com/clojure/core.match shows just this application, as I found out afterwards
09:17dark4eg#/join clojurescript
09:44expezdoes tools.nrepl guarantee the delivery order of messages?
11:06lgrapenthinHas somebody attempted to turn tbaldrigdes ioc macro into a step debugger already?
11:17patrkrishi folks. i've written a function for reading #inst literals that returns either LocalDate or LocalDateTime from the new Java 8 datetime APIs. it works fine in the REPL when i enter #inst "1984-08-27" for instance, but when I use the same literal as a value in a map, I get the following error: CompilerException java.lang.RuntimeException: Can't embed object in code, maybe print-dup not defined: 1984-08-2
11:17patrkris7
11:19patrkrisah, found this: http://blog.jenkster.com/2014/02/using-joda-time-as-your-clojure-inst-class.html, so nevermind :)
11:27gfredericksI keep thinking there oughta be a lib for setting up that reader literal stuff
11:27gfredericksbut I'm not sure exactly what it would look like
11:42noncom|2how do i get a fully qualified name of a symbol ?
11:43noncom|2for example, in a namespace i have a symbol "set-mark" that refers to a function. i want to record the call to this function with the arguments. so hpw do i get fully qualified name of it so that i could reproduce the call when evaled in a different namespace ?
11:48gfredericksnoncom|2: you're writing a macro?
11:49noncom|2gfredericks: right, a macro (record) that is wrapped around the usual call of the function... something like (apply)
11:50gfredericksI think resolve should work, at macroexpand time
11:50gfredericks,(doc resolve)
11:50clojurebot"([sym] [env sym]); same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"
11:50gfrederickshm
11:50gfredericksyeah
11:51noncom|2*ns* is clojure.core when i eval the recorded form from a different site :D
11:51gfredericksum
11:51gfredericksit should be the right thing at macroexpand time
11:51gfredericksi.e., it should be the namespace of wherever the call to record is happening
11:52noncom|2so, i just do (resolve) on the function-name symbol inside the macro ?
11:52gfredericksyeah, that'll give you a var
11:52gfrederickswith all sorts of helpful metadata
11:52gfredericks,(meta #'first)
11:52clojurebot{:ns #<Namespace clojure.core>, :name first, :added "1.0", :file "clojure/core.clj", :static true, ...}
11:53gfredericks^ like such
11:53noncom|2okay :)
11:53noncom|2thanks)
11:54gfredericksnp
11:57thedanko_sup fellas?
11:58thedanko_beautiful day in chicago
12:00thedanko_wow schema looks sweet
12:17patrkrisexit
12:53mmeix_Short question: I built two different versions of "fizzbuzz": https://www.refheap.com/92289 - which one would be preferable? (For me the first one is more readable...)
12:54bbloommmeix_: both of them seem a little needlessly cryptic
12:54mmeix_ok
12:55bbloommmeix_: http://rosettacode.org/wiki/FizzBuzz#Clojure that first one looks fine to me
12:55mmeix_there is a fine line between compact and cryptic, I guess ...
12:56mmeix_ah, that's clearer, yes
12:56mmeix_thanks
12:56bbloommmeix_: it's also more compact :-)
12:57mmeix_of course
12:57mmeix_still learning
12:57bbloomthe other ones on that page look awful
12:57mmeix_but it's getting better (with a little help from #clojure) :-)
12:57bbloom(iterate inc 1) is just silly
12:57justin_smithmmeix_: why (as-> n % [(rem % 3) (rem % 5)]) rather than [(rem n 4) (rem n 5)]
12:58justin_smithI don't see what as-> buys you here
12:58mmeix_right you are
12:58mmeix_just had found as->, only excusion :-)
12:59bbloommmeix_: if you're just learning: avoid core.match
12:59mmeix_ok
13:00mmeix_thanks
13:00mmeix_(words from the wise are very appreciated)
13:01justin_smithnow (interate inc' 0) might actually have a point, if you intended to get to numbers that high
13:03mmeix_aren't both iterate and range lazy?
13:03mmeix_(I thought so)
13:04gfredericksthey are
13:05mmeix_but iterate throws away interm. steps?
13:05justin_smithmmeix_: no, range uses inc, inc' is different
13:05justin_smith(doc inc')
13:05clojurebot"([x]); Returns a number one greater than num. Supports arbitrary precision. See also: inc"
13:05gfredericksjustin_smith: that's hard to imagine it getting that high
13:05justin_smithgfredericks: right, but I really did qualify what I said with "if you intend to get to numbers that high"
13:06justin_smithgfredericks: in the case we were talking about, they used inc instead of inc' anyway
13:06gfredericksjustin_smith: I'm just wondering if it's physically possible despite intentions
13:06gfredericksI'm also curious if there's any perf benefit; my understanding would say no
13:06mmeix_(ah: inc', hadn't seen the ')
13:07justin_smithgfredericks: there is a perf benefit for range not using inc'
13:07gfredericksjustin_smith: what from?
13:07gfredericks,(time (nth (iterate inc 0) 1000000))
13:07clojurebot"Elapsed time: 136.264005 msecs"\n1000000
13:07gfredericks,(time (nth (iterate inc' 0) 1000000))
13:07clojurebot"Elapsed time: 133.085312 msecs"\n1000000
13:08gfredericksoh range is chunked isn't it
13:08gfredericksI guess that would do it
13:08gfredericks,(time (nth (range) 1000000))
13:08clojurebot"Elapsed time: 169.179278 msecs"\n1000000
13:08gfredericksha
13:11justin_smith(nth (partition 10 (iterate inc' 0)) Integer/MAX_VALUE) ; space-heater
13:11gfredericksdoes the partition 10 enhance the heater somehow?
13:13justin_smithgfredericks: I wanted to make it spit out numbers larger than Integer/MAX_VALUE, but nth does not allow indexes that high
13:13justin_smithand I think the partition does introduce an overhead, yeah
13:14bbloomjustin_smith: try (drop Integer/MAX_VALUE) several times :-)
13:14justin_smithbbloom: good call
13:19gfrederickshuh. what is the benefit of nth taking an int
13:19gfredericks,(nth (range) 9999999999999)
13:19clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for int: 9999999999999>
13:20bbloomgfredericks: nth is linear for non-random access colls, so an int is more than reasonably big enough. for random access colls, i guess you could make an argument for longs for supporting sparse vectors etc
13:21bbloomgfredericks: but i suspect the reason they are ints is b/c they are often backed by java collections that take ints as indexes
13:21bbloomjava arrays, for example, are int indexed
13:21mmeix_(there is no sparse coll in clojure, right?)
13:21bbloommmeix_: it's called a map
13:21bbloom:-)
13:22mmeix_umpf
13:22mmeix_ok
13:22mmeix_sight
13:22mmeix_sigh*
13:22bbloomseriously, if you were to create a persistent/immutable sparse vector, you'd just be re-implementing clojure's persistent immutable hash maps
13:22bbloomor maybe the tree maps
13:22bbloomeither way, yeah, it's called a map
13:23gfredericks,{9999999999999 :hey}
13:23clojurebot{9999999999999 :hey}
13:23gfredericks^ big sparse vector
13:23mmeix_didn't think about it that way - thanks
13:23llasrambbloom: Random-access sparse anyway. Sequential-access sparse is a bit different :-)
13:24bbloomalthough, there could be a case for implementing a wrapper around maps to provide a vector-like interface
13:24bbloomso that nth, count, etc would make more sense for sparse vector usage
13:24mmeix_(bear with a beginner's confusions)
13:24bbloommmeix_: that's not a beginners confusion. i know lots of experts who don't understand that!
13:24mmeix_I only had the sequential case in mind
13:24bbloomllasram: sorted-map can give you sequential access to sparse vector-like maps
13:25gfredericks,{-3.14 :hey} ;; super weird vector
13:25clojurebot{-3.14 :hey}
13:25bbloom,(sorted-map 5000 :x 1 :y 99999999999 :z)
13:25clojurebot{1 :y, 5000 :x, 99999999999 :z}
13:25mmeix_bbloom thanks for encouragement :-)
13:25bbloomgfredericks: ugh. floats as map keys *cringe*
13:26bbloomequality? we don't need no stinkin' equality!
13:26gfredericksfloats haha what are you gonna do
13:27mmeix_{nil 3 false 2} seems to be legal ...
13:27gfredericksbecause ##(= nil false)
13:27lazybot⇒ false
13:27mmeix_(not I could think of a use case ...)
13:28mmeix_that I*
13:28gfredericks,(hash-map nil 1 false 2 'nil 3 'false 4)
13:28clojurebot{nil 3, false 4}
13:28gfredericks,(hash-map nil 1 false 2 (symbol "nil") 3 (symbol "false") 4)
13:28clojurebot{nil 1, false 4, false 2, nil 3}
13:28mmeix_funny
13:28justin_smith,(hash-map 1 :a 1N :b (float 1) :c (double 1) :d 1M :e)
13:28clojurebot{1.0 :d, 1 :b, 1M :e}
13:28andyfNot that bbloom needs any more Clojure warts floating around in his brain, but I did notice a while back that vector access and a few other related things can take longs, but silently truncate with loss of precision to ints before checking range bounds. Kind of odd.
13:29bbloomandyf: argh. that sucks
13:29justin_smithhaha, that turned 1N into 1
13:29gfredericksthe imaginary language in my head that I never made or designed has none of the flaws that clojure does
13:30andyf,([:a :b :c] 1)
13:30clojurebot:b
13:30andyf([:a :b :c] (+ 1 (+ 2 (*' 2 Long/MAX_VALUE))))
13:30andyf,([:a :b :c] (+ 1 (+ 2 (*' 2 Long/MAX_VALUE))))
13:30clojurebot:b
13:30mmeix_nil as a key: could there posssibly be a sensible use case?
13:31andyfIt is unlikely to snag you in practice, I expect.
13:31gfredericksmmeix_: probably not
13:32justin_smithmmeix_: when using a map as a dispatch table and handling a nil input
13:32justin_smiththough I guess you would usually want nil to do the same thing as not-found
13:32mmeix_aha!
13:33gfredericksjustin_smith: it could be the difference between not supplying an option vs accidentally supplying a nonexistent one
13:33justin_smithgfredericks: sure
13:33justin_smithor if the dispatch table was supposed to emulate cons somehow, and nil is thus a viable alternative
13:34mmeix_I guess, it would be better to avoid such a situation anyhow, right?
13:34justin_smith,(cons 1 nil)
13:34clojurebot(1)
13:34justin_smithnil is explicitly provided and has a specific meaning here
13:35mmeix_as: "start consing from here"?
13:36justin_smithmmeix_: yeah, basically hysterical raisins from historical lisps, where the sentinal value in a linked list meaning "end" was nil
13:36mj_langfordlol at "hysterical raisins"
13:37andyfvisualize whirled peas
13:37mmeix_nil as in: nothing 'more' to get here?
13:37mmeix_ok
13:38mmeix_thanks for context
13:38danielglauserAny pointers to getting started with clojurescript and a good environment with a repl? Seems to be a rapidly moving target, the last recommendation I saw was austin.
13:40mmeix_(I'm collecting some of my questions with answers from here, so I can laugh about them in a month or two ... :-)
13:41bbloomdanielglauser: weasel is much easier to use and more reliable than austin
13:45sritchiebbloom: fully agree
13:48danielglauserThanks gents, I'll check it out
13:55mmeix_last question for today: would you recommend reading through the clore.core source to deepen understanding (besides books and REPLing of course)?
13:55sritchiedanielglauser: om-bootstrap’s doc site is all set up with a weasel repl, https://github.com/racehub/om-bootstrap/blob/develop/project.clj
13:55sritchieif you want to check that out
13:55sritchiemmeix_: it can be nice to try to recreate functions from core,
13:56sritchiemmeix_: then look at core to check your work
13:56mmeix_ah, that's better
13:56sritchiemmeix_: many of the https://www.4clojure.com/ problems are re-impls of core
13:56sritchieI’d suggest working through 4clojure, then reading source later for fun
13:56justin_smithmmeix_: also, clojure.core is not normal clojure - it's optimized clojure
13:56justin_smithmmeix_: if you are writing for readability the way core does it is not always best
13:57mmeix_yes, I'm working 4clojure, right now beginning the Medium cases...
13:57mmeix_justin_smith understood
13:57sritchiemmeix_: all of the ones marked “core-functions”: https://www.4clojure.com/problems
13:57sritchiemmeix_: you can check in core.clj later for fun
13:58mmeix_great advice, thanks
14:00mmeix_so for example "fn [x] ...fn [x y] ... fn [x y z] ... fn [x & more] ..." in core are such otimized cases, if I understand correctly
14:01bbloommmeix_: yes, but they are *micro* optimizations that you probably shouldn't ever do unless you really know you need to
14:01bbloomremember: core is on *everyone's* hot path
14:02mmeix_yeah, only asked to understand, not to imitate
14:04mmeix_(thanks for today, nightfall here, I'll get me a glass of wine and tune my harpsichord :-)
14:05mmeix_(I like the fact, that Rich Hickey started out as a musician :-)
14:05mmeix_bye
14:11danielglausersritchie: Thanks for the pointer. Sent you a PR for a minor spelling issue in the README.
14:11sritchienice, thanks!
14:16donbonifaciois it possible to non blocking IO with compojure?
14:25hoangelosI need some help. I have a file that I want to compress on the fly. So that I can pass an input stream to another function that expects an input stream.
14:27hoangelosI took a look at this: https://github.com/itang/clj-lzma/blob/master/src/clj_lzma/core.clj but am wanting a funciton that you give it a file. And what's returned is an inputstream of the encrypted file.
14:32justin_smithhoangelos: you can use clojure.java.io/input-stream to get an input-stream from a file
14:32justin_smith((comp io/input-stream io/file) file-name)
14:33justin_smithhoangelos: in fact, that code is already using io/input-stream, so you should just be able to pass it a java.io.File and it will do the right thing
14:34hoangelosBut the io/copy doesn't that return an outputstream and not an input stream?
14:35justin_smithit puts the contents of the input onto the output, and you can use io/inputstream to get an input from that output
14:36justin_smithio/input-stream that is
14:39hoangelosso you are saying like (io/input-stream (io/copy in out))
14:39justin_smithdoes io/copy return the out argument? I forget
14:40justin_smithbut yeah, something like that
14:40justin_smith(I use io/copy for its side effects, so I end up ignoring the return value, since I already have a handle to its output)
14:41justin_smithhoangelos: I just noticed in the docs - it returns nil actually
14:41justin_smith(doc clojure.java.io/copy)
14:41clojurebot"([input output & opts]); Copies input to output. Returns nil or throws IOException. Input may be an InputStream, Reader, File, byte[], or String. Output may be an OutputStream, Writer, or File. Options are key/value pairs and may be one of :buffer-size buffer size to use, default is 1024. :encoding encoding to use if converting between byte and char streams. Does not close any streams except those it opens itself (on
14:43scriptdevilHi, I do not know the name of the following operation, but I want to do it. I want to inline a vector into another. For instance, [1 2 3 (fun-rets-list)], but I want the returned vector to be inlined within the vector
14:43justin_smithscriptdevil: use into
14:44justin_smith,(into [1 2 3] ((fn [] (list 4 5 6))))
14:44clojurebot[1 2 3 4 5 ...]
14:44justin_smiththanks for printing "..." instead of 6 clojurebot, that sure did save space!
14:44scriptdevilBut this is in the middle of another vector...
14:44justin_smithdon't do that
14:44justin_smithit isn't a thing
14:45justin_smithscriptdevil: to be less glib - there is no reader that does that, you could do it in a macro but there is really no point in using a macro for this
14:45scriptdevilI am using hiccup here. I am returning a partial set of hiccup elements and want to put it inside a div without having to create another superfluous div.
14:45scriptdeviljustin_smith: Oh. Ok. Thanks.
14:45justin_smithhiccup will use the vector returned by into just fine
14:46hoangelossomething must be wrong, because I keep getting OOM errors with teh Java heap size.
14:46scriptdeviljustin_smith: Wouldn't [:div#footer [[:p foo] [:p bar]]] be a problem?
14:46justin_smithhoangelos: clojuer uses a LOT of heap, you should up your limit probably
14:47scriptdeviljustin_smith: [[:p foo] [:p bar]] are returned by my function.
14:47scriptdevils/are/is
14:47hoangelosjustin_smith: even when I set to over 1000M it gives me OOM
14:47justin_smithscriptdevil: then return the right thing instead
14:47scriptdeviljustin_smith: what do you suggest I return?
14:47justin_smithhoangelos: I often have to go up to 10g depending on what I am doing, but you can use jvisualvm to see where the RAM is being used up
14:48hoangelosour app has never required more heap that 60m
14:48scriptdeviljustin_smith: I genuinely am interested in understanding what to do here. I have a funciton that computes a vector of paragraphs. I want to insert it into a div that is in hiccup. How do I force it in?
14:49scriptdevilNot being lazy here.
14:49justin_smithscriptdevil: run a function on the div
14:50justin_smithscriptdevil: hiccup just uses normal clojure data structures, so you can use standard functions (like into as I showed above) to build your values
14:50scriptdeviljustin_smith: Ok. Thanks.
14:51justin_smithhoangelos: profiling is the answer I think. Yeah, going from megs to gigs of heap usage is a bad sign.
14:51scriptdevilI just realized that I could use ~@ if I returned a list instead of a vector. That looks interesting. Thanks.
14:51justin_smithscriptdevil: with a syntax-quote, yeah I guess so
14:52justin_smithsyntax-quote with ~@ is just a sugar for concat
14:52scriptdevilThanks, justin_smith. This was useful.
14:55eggheadis there some version of `get-in` that will work with lazy seqs?
14:56justin_smithegghead: no, because 'get' does not work on lazy-seqs
14:56justin_smithbut you can use -> very similarly, with nth
14:56egghead,(get-in {:nums (range 3)} [:nums 0])
14:56clojurebotnil
14:56eggheadis the sort of thing I want to do :/
14:57justin_smith,(-> {:a {:b (range)}} :a :b (nth 0))
14:57clojurebot0
14:57eggheadhm, I guess I could just write a function that is kind of like get-in but does 'the right thing' ?
14:57eggheadi.e. get vs nth
14:57justin_smithegghead: or a macro wrapping -> would be another option
14:58justin_smith(dec macro-contagion)
14:58lazybot⇒ -1
15:05arrdemlazybot: ping
15:05lazybotarrdem: Ping completed in 0 seconds.
15:18arrdemanyone aware of an LR/LALR parser compiler for Clojure? I know we have a bunch of RDPs and monadic parsers but I'm specifically interested in the (LA)?LR table generation and linear time guarantee.
15:22justin_smitharrdem: I assume you checked out the top google hits - parsnip doesn't specify lr/lalr but do specify that it is deterministic, scannerless, and incremental
15:22justin_smithhttps://github.com/cgrand/parsnip/
15:25arrdemI saw it last night... didn't dig into it. looking now it's a table driven RDP interpreter.. identical to what I whipped up last night
15:26arrdemunless I'm missing something in the implementation of alt
15:26mj_langfordhttps://github.com/Engelberg/instaparse ?
15:26mj_langfordIt does all context free grammars, so LR/LALR is in that set right?
15:26mj_langford(been a few years)
15:28arrdemmj_langford: sure, I've used instaparse before I'm just specifically interested in the LR/LALR table implementation rather than the instaparse monadic parser combinator.
15:28mj_langfordAhh, sorry!
15:28arrdemno worries
16:29mi6x3mhey, could someone explain this "For Symbols, syntax-quote resolves the symbol in the current context"
16:29arrdemwhat's to explain?
16:29mi6x3mI am wondering where I should write clojure.core/conj in my macro
16:29mi6x3mor just "conj" when I syntax quote
16:29arrdemjust conj
16:29arrdemit'll resolve to clojure.core/conj if it's referred
16:30mi6x3mok, so it will be resolved at compile time
16:30arrdemeh... at macro time IIRC
16:30mi6x3myeah
17:00amalloyarrdem: at reader time
17:00arrdemamalloy: backquote wrapped symbols are reader-resolved?!
17:01amalloy,`conj
17:01arrdem&'`foo
17:01lazybot⇒ (quote clojure.core/foo)
17:01clojurebotclojure.core/conj
17:01amalloyarrdem: everything ` does is at read time
17:10KeithPMAny advice on how to survive being forced to learn some python for a coursera course?
17:10TravisDLearn python, I suppose
17:11Wild_CatKeithPM: Python's a cool language, and it's omnipresent. Learning it is a good opportunity.
17:12mdeboardClojure and Python share important similarities after all
17:12KeithPMThanks. I am finding it rather attractive, but I have committed to immutability so it is a bit painful when I have to alter numpy arrays, etc. I t looks useful.
17:13KeithPMThanks, I will go forward bravely with your encouragement :)
17:13mdeboardImmutability is cheap and easy in Python. It's just not the default.
17:13KeithPMOK mdeboard. I will seek out that style
17:14TravisDAlso, if you’re doing numerical stuff, I think you probably want to have simple datastructures for representing vectors, arrays, etc
17:14TravisDand that makes them expensive to work with immutably
17:14mdeboardPython also supports functional programming paradigms & style quite well. https://docs.python.org/2/library/functools.html https://docs.python.org/2/library/itertools.html
17:15justin_smithTravisD: and depending on how an array is used, the mutation of the array doesn't need to mean mutable program semantics (if there is only one scope with access to the array at a given time, with clear handoffs of "ownership")
17:15KeithPMThanks, I would like to take a functional approach. Language looks powerful, I miss map, reduce, filter, etc. I will be hunting them down
17:16mdeboardand of course out of the box it has first-class functions
17:16mdeboardKeithPM: map/reduce/filter are non-idiomatic in python. Generators and comprehensions are what's used for such things
17:16KeithPMsweet. I am feeling better already
17:17KeithPMI am seeing something called broadcasting looks a bit like mapping to me
17:17TravisDjustin_smith: Yeah, right :) Mostly an implementation detail of a few functions. You can probably get away with exposing only a pure interface most of the time
17:17mdeboardKeithPM: I think that's a NumPy specific concept
17:18mdeboardabout which I know really nothing :D
17:18KeithPMYes it appears to be an adarray feature
17:18TravisDKeithPM: You can gain major performance benefits by letting numpy do things for you, instead of implementing it yourself in python. Broadcating is a way to describe certain operations for numpy to cary out
17:19TravisDthe major use case is something like adding a vector to every row of a matrix
17:19KeithPMOh yes. That is the plan. We're using numpy and scipy to do FFTs and other sound analysis
17:20TravisDyou can also use it to apply functions to matrices component-wise, IIRC
17:20TravisDwhich is something that crops up surprisingly often
17:21KeithPMThanks. I will go bravely, it looks pretty attractive so far.
17:21mdeboardin general it's straightforward to structure python code exactly as you would clojure code
17:21KeithPMCool
17:22mdeboard(Clojure wins in terms of immutability-by-default though for sure)
17:22TravisDmdeboard: are there no performance overheads to writing clojure-style code in python?
17:22KeithPMThat is MY use case for clojure. Very powerful
17:22justin_smithmdeboard: as long as you don't do anything with threads :)
17:22TravisDI think function evaluation in python is like, ridiculously expensive
17:22arrdemTravisD: there are performance overheads to writing Clojure style code in Clojure :D
17:23TravisDtrue :)
17:23mdeboardTravisD: You might be thinking about function lookup or something? I'm not sure wha tyou mean
17:23TravisDFor numerical code these things can be serious problems, though
17:23mdeboardThen again, I'm not writing high performance code in python
17:23borkdudein transducers, an iteration is non realized transformation with data supplied?
17:24TravisDmdeboard: Nothing specific. If you have a tight loop that calls a simple function it is typically many times slower than if you inline the function in the loop
17:24mdeboardThen again again, I highly doubt for a given problem the bottleneck would even be the language
17:25TravisDmdeboard: These things can make a pretty big difference to the running time, like between 2 and 30 times difference. That’s the difference between a day and a month
17:25justin_smithmdeboard: clojure / jvm can do some smart things to inline and optimize function calls if you hint the args and scope things right
17:25justin_smithmdeboard: the semantics of python make these optimizations illegal
17:25mdeboardSure
17:25mdeboardThat's the JIT right? Warming etc.?
17:25justin_smithso in clojure we can promise "x is always a primitive int" and the compiler can act on that
17:25justin_smithin python, there is no such concept - the type must be checked
17:26nathan7PyPy gets quite far
17:26nathan7but it's a pretty damn advanced JIT
17:26TravisDIs the JVM responsible for the optimizations that happen when using clojure?
17:26TravisDOr does it all happen at compile time?
17:26nathan7a mixture of the two
17:27nathan7Clojure compiler produces bytecode and performs some optimisations at compile time, JVM optimises that at runtime using runtime information
17:27TravisDcool
17:27justin_smithhttps://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/
17:28justin_smiththe funny thing about that article, is clojure has many of the features that he claims make optimizing python hard, but has them in ways that are designed to be optimizable
17:30mdeboardAll I actually meant was, there's no reason to use Python like a generic OOP language in terms of how you structure your code. Small, referentially transparent functions etc.
17:32mdeboardbut of course if you're using Python (or Clojure) performance isn't your primary concern anyway
17:34mdeboard(runtime performance)
17:36TravisDYeah, not your primary concern. But still nice if you can make things fast, and if that means small deviations from the preferred style then it might be worth it
17:39mdeboardTrue. Always a balancing act though, I put a lot of emphasis on long-term maintainability, and a functional style helps with that a lot. In the web world, server-side application runtime prob isn't going to be the bottleneck anyway. Scientific computing is a whole other thing I've no experience to
17:41mdeboard(I want to also point out I greatly prefer Clojure to Python for many, many, many reasons for almost every possible application)
17:42mdeboardMy loyalty cannot be question, Komisar!
17:43TravisDhehe yeah, I’ve never written a single piece of production code so I have no perspective on that :)
17:43TravisDhopefully that will change soon
17:50justin_smithmdeboard: "server-side application runtime prob isn't going to be the bottleneck anyway" the folks who pay me to write clojure switched from ruby because it was actually. Clojure was a massive reduction in their hardware costs, and maintinance and setup time for deployed systems, and this is all rooted in Clojure's relative performance.
17:51mdeboardjustin_smith: cool
17:51mdeboardwhat was the app doing that ruby itself slowed it down?
17:51justin_smithmdeboard: serving pages
17:51mdeboardWell, right, but ...
17:52justin_smithruby has memory leaks, which leads to a need to have a collection of servers that get killed when their space usage gets too high
17:52mdeboardah
17:52mdeboardweird
17:52justin_smithwhich leads to a need for more hardware to serve the same number of requests
17:52mdeboardcrazy, never heard that before. never used ruby at all
17:52mdeboardexcept in vagrantfile
17:53justin_smithalso, you can always expand to more servers, but how many requests each server can handle is still a linear factor in your backend expenses
17:54justin_smithin practice they went from multiple servers for one site, to multiple sites on one server
17:55mdeboardsounds awful
17:55mdeboardI mean, the former
17:55justin_smithyeah
17:55mdeboardHow much of that is a function of web server choice and the ruby adapter for it?
17:56justin_smithmdeboard: both clojure and ruby are providing their own server (http-kit / mongrel)
17:57mdeboardmongrel is the zed shaw thing right
17:57justin_smithwell, unicorn managing multiple mongrels, but that's the gist
17:57mdeboardOh god
17:57justin_smithyeah
17:57mdeboardYeah a web server written in ruby (or python) sounds like the worst idea
17:57mdeboardever
17:57AimHereI wrote a rudimentary webserver in perl once
17:58justin_smithunicorn is a reverse proxy for multiple instances of a ruby web server, written in ruby :)
17:58mdeboardoof
17:58mdeboardnginx is where it's at. Modern Apache ain't bad either
17:58mdeboardright tool for the job etc.
17:58llasramjustin_smith: I don't believe that's strictly true... Unicorn is a multiprocess Rack Web server
17:58justin_smithllasram: OK
17:58llasramEach Unicorn process directly serves an instance of the application
17:59mdeboardrack is the ruby equiv of wsgi no?
17:59llasramYep
17:59mdeboardgateway interface
17:59llasramWe've still got a few Ruby apps, all using Unicorn and fronted by Apache
17:59justin_smithllasram: yeah, you are right of course, I misremembered the details
17:59mdeboardunicorn sounds like uwsgi
18:00llasramrack :: wsgi :: ring
18:00llasramunicorn :: gunicorn :: ring-jetty-adapter+jetty
18:00mdeboardnginx + uwsgi is speedy and lightweight
18:00mdeboardahso
18:01llasram(Well, except that there's no multiprocess JVM Web server, so the analogy is imperfect.)
18:02justin_smithllasram: immutant/jboss could be, depending on setup, right?
18:02llasramjustin_smith: Kind of, but not in the same way, where a parent process manages a herd of worker children
18:02llasramThat kind of model just doesn't make sense for something on the JVM afaik
18:03justin_smithllasram: I think it could work, but what would be the point when your vm does threads well already?
18:03llasramExactly
18:03justin_smithwhich gives much more flexibility
18:04justin_smithwell, does threads well + does not get into shit-tastic states where the best thing is to kill it with a -9 flag
18:04llasramThreads + some of the best mainstream GC
18:04justin_smith:)
18:04llasramheh
18:17mi6x3mhow fast is assoc with persistent vectors?
18:18justin_smithmi6x3m: worst case it's log time iirc
18:18mi6x3mI see
18:19justin_smithmi6x3m: probably answers all the questions you might have, and then some http://hypirion.com/musings/understanding-persistent-vector-pt-1
18:19justin_smithmi6x3m: also, criterium is really good for micro-benchmarking, but profiling is king!
18:20justin_smiththe steps should be: make it work, notice something is too slow, benchmark, fix the most egregious issue you find in the benchmark
18:23bbloommi6x3m: the correct answer is "very fast"
18:23mi6x3myes, I believe so :)
18:24bbloom,(def a (object-array 100000))
18:24clojurebot#'sandbox/a
18:24bbloom,(def v (vec (repeat 100000 nil)))
18:24clojurebot#'sandbox/v
18:25bbloom,(time (dotimes [_ 10000] (aset a 50000 123)))
18:25clojurebot"Elapsed time: 558.473421 msecs"\n
18:25bbloom,(time (dotimes [_ 10000] (aset v 50000 123)))
18:25clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: aset>
18:25bbloom,(time (dotimes [_ 10000] (assoc v 50000 123))); rather
18:25clojurebot"Elapsed time: 16.364501 msecs"\n
18:25bbloomboom. fast.
18:25bbloomi'm sure there's some reflection problem in there tho, heh
18:25bbloom,(time (dotimes [_ 10000] (aset ^objects a 50000 123)))
18:25Bronsabbloom: definitely
18:25clojurebot"Elapsed time: 326.54297 msecs"\n
18:25bbloomBronsa: where is it?
18:25justin_smithfunny how much faster the assoc is
18:26justin_smithI wonder if that's because the compiler knows the result of the assoc can't be accessed via static analysis?
18:26Bronsabbloom: the reflector is dumb and it tries to use 123 as unboxed
18:27bbloom,(time (dotimes [_ 10000] (aset ^objects a 50000 (long 123))))
18:27clojurebot"Elapsed time: 306.559714 msecs"\n
18:27bbloom,(time (dotimes [_ 10000] (aset ^objects a 50000 (Long. 123))))
18:27clojurebot"Elapsed time: 6.773635 msecs"\n
18:27bbloomah, there we go
18:27bbloomwow
18:27Bronsayep
18:27bbloomthat makes a lot more sense
18:27justin_smithdifferences like that kind of blow my mind
18:27Bronsa,(def b 123)
18:27clojurebot#'sandbox/b
18:27bbloommi6x3m: in short, other things will be slow long before vectors are slow :-)
18:27Bronsa ,(time (dotimes [_ 10000] (aset ^objects a 50000 b)))
18:27clojurebot"Elapsed time: 1.718982 msecs"\n
18:27Bronsabbloom: even faster^
18:28bbloomBronsa: but the vector version has to do the boxing each iteration too, now it's not fair
18:28Bronsabbloom: not sure actually
18:28bbloom,(time (dotimes [_ 10000] (assoc v 50000 b)))
18:28clojurebot"Elapsed time: 12.847707 msecs"\n
18:28bbloomthere you go
18:28bbloom,(time (dotimes [_ 10000] (assoc v 50000 b)))
18:28clojurebot"Elapsed time: 12.511901 msecs"\n
18:28bbloom,(time (dotimes [_ 10000] (assoc v 50000 123)))
18:28clojurebot"Elapsed time: 12.752028 msecs"\n
18:29bbloom,(time (dotimes [_ 10000] (assoc v 50000 123)))
18:29clojurebot"Elapsed time: 12.50338 msecs"\n
18:29bbloomhm
18:29Bronsabbloom: I believe it will just create a boxed 123 in the static initializer
18:29Bronsaand use that
18:29bbloomi guess the compiler lifts it?
18:29Bronsayes
18:29bbloomgotcha
18:29bbloomooooh computers, you so crazy
18:29Bronsabbloom: the fact that it doesn't do it for aset -- I would consider that a reflector bug
18:30Bronsait should be able to figure out that Object[],int,Object[] is the only arity that makes sense
18:30bbloomBronsa: this may be a good question to ask you....
18:30Bronsaand that 123 can be boxed
18:30BronsaObject[],int,Object rather
18:30bbloomBronsa: does the compiler correctly compile primitive invocations for interop method calls?
18:30bbloomespecially asking with respect to things like bytes or shorts (ie not doubles or longs)
18:31Bronsait should, yeah
18:31bbloomyeah, i assumed it would, but i was seeing some odd profiling data
18:31Bronsabut I have to say, the reflector method matching stuff has some weird behaviours
18:31bbloomcouldn't tell if boxing was or wasnt there, and if it was there, whether it was being attributed to caller or callee
18:31Bronsait might pick a method randomly when multiple match
18:31Bronsaor fail to pick one when there's an obvious valid one like in this case
18:32BronsaI gave up trying to fix it and just rewrote the logic from scratch for t.a.jvm
18:32bbloomheh
18:32justin_smithBronsa: sounds like a terrible followup to method_missing, method_roulette
18:32BronsaI won't claim my implementation is edge-cases free but it should work better in some cases
18:32clojurebotOk.
18:33bbloomjustin_smith: i'm still bitter about this: https://github.com/marcel/aws-s3/pull/14
18:34bbloomBronsa: you know anything about calls to "native" methods?
18:34bbloomie are they special/different in anyway?
18:36justin_smithbbloom: that's terrible
18:38bbloomjustin_smith: you can say that again
18:39justin_smithmakes me think they could make a followup to "here comes honey boo boo" about web devs who make bad architectural decisions
18:44Bronsabbloom: native in what sense?
18:47mi6x3mI'd say, I really wish recur and try would play nicer together
18:47mi6x3mI understand the implications, no flame
18:47danneui've been porting my Om app to Reagent to get a taste of both worlds. but so far i'm having trouble grasping what actually triggers re-rendering in Reagent. twice today i found myself doing this to force re-rendering after reagent.core/atom updates: `(swap! local-state ...) @local-state`.
18:48justin_smithmi6x3m: put the entire body you are recurring to inside the try if the recur needs to be inside the try
18:49bbloomBronsa: like the java `native` keyword
18:49mi6x3mjustin_smith: nah, this is not the usual use case, I am writing a somewhat complex macro
18:49mi6x3mdoing ... stuff
18:49Bronsabbloom: ah, I have no idea about that
18:49bbloomBronsa: i was seeing some weirdness that looked sorta like boxing in the perf profile when calling a native function
18:50bbloomBronsa: i didn't dig in to the generated bytecode, but i was assuming that it would be no different from a normal method call from the persepctive of the caller
18:51Bronsabbloom: I haven't seen any special handling of native methods anywhere so I don't think there should be any difference
18:51bbloomBronsa: k, that's basically what i expected. thanks
18:51justin_smithmi6x3m: care to describe what the actual issue is then?
18:52mi6x3mjustin_smith: Because I fail to locate license information for https://gist.github.com/377278/936b164c116cb6dd40b1315e4ecbd8f5bfcdc024 I am writing my own version. Also, the gist version has an unfixed bug
18:52mi6x3mbut my solution is a loop / recur loop
18:53justin_smithmi6x3m: which part ends up looping?
18:54mi6x3mjustin_smith: well, you have to check every expression in the bindings vector individually and build up the vector step by step
18:54justin_smithoh wait, instead of try-let it's try-loop then?
18:54mi6x3mno
18:54mi6x3msuppose you have (try-let [x 1 y 2 z (throw blabla....
18:54mi6x3min your catch clause you want x = 1 and y = 2
18:54mi6x3mto perform some clean-up
18:55mi6x3mthe gist macro does that by unrolling a large number of bindings
18:55mi6x3mI do it by using a simple vector and a loop / recur to build up the binding value
18:55mi6x3mwill upload the first version in a second
18:56justin_smithmi6x3m: I wonder if it would be simpler with local vars (but then you would take on the issue of potentially not-yet-bound vars being referenced in the catch block)
18:58justin_smithoh, and they require using deref explicitly, so you may as well use delay or promise (which have the same deref issue)
18:58mi6x3mjustin_smith: nah, you don't need all this
19:10mi6x3mif a part of a lazy seq throws an exception
19:10mi6x3mwhy is it thrown every other time?
19:28ghadisha`that thing of when you start by trying to "improve" c.c/range but end up modifying the compiler too
19:32danneuif anybody is involved with cljs bug tracking, can you make an issue that points out that (js->clj x {:keywordize-keys false}) should be (js->clj x :keywordize-keys false)? https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L8376
20:21gfredericks,(def cool-nums (map #(/ 42 %) [3 2 1 0]))
20:21clojurebot#'sandbox/cool-nums
20:21gfredericks,(last cool-nums)
20:21clojurebot#<ArithmeticException java.lang.ArithmeticException: Divide by zero>
20:21gfredericks,(last cool-nums)
20:21clojurebotnil
20:21gfredericksmi6x3m: you were asking about that? ^
20:22gfredericksI remember looking at that in LazySeq.java and there didn't seem to be any way around that without extra checks that would slow things down
20:23andrewhrmy mind just blown with this bot evaling clojure
20:23andrewhr:o)
22:31mateusHi, I'm working on a problem that involves a graph. I've chosen to represent the graph as a map, where the keys are values, mapped to a set of its neighbors.
22:32mateusSo, for example, a simple map would be {:1 #{:3 :2}, :2 #{:3}, :3 #{:1 :2}}
22:33mateusSo, let's say I have a node that has these neighbors: #{:60 :89 :37 :59 :40 :18 :11 :24 :10 :73 :61 :66 :30 :4 :57 :98 :1 :50 :22 :47 :20 :46 :69 :41 :15 :3 :54 :80 :34}
22:34mateus"(map #(get graph %) neighbors) (#{:88 :27 :77 :75 :73 :13 :38 :57 :85 :35 :81 :25 :32 :5} #{:88 :65 :52 :12 :56 :70 :13 :66 :53 :43 :57 :26 :79 :44 :55 :8 :62 :74 :20 :94 :90 :6 :54 :68} #{:88 :45 :31 :65 :40 :12 :75 :13 :0 :58 :38 :44 :35 :78 :20 :86 :17 :46 :28 :15 :33} #{:88 :45 :24 :76 :75 :23 :66 :26 :95 :81 :55 :74 :20 :99 :51 :84} #{:88 :37 :64 :23 :26 :16 :81 :78 :8 :86 :5 :33 :51 :29} #{:88 :64 :12 :24 :10 :56 :0 :66 :79 :9
22:34mateusThe map would return a lazyseq of sets.
22:34mateusHow do I merge these sets?
22:51djamesI'm reading https://netbeans.org/bugzilla/show_bug.cgi?id=242171 but not sure where to put META-INF/resources for a leiningen project
22:52djamesperhaps simply PROJECT-ROOT/resources?
23:03Guest55164+
23:03TravisDAw, I meant to tell mateus that he could use reduce
23:07hadronzo`Rich discusses transducers as taking a single input stream and producing a single output stream. Looking at the definition though, it seems like one could also construct mult-input transducers.
23:10hadronzo`nevermind, it wouldn't work