#clojure log - Oct 25 2014

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

0:26 ddellacosta: justin_smith: I guess it was an hour ago you mentioned it, but been using schema a lot lately and really liking it

0:26 will be really happy if they provide some tools to dump out the (schema) type annotations into docs

0:26 justin_smith: I am literally putting it into the codebase this very moment to help track down errors I get on certain inputs

0:26 ddellacosta: that would be an awesome feature for marginalia

0:26 ddellacosta: nice

0:27 justin_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

0:27 doing haskell has spoiled me there, that is a really nice thing about haskell libs and docs

0:28 justin_smith: ddellacosta: 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

0:29 ddellacosta: yeah, I can imagine that was a big shock!

0:29 justin_smith: ddellacosta: 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

0:30 ddellacosta: justin_smith: oh yeah, along those lines, been trying to integrate test.check lately too, but still at early stages with that

0:30 justin_smith: so 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

0:30 ddellacosta: oh man, I know that pattern *very* well

0:30 justin_smith: kind of tdd inside out

0:30 oh, I should have guessed it was a common thing :)

0:30 technomancy: marginalia-mode.el

0:30 please someone write this

0:31 justin_smith: is there a name for it? tdrc - test driven reading comprehension?

0:31 technomancy: that would rock so hard

0:31 ddellacosta: yeah, kind of "big ball of mud de-complecting-DD" ;-)

0:31 justin_smith: technomancy: 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

0:31 thanks

0:32 prismatic/schema even has its own wrapper for defmulti

0:32 ddellacosta: oh didn't know that, neat

0:32 technomancy: I knew being a cagey old hermit would pay off

0:32 cool

0:32 ddellacosta: justin_smith: also check out plumbing if you haven't--got some stuff above and beyond schema that makes it useful

0:33 justin_smith: you can specify schema for method dispatch, or for the args

0:33 ddellacosta: cool, I will add it to the list

0:33 (inc the clojure community)

0:33 lazybot: ⇒ 1

0:36 ddellacosta: :-)

0:37 technomancy: 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. :-(

0:37 technomancy: justin_smith: had you been doing ocaml professionally before, or just funsies?

0:37 justin_smith: technomancy: just funsies, but serious hours of funsies

0:37 technomancy: cool, cool

0:37 justin_smith: technomancy: the clojure job was my first real tech job of any sort

0:38 ddellacosta: you cats see the comparison btw OCaml and SML that popped up recently?

0:38 technomancy: I guess "funsies" sounds dismissive

0:38 justin_smith: beyond being payed to stare at some php for a couple weeks at a time

0:38 technomancy: didn't intend that

0:38 justin_smith: technomancy: it's all good

0:38 technomancy: ddellacosta: definitely. hope to get a release out soon, so get a bug report in soon

0:38 justin_smith: ddellacosta: no, whats the gist?

0:38 ddellacosta: technomancy: yeah, I'll start with an issue...I'm not sure it's a bug our our own confusion here

0:38 technomancy: course it's been "just around the corner" for a while now

0:39 while I spend my nights sanding and doing circuit design

0:40 ddellacosta: justin_smith: oh, was just comparing syntax, thought it was an interesting comparison. Trying to find it now...

0:40 here it is: https://news.ycombinator.com/item?id=8497214

0:40 and if you want to avoid HN entirely, the direct link: http://adam.chlipala.net/mlcomp/

0:41 technomancy: justin_smith: you did find something after that caribou gig fell over, right?

0:41 ddellacosta: since 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...)

0:42 justin_smith: technomancy: 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

0:42 and actually apply etc.

0:42 technomancy: ah, gotcha. good luck.

0:43 ddellacosta: justin_smith: if you have some devops experience and are in North America, we are looking for devops/clojure dev 50/50

0:43 justin_smith: technomancy: 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

0:43 technomancy: good on ya

0:43 justin_smith: ddellacosta: yeah, I am at home on the cli with a linux box, can set up servers etc.

0:43 technomancy: some folks start drawing a paycheck and it all goes to their head

0:44 justin_smith: ddellacosta: feel free to msg me more info if you like

0:57 danneu: [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]?

0:59 justin_smith: danneu: that makes me think the protocol definition got re-evaluated but an instance of the old version of the protocol is still around

1:00 danneu: or at least that happens in clj, dunno about cljs

1:01 danneu: oh wait, TIL that you pass {dropping,sliding}-buffer to the `chan` function

1:05 arrdem: with test.check is there a good way to express special equality relationships between generated values?

1:05 say I want to ensure that behavior B exhibits only if two generators are equal and otherwise behavior A occurs

1:06 justin_smith: danneu: ahh, reading fail on my part, I saw a-dropping-buffer and assumed chan-with-a-dropping-buffer

1:06 arrdem: I 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

1:07 reiddraper: arrdem: nothing beyond just writing the if expression in your property

1:07 arrdem: reiddraper: okay. that's what I expected. thanks.

1:08 reiddraper: arrdem: and I think it'd be fine to have two properties, as you describe

1:08 keeps each one nice and simple

1:08 arrdem: reiddraper: 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

1:10 reiddraper: arrdem: 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

1:11 arrdem: reiddraper: honestly a pair generator where a and b are guranteed never to be equal would solve this for me...

1:11 * arrdem reads the fine manual

1:12 akhudek: I wish clojure.data.xml had an option to preserve whitespace

1:12 reiddraper: Arrdem: 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

1:13 Or what if you accidentally: (gen/distinct-pair (gen/return 0) (gen/return 0))

1:13 arrdem: reiddraper: or you can construct a non-colliding relation between the two values..

1:13 oh hice

1:13 *nice

1:14 reiddraper: arrdem: that function doesn't exist, I'm just illustrating a pair that could never be unique

1:14 arrdem: reiddraper: generally sure. in the case at hand I can define such pairs reasonably.

1:15 reiddraper: arrdem: distinct-pair would be easy to write:

1:15 arrdem: (defn distinct-pair [a b] (gen/such-that (fn [[x z]] (not= x z)) (gen/tuple a b))

1:17 arrdem: just mind the such-that caveat: https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.clj#L268-L272

1:19 arrdem: reiddraper: I just want a distinct (char . char) pair. p >> 10% here :D

1:20 reiddraper: arrdem: i'd expect that with (gen/tuple gen/char gen/char)

1:20 arrdem: &(* 1/255 1/255)

1:20 lazybot: ⇒ 1/65025

1:20 reiddraper: (if you're looking with gen/sample, make sure you sample enough values: gen/sample my-gen 100) or so

1:21 arrdem: very tempted to add for-all -> \forall rewriting to my .emacs.d :P

1:22 reiddraper: :)

1:22 gen/char too should be fixed to support the full unicode range, but, it doesn't at the moment :|

1:22 as you mentioned, just 0-255 at the moment

1:23 arrdem: well.. there's the clj-dev chatter about working with unicode chars..

1:23 reiddraper: if my stats are correct, you'll expect to see the same pair 1/256 times

1:24 so, fits your 10% just fine

1:26 anyway, past my bedtime

1:27 arrdem: g'night

1:27 thanks

1:27 (inc reiddraper)

1:27 lazybot: ⇒ 4

1:31 justin_smith: (inc reiddraper)

1:31 lazybot: ⇒ 5

1:31 clojangles: heya 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:

1:31 (ns joy.argh (:require [clojure.set :rename {intersection isxn}]))

1:32 but I can't get at isxn, any hints or doc pages you recommend I read?

1:33 justin_smith: clojangles: clojure.set/isxn

1:33 clojangles: require does not do any remapping, unless you add the :as or :refer keys

1:33 (doc require)

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

1:33 justin_smith: it's a big doc string, better to read it online

1:34 $source require

1:34 lazybot: require is http://is.gd/cHBGH6

1:34 clojangles: ah nice, thank you justin_smith. I'll dig in

1:34 justin_smith: clojangles: in general, the clojure.repl/doc and clojure.repl/source functions are very helpful

1:35 most clojure repls should make them immediately available, but you are learning right now how to require them if not :)

1:36 clojangles: I'm using leiningen, so I'm good to go there :) I love that the source function is a thing

1:36 justin_smith: clojangles: 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

1:37 clojangles: yeah, it makes exploring the language much easier

1:37 though 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)

1:40 clojangles: justin_smith: I can still use (source n) to browse libraries though for some examples of more idiomatic code?

1:41 justin_smith: clojangles: absolutely

1:42 margenalia makes nice readable output from codebases too (via the lein marg plugin) - I recommend adding it to your :plugins in ~/.lein/profiles.clj

1:43 some good projects for code browsing include flatland/useful and ring (imho), also anything by ztellman tends to be well written

1:43 arrdem: &(not= 1 2 4)

1:43 lazybot: ⇒ true

1:44 arrdem: &(not= 1 2 1)

1:44 lazybot: ⇒ true

1:44 arrdem: hum..

1:44 justin_smith: ,(not= 1 1.0 1/1)

1:44 clojurebot: true

1:45 arrdem: there we go

1:46 clojangles: justin_smith: awesome, adding those to my list of clojure things. thank you again!

1:46 justin_smith: arrdem: were you checking for anything in particular?

1:47 arrdem: justin_smith: https://github.com/oxlang/oxlang/blob/master/test/oxlang/parser_test.clj#L9-L14

3:04 mearnsh: justin_smith: hey i like noise, saw KD recently too :)

3:06 justin_smith: mearnsh: cool. I knew him in the mid '90s when I lived in Chicago, he's been a big influence.

3:07 mearnsh: cool thing - he was using a pedal I helped design

3:07 mearnsh: ah sweet

3:07 justin_smith: (but he did not realize until I pointed it out)

3:08 you've maybe heard of 4ms pedals?

3:08 mearnsh: i don't know much about gear so no

3:10 justin_smith: Dan 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")

3:12 mearnsh: neat

3:16 rritoch: Is 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.

3:18 justin_smith: you mean it would compile faster? there is no reader macro for string concatenation, no

3:18 str uses a StringBuffer internally, can't do much better than that on the jvm

3:19 rritoch: Yeah, that is what I was hoping for, something like $("foo" "bar") or something like that.

3:20 anyhow, thanks. I have about 200 of these long strings to break up so it's going to be another boring day.

3:21 justin_smith: sounds like a good task for an editor macro

3:22 ,*data-readers*

3:22 clojurebot: {}

3:22 justin_smith: that will return all the readers currently in play that beyond the clojure defaults

3:22 you could actually define your own reader btw, with data_readers.clj

3:23 I don't think it would do much in this case except maybe make your code look nicer

3:23 fairly comprehensive docs about the reader, including data_readers.clj is here http://clojure.org/reader

3:25 rritoch: Sounds 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.

3:27 justin_smith: ,default-data-readers ; this is what I was looking for

3:27 clojurebot: {inst #'clojure.instant/read-instant-date, uuid #'clojure.uuid/default-uuid-reader}

3:27 justin_smith: there are not many of them, wow

3:38 dysfun: so 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?

3:42 justin_smith: ,(binding [clojure.core/*data-readers* {'s clojure.core/str}] (read-string "#s [a\n b\n c]")) ;; rritoch

3:42 clojurebot: "[a b c]"

3:42 justin_smith: rritoch: 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 :)

3:45 dysfun: where would you be doing this checking?

3:46 dysfun: 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.

3:47 otherwise, runtime error saying that the java object does not implement interface foo

3:47 dysfun: yes, that's basically the case

3:48 cool. thanks

4:14 rritoch: justin_smith: I see, thanks. What a mess though

4:14 justin_smith: rritoch: the mess is only there so I can demonstrate evaluation inside the thread binding

4:14 rritoch: if you use data_readers.clj as intended, it will work for normal code

4:14 rritoch: You'll see what I mean in a sec

4:15 justin_smith: #s [whatever you want can go here]

4:15 (complete with line breaks, whatever)

4:15 rritoch: ,(binding [clojure.core/*data-readers* {(symbol "s") (fn [& args] (apply str (read-string (apply str args))))}] (read-string "#s( \"a\" \"bc\" \"d\")"))

4:15 clojurebot: "abcd"

4:15 arrdem: justin_smith: note that user defined data readers are _supposed_ to have namespace prefixes

4:15 clearly this can be avoided however

4:15 justin_smith: arrdem: yeah, that was just for simplicity

4:16 rritoch: those symbols do not need to be in double quotes, not that in mine they were not

4:16 it works either way

4:16 *note that

4:17 rritoch: Ok, well I put them in quotes as I'd ultimatly want the source code to be #s("some text" "some text")

4:17 But either way, it seems it will be faster compile time if I stick with the plain (str syntax.

4:18 justin_smith: yeah - you'll want string/join rather than apply str for that

4:18 (otherwise you get "some textsome text")

4:19 rritoch: 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

4:19 rritoch: justin_smith: "some textsome text" is the expected output.

4:19 justin_smith: oh, OK

4:19 rritoch: The point of this would be to break the string into multiple lines, adding \n as needed.

4:20 But the (str "some text" "some text") will probably be faster than the reader macro so I'm better off with that.

4:21 borkdude: why 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

4:21 justin_smith: given that this is only speeding up compilation time, it's a spit in the ocean given how slow clojure builds are

4:22 rritoch: lol

4:23 It's ok with me, I get most my breaks while waiting for builds to complete.

4:24 But I think its mostly from leiningen and network latency

4:25 My builds seem significally faster for apps with most deps on a lan based maven repository

4:25 For my work all repositories are on amazon servers, which aren't always fast

4:26 justin_smith: do you frequently clear your cache or change deps?

4:28 rritoch: Not really, but I'm always building from snapshots

4:36 dysfun: justin_smith: only because it takes so long to boot up the jvm

4:36 and for the most part, autotest has fixed that

4:37 but clojure compilation really doesn't seem particularly slow. I think you'd have to have a lot of code

4:37 that said, starting up the jvm eats all four cores on this because it's not I/O bound (SSD)

4:38 it's one of the things scala developers quite peeved by. it takes ages to compile scala

4:38 the jvm startup on top is just insult to injury

4:40 justin_smith: ,(time (eval '(* 1000 1000)))

4:40 clojurebot: "Elapsed time: 1.095008 msecs"\n1000000

4:41 justin_smith: ,(time (* 1000 1000))

4:41 clojurebot: "Elapsed time: 0.034647 msecs"\n1000000

4:42 dysfun: consider that with autotest running, by the time i've hit save and looked at the terminal, my tests have rerun

4:47 justin_smith: dysfun: 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.

4:47 dysfun: a hello world in java compiles and runs very quickly

4:48 dysfun: yes, but i'd hardly call java development 'interactive' in the way repl development is

4:48 justin_smith: right

4:49 dysfun: consider that to use javafx from java, you have to build a jar to test it

4:49 not that deving javafx is a particularly smooth procedure in clojure either

4:50 justin_smith: but 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.

4:51 dysfun: well 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

4:52 it's utterly "fast enough"

4:52 justin_smith: dysfun: in flycheck, it's basically starting up the compiler from scratch every 15 seconds or so

4:53 dysfun: huh, i don't have flycheck enabled for clojure mode

4:53 justin_smith: right, it doesn't exist, it wouldn't work

4:53 (because some things don't reload very cleanly, and starting from scratch every time would be rediculous)

4:53 dysfun: it would if it used grenchman

4:53 or you did it with cider so you can use nrepl

4:54 yeah, there comes a time when you have to restart your jvm, but it's fairly rare

4:55 justin_smith: there 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.

4:55 dysfun: writing software rarely is

4:56 i'm teaching a friend to program on monday. i wonder how well he'll do

5:06 rritoch: dysfun_: 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.

5:07 amalloy: those sound like pretty good success rates. how many people who learn to run go on to be runners?

5:09 dysfun: well he has a very technical mindset, so i think he'll take to it quite well

5:09 i don't anticipate he'll become a programmer though

5:10 plus 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

5:10 rritoch: dysfun: 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.

5:11 dysfun: that's a helluva stereotype

5:11 i don't consider myself in the slightest bit 'power hungry'

5:12 and i've been programming for getting on 20 years now

5:13 the patience for wading through docs i'll say is definitely a prereq though

5:15 rritoch: dysfun: 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 .

5:15 borkdude: does anyone have a non React todo-mvc clojurescript app that doesn't re-render naively but has fine grained DOM updates?

5:16 dysfun: personally 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

5:16 i must have picked up and put down some of my projects hundreds of times over the years

5:17 rritoch: dysfun: You may be onto something there, I've written some of my most innovative code while intoxicated.

5:18 dysfun: But normally I find my solutions after a great deal of swearing.

5:18 dysfun: my tolerance for boredom goes either way when intoxicated. sometimes great, sometimes not so much

5:19 creativity on the other hand, well...

5:19 and makes people more inclined to write tests as well i find

5:29 rritoch: dysfun: 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.

5:30 dysfun: provided they've got experience in any comparable language, i don't agree

5:30 and for the majority of clojure work, you need to know very little about java

5:30 justin_smith: rritoch: 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

5:30 dysfun: i'd contest there's more risk of breaking them into bad habits

5:37 elegize: How does one get started with clojure?

5:38 rritoch: elegize: Depends on your experience, what other languages do you know?

5:40 elegize: 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

5:53 justin_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.

5:54 justin_smith: Though honestly I never finished reading past the first section. It was more "brain-washing" than I wanted to deal with.

5:56 justin_smith: brain washing?

5:57 I 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.

5:58 nextos: Hello, 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?

6:00 justin_smith: nextos: there are a few approaches. Some of them don't even use laziness.

6:00 nextos: are the tasks CPU bound? IO bound?

6:01 nextos: justin_smith: they are mostly CPU bound, and they call external programs via a shell

6:02 justin_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?

6:03 justin_smith: so i want the same semantics as in unix foo | bar | baz, where foo, bar & baz are reading from input streams in parallel

6:04 justin_smith: nextos: so foos output goes to bar etc?

6:05 nextos: justin_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

6:06 justin_smith: I think core.async would work decently for that, but avoid IO in go blocks

6:08 rritoch: nextos: If your just piping shell commands why not just have the shell handle the piping?

6:09 nextos: rritoch: well, there's very heavy processing of the shell commands which i do in clojure

6:10 rritoch: 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

6:13 justin_smith: nextos: reducers, or a transducer based replacement of them, could be an option here.

6:17 rritoch: nextos: 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

6:22 sdfdsfsfdsfd: hi

6:26 rritoch: nextos: 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.

6:27 nextos: But it is in no way "clojure idiomatic"

6:28 nextos: rritoch: yes, thats not idiomatic ;) but thanks

6:30 justin_smith: nextos: another option is futures that share queues, but that's just lighter weight core.async without the sugar

6:33 nextos: justin_smith: ok, thanks!

6:35 justin_smith: nextos: 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

6:35 ,(def q (atom clojure.lang.PersistentQueue/EMPTY))

6:35 clojurebot: #'sandbox/q

6:35 justin_smith: (swap! q conj :a)

6:35 ,(swap! q conj :a)

6:35 clojurebot: #<PersistentQueue clojure.lang.PersistentQueue@3c6f0c48>

6:36 justin_smith: ,(into [] q)

6:36 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Atom>

6:36 justin_smith: oops

6:36 ,(into [] @q)

6:36 clojurebot: [:a]

6:36 justin_smith: ,(swap! q conj :b)

6:36 clojurebot: #<PersistentQueue clojure.lang.PersistentQueue@8de188a4>

6:36 justin_smith: ,(into [] @q)

6:36 clojurebot: [:a :b]

6:36 justin_smith: ,(swap! q pop)

6:36 clojurebot: #<PersistentQueue clojure.lang.PersistentQueue@3c6f0c0b>

6:36 justin_smith: ,(into [] @q)

6:36 clojurebot: [:b]

6:37 justin_smith: well I probably should have grabbed that value, but hopefully you get the idea

6:55 ddfreyne: Hey peeps. I am having a bit of a difficult time wrapping my head around some Clojure behavior.

6:55 For instance, (:firstname nil) returning nil instead of an exception.

6:56 I wrote down the problem that I’m facing: https://gist.github.com/ddfreyne/57efc45455fa5837b58e

6:56 I have a strong feeling I am not using Clojure properly, or that I don’t understand Clojure’s philosophy here.

6:57 justin_smith: ddfreyne: a keyword, symbol, hash-map, set, or vector when used as a function ends up calling get

6:58 ddfreyne: 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

6:59 ddfreyne: (map #(:firstname % ::not-found) (:body response))

6:59 then you can test for ::not-found

7:00 (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

7:00 ddfreyne: justin_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.

7:01 justin_smith: ddfreyne: sure, and you could make your own function for this, of course

7:01 it's not a complex bit of code, it's just not the default behavior

7:03 ddfreyne: contains? will likely be useful if you want to do a proper assertion check

7:04 ,((fn [place key] (assert (contains? place key)) (get place key)) {:b 0} :a)

7:04 clojurebot: #<AssertionError java.lang.AssertionError: Assert failed: (contains? place key)>

7:04 ddfreyne: justin_smith: I am also tempted to implement safe-get myself. Somewhat weird to have to reimpement it though.

7:05 justin_smith: I think the encouraged style of programming is one where not finding data in a datastructure isn't neccessarily an error

7:06 ddfreyne: 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)

7:07 so 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

7:08 ddfreyne: justin_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.

7:09 justin_smith: ddfreyne: I think part of it is that it's the lisp tradition

7:09 ddfreyne: justin_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.

7:09 justin_smith: and 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

7:10 ddfreyne: Yeah, I believe so.

7:12 I’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

7:12 So I definitely want to work on that.

7:13 justin_smith: I 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

7:13 which in some codebases can be kind of unclear

7:15 ddfreyne: Yup. It is odd to add type information all over the place in a dynamic language though. Feels a bit schizophrenic.

7:16 justin_smith: ddfreyne: 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)

7:18 ddfreyne: True. It’s alos more about structure rather than types.

7:18 justin_smith: yeah - though langs like OCaml can infer "the type that contains an int under key a" and enforce that just by analyzing your code

7:19 so really it is a type that we would call a shape :)

7:21 and 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)

7:36 rritoch: ddfreyne: 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.

7:37 justin_smith: rritoch: that's what keep is for

7:37 rritoch: keep?

7:37 dysfun: keep is like filter identity . map

7:37 justin_smith: ,(keep :foo [{:foo :a} {} {:foo :b}])

7:37 clojurebot: (:a :b)

7:38 justin_smith: dysfun: almost, it lets false through though, just drops the nils

7:38 rritoch: checking now ...

7:38 justin_smith: also, #(:foo %) in that context is just :foo

7:38 dysfun: justin_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

7:39 justin_smith: dysfun: 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

7:39 dysfun: oh i quite agree. i'm a fan of keep

7:40 i'm not converted on () being true though

7:40 chaining seq is a bit annoying

7:40 rritoch: ,keep #(* 2) [1 2 3 4])

7:40 clojurebot: #<core$keep clojure.core$keep@14c5cb5>

7:40 rritoch: ,(keep #(* 2) [1 2 3 4]))

7:40 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/eval71/fn--72>

7:40 rritoch: ,(keep #(* 2 %) [1 2 3 4]))

7:40 clojurebot: (2 4 6 8)

7:40 dysfun: (partial * 2) also works

7:41 rritoch: Hmm, keep is my new best friend

7:41 Is there a keepv hiding somewhere?

7:41 dysfun: i cleaned up a lot of code when i found keep

7:42 no, but you can (apply vector %)

7:42 justin_smith: dysfun: or better (into [] ...)

7:42 dysfun: is that 'better'?

7:42 it's a couple of keystrokes shorter, but i try to avoid into generally

7:43 rritoch: When I need to cast to vector I usually just (vec ...)

7:43 justin_smith: dysfun: check the source for vector, it does a bunch of consing

7:43 dysfun: 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

7:43 into is much more straightforward

7:46 rritoch: Is there a benefit to using (into [] '(1 2 3)) vs (vec '(1 2 3)) ?

7:48 dysfun: justin_smith: only the first few items?

7:49 not that i expect it matters much anyway. few programs crunch enough data that it'll make a noticeable difference. microbenchmarking is bad etc.

7:49 rritoch: From 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?

7:49 justin_smith: rritoch: yeah, vec directly reuses the input as its basis

7:50 which, if you already had that collection, is a good thing iirc

7:51 rritoch: I think the fact that mapv uses either reduce and transients (which is what into uses internally) or just calls into is a clue

7:51 err, wrong target there sorry

7:51 dysfun: ^^

7:52 dysfun: core tends to be pretty aggressive about micro scale performance stuff

7:52 dysfun: and terrible about documenting such things

7:52 justin_smith: dysfun: true that

7:53 dysfun: /me submitted a doc patch this week

8:03 rritoch: ,(time (vec (keep (partial * 2) [1 2 3 4])

8:03 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

8:04 rritoch: ,(time (vec (keep (partial * 2) [1 2 3 4])))

8:04 clojurebot: "Elapsed time: 0.703835 msecs"\n[2 4 6 8]

8:04 rritoch: ,(time (filterv identity (mapv (partial * 2) [1 2 3 4])))

8:04 clojurebot: "Elapsed time: 3.346403 msecs"\n[2 4 6 8]

8:05 rritoch: Yep, keep is my new best friend

8:11 I guess I really need to read that refrence manual

8:13 foodoo: and again, Clojure has showed me that I should look for the simple solution...

8:14 dysfun: rritoch: the cheatsheet is quite handy

8:15 you can 'golf' clojure. just in terms of complexity rather than code size (although it's often smaller)

8:15 foodoo: btw: What is currently the most-used unofficial documentation site for Clojure? clojuredocs.org? clojuredoc.org?

8:16 dysfun: cheatsheet goes to clojuredocs.org now, probably that.

8:34 mmeix: Again 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...)

8:35 (would you*)

9:05 mfikes: mmeix: Yes, am able to read the first one more rapidly owing to its use of data literals

9:07 mmeix: thanks - I guess core.match would be overkill in this case (in fact it is matching against a test pattern)

9:14 mfikes: mmeix: Yes, it made me think of pattern matching; I have no experience with core.match yet :)

9:15 mmeix: the first example in https://github.com/clojure/core.match shows just this application, as I found out afterwards

9:17 dark4eg: #/join clojurescript

9:44 expez: does tools.nrepl guarantee the delivery order of messages?

11:06 lgrapenthin: Has somebody attempted to turn tbaldrigdes ioc macro into a step debugger already?

11:17 patrkris: hi 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:17 7

11:19 ah, found this: http://blog.jenkster.com/2014/02/using-joda-time-as-your-clojure-inst-class.html, so nevermind :)

11:27 gfredericks: I keep thinking there oughta be a lib for setting up that reader literal stuff

11:27 but I'm not sure exactly what it would look like

11:42 noncom|2: how do i get a fully qualified name of a symbol ?

11:43 for 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:48 gfredericks: noncom|2: you're writing a macro?

11:49 noncom|2: gfredericks: right, a macro (record) that is wrapped around the usual call of the function... something like (apply)

11:50 gfredericks: I think resolve should work, at macroexpand time

11:50 ,(doc resolve)

11:50 clojurebot: "([sym] [env sym]); same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"

11:50 gfredericks: hm

11:50 yeah

11:51 noncom|2: *ns* is clojure.core when i eval the recorded form from a different site :D

11:51 gfredericks: um

11:51 it should be the right thing at macroexpand time

11:51 i.e., it should be the namespace of wherever the call to record is happening

11:52 noncom|2: so, i just do (resolve) on the function-name symbol inside the macro ?

11:52 gfredericks: yeah, that'll give you a var

11:52 with all sorts of helpful metadata

11:52 ,(meta #'first)

11:52 clojurebot: {:ns #<Namespace clojure.core>, :name first, :added "1.0", :file "clojure/core.clj", :static true, ...}

11:53 gfredericks: ^ like such

11:53 noncom|2: okay :)

11:53 thanks)

11:54 gfredericks: np

11:57 thedanko_: sup fellas?

11:58 beautiful day in chicago

12:00 wow schema looks sweet

12:17 patrkris: exit

12:53 mmeix_: 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:54 bbloom: mmeix_: both of them seem a little needlessly cryptic

12:54 mmeix_: ok

12:55 bbloom: mmeix_: http://rosettacode.org/wiki/FizzBuzz#Clojure that first one looks fine to me

12:55 mmeix_: there is a fine line between compact and cryptic, I guess ...

12:56 ah, that's clearer, yes

12:56 thanks

12:56 bbloom: mmeix_: it's also more compact :-)

12:57 mmeix_: of course

12:57 still learning

12:57 bbloom: the other ones on that page look awful

12:57 mmeix_: but it's getting better (with a little help from #clojure) :-)

12:57 bbloom: (iterate inc 1) is just silly

12:57 justin_smith: mmeix_: why (as-> n % [(rem % 3) (rem % 5)]) rather than [(rem n 4) (rem n 5)]

12:58 I don't see what as-> buys you here

12:58 mmeix_: right you are

12:58 just had found as->, only excusion :-)

12:59 bbloom: mmeix_: if you're just learning: avoid core.match

12:59 mmeix_: ok

13:00 thanks

13:00 (words from the wise are very appreciated)

13:01 justin_smith: now (interate inc' 0) might actually have a point, if you intended to get to numbers that high

13:03 mmeix_: aren't both iterate and range lazy?

13:03 (I thought so)

13:04 gfredericks: they are

13:05 mmeix_: but iterate throws away interm. steps?

13:05 justin_smith: mmeix_: no, range uses inc, inc' is different

13:05 (doc inc')

13:05 clojurebot: "([x]); Returns a number one greater than num. Supports arbitrary precision. See also: inc"

13:05 gfredericks: justin_smith: that's hard to imagine it getting that high

13:05 justin_smith: gfredericks: right, but I really did qualify what I said with "if you intend to get to numbers that high"

13:06 gfredericks: in the case we were talking about, they used inc instead of inc' anyway

13:06 gfredericks: justin_smith: I'm just wondering if it's physically possible despite intentions

13:06 I'm also curious if there's any perf benefit; my understanding would say no

13:06 mmeix_: (ah: inc', hadn't seen the ')

13:07 justin_smith: gfredericks: there is a perf benefit for range not using inc'

13:07 gfredericks: justin_smith: what from?

13:07 ,(time (nth (iterate inc 0) 1000000))

13:07 clojurebot: "Elapsed time: 136.264005 msecs"\n1000000

13:07 gfredericks: ,(time (nth (iterate inc' 0) 1000000))

13:07 clojurebot: "Elapsed time: 133.085312 msecs"\n1000000

13:08 gfredericks: oh range is chunked isn't it

13:08 I guess that would do it

13:08 ,(time (nth (range) 1000000))

13:08 clojurebot: "Elapsed time: 169.179278 msecs"\n1000000

13:08 gfredericks: ha

13:11 justin_smith: (nth (partition 10 (iterate inc' 0)) Integer/MAX_VALUE) ; space-heater

13:11 gfredericks: does the partition 10 enhance the heater somehow?

13:13 justin_smith: gfredericks: I wanted to make it spit out numbers larger than Integer/MAX_VALUE, but nth does not allow indexes that high

13:13 and I think the partition does introduce an overhead, yeah

13:14 bbloom: justin_smith: try (drop Integer/MAX_VALUE) several times :-)

13:14 justin_smith: bbloom: good call

13:19 gfredericks: huh. what is the benefit of nth taking an int

13:19 ,(nth (range) 9999999999999)

13:19 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for int: 9999999999999>

13:20 bbloom: gfredericks: 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:21 gfredericks: but i suspect the reason they are ints is b/c they are often backed by java collections that take ints as indexes

13:21 java arrays, for example, are int indexed

13:21 mmeix_: (there is no sparse coll in clojure, right?)

13:21 bbloom: mmeix_: it's called a map

13:21 :-)

13:22 mmeix_: umpf

13:22 ok

13:22 sight

13:22 sigh*

13:22 bbloom: seriously, if you were to create a persistent/immutable sparse vector, you'd just be re-implementing clojure's persistent immutable hash maps

13:22 or maybe the tree maps

13:22 either way, yeah, it's called a map

13:23 gfredericks: ,{9999999999999 :hey}

13:23 clojurebot: {9999999999999 :hey}

13:23 gfredericks: ^ big sparse vector

13:23 mmeix_: didn't think about it that way - thanks

13:23 llasram: bbloom: Random-access sparse anyway. Sequential-access sparse is a bit different :-)

13:24 bbloom: although, there could be a case for implementing a wrapper around maps to provide a vector-like interface

13:24 so that nth, count, etc would make more sense for sparse vector usage

13:24 mmeix_: (bear with a beginner's confusions)

13:24 bbloom: mmeix_: that's not a beginners confusion. i know lots of experts who don't understand that!

13:24 mmeix_: I only had the sequential case in mind

13:24 bbloom: llasram: sorted-map can give you sequential access to sparse vector-like maps

13:25 gfredericks: ,{-3.14 :hey} ;; super weird vector

13:25 clojurebot: {-3.14 :hey}

13:25 bbloom: ,(sorted-map 5000 :x 1 :y 99999999999 :z)

13:25 clojurebot: {1 :y, 5000 :x, 99999999999 :z}

13:25 mmeix_: bbloom thanks for encouragement :-)

13:25 bbloom: gfredericks: ugh. floats as map keys *cringe*

13:26 equality? we don't need no stinkin' equality!

13:26 gfredericks: floats haha what are you gonna do

13:27 mmeix_: {nil 3 false 2} seems to be legal ...

13:27 gfredericks: because ##(= nil false)

13:27 lazybot: ⇒ false

13:27 mmeix_: (not I could think of a use case ...)

13:28 that I*

13:28 gfredericks: ,(hash-map nil 1 false 2 'nil 3 'false 4)

13:28 clojurebot: {nil 3, false 4}

13:28 gfredericks: ,(hash-map nil 1 false 2 (symbol "nil") 3 (symbol "false") 4)

13:28 clojurebot: {nil 1, false 4, false 2, nil 3}

13:28 mmeix_: funny

13:28 justin_smith: ,(hash-map 1 :a 1N :b (float 1) :c (double 1) :d 1M :e)

13:28 clojurebot: {1.0 :d, 1 :b, 1M :e}

13:28 andyf: Not 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:29 bbloom: andyf: argh. that sucks

13:29 justin_smith: haha, that turned 1N into 1

13:29 gfredericks: the imaginary language in my head that I never made or designed has none of the flaws that clojure does

13:30 andyf: ,([:a :b :c] 1)

13:30 clojurebot: :b

13:30 andyf: ([:a :b :c] (+ 1 (+ 2 (*' 2 Long/MAX_VALUE))))

13:30 ,([:a :b :c] (+ 1 (+ 2 (*' 2 Long/MAX_VALUE))))

13:30 clojurebot: :b

13:30 mmeix_: nil as a key: could there posssibly be a sensible use case?

13:31 andyf: It is unlikely to snag you in practice, I expect.

13:31 gfredericks: mmeix_: probably not

13:32 justin_smith: mmeix_: when using a map as a dispatch table and handling a nil input

13:32 though I guess you would usually want nil to do the same thing as not-found

13:32 mmeix_: aha!

13:33 gfredericks: justin_smith: it could be the difference between not supplying an option vs accidentally supplying a nonexistent one

13:33 justin_smith: gfredericks: sure

13:33 or if the dispatch table was supposed to emulate cons somehow, and nil is thus a viable alternative

13:34 mmeix_: I guess, it would be better to avoid such a situation anyhow, right?

13:34 justin_smith: ,(cons 1 nil)

13:34 clojurebot: (1)

13:34 justin_smith: nil is explicitly provided and has a specific meaning here

13:35 mmeix_: as: "start consing from here"?

13:36 justin_smith: mmeix_: yeah, basically hysterical raisins from historical lisps, where the sentinal value in a linked list meaning "end" was nil

13:36 mj_langford: lol at "hysterical raisins"

13:37 andyf: visualize whirled peas

13:37 mmeix_: nil as in: nothing 'more' to get here?

13:37 ok

13:38 thanks for context

13:38 danielglauser: Any 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:40 mmeix_: (I'm collecting some of my questions with answers from here, so I can laugh about them in a month or two ... :-)

13:41 bbloom: danielglauser: weasel is much easier to use and more reliable than austin

13:45 sritchie: bbloom: fully agree

13:48 danielglauser: Thanks gents, I'll check it out

13:55 mmeix_: last question for today: would you recommend reading through the clore.core source to deepen understanding (besides books and REPLing of course)?

13:55 sritchie: danielglauser: om-bootstrap’s doc site is all set up with a weasel repl, https://github.com/racehub/om-bootstrap/blob/develop/project.clj

13:55 if you want to check that out

13:55 mmeix_: it can be nice to try to recreate functions from core,

13:56 mmeix_: then look at core to check your work

13:56 mmeix_: ah, that's better

13:56 sritchie: mmeix_: many of the https://www.4clojure.com/ problems are re-impls of core

13:56 I’d suggest working through 4clojure, then reading source later for fun

13:56 justin_smith: mmeix_: also, clojure.core is not normal clojure - it's optimized clojure

13:56 mmeix_: if you are writing for readability the way core does it is not always best

13:57 mmeix_: yes, I'm working 4clojure, right now beginning the Medium cases...

13:57 justin_smith understood

13:57 sritchie: mmeix_: all of the ones marked “core-functions”: https://www.4clojure.com/problems

13:57 mmeix_: you can check in core.clj later for fun

13:58 mmeix_: great advice, thanks

14:00 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:01 bbloom: mmeix_: yes, but they are *micro* optimizations that you probably shouldn't ever do unless you really know you need to

14:01 remember: core is on *everyone's* hot path

14:02 mmeix_: yeah, only asked to understand, not to imitate

14:04 (thanks for today, nightfall here, I'll get me a glass of wine and tune my harpsichord :-)

14:05 (I like the fact, that Rich Hickey started out as a musician :-)

14:05 bye

14:11 danielglauser: sritchie: Thanks for the pointer. Sent you a PR for a minor spelling issue in the README.

14:11 sritchie: nice, thanks!

14:16 donbonifacio: is it possible to non blocking IO with compojure?

14:25 hoangelos: I 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:27 I 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:32 justin_smith: hoangelos: you can use clojure.java.io/input-stream to get an input-stream from a file

14:32 ((comp io/input-stream io/file) file-name)

14:33 hoangelos: 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:34 hoangelos: But the io/copy doesn't that return an outputstream and not an input stream?

14:35 justin_smith: it puts the contents of the input onto the output, and you can use io/inputstream to get an input from that output

14:36 io/input-stream that is

14:39 hoangelos: so you are saying like (io/input-stream (io/copy in out))

14:39 justin_smith: does io/copy return the out argument? I forget

14:40 but yeah, something like that

14:40 (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:41 hoangelos: I just noticed in the docs - it returns nil actually

14:41 (doc clojure.java.io/copy)

14:41 clojurebot: "([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:43 scriptdevil: Hi, 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:43 justin_smith: scriptdevil: use into

14:44 ,(into [1 2 3] ((fn [] (list 4 5 6))))

14:44 clojurebot: [1 2 3 4 5 ...]

14:44 justin_smith: thanks for printing "..." instead of 6 clojurebot, that sure did save space!

14:44 scriptdevil: But this is in the middle of another vector...

14:44 justin_smith: don't do that

14:44 it isn't a thing

14:45 scriptdevil: 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:45 scriptdevil: I 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:45 justin_smith: Oh. Ok. Thanks.

14:45 justin_smith: hiccup will use the vector returned by into just fine

14:46 hoangelos: something must be wrong, because I keep getting OOM errors with teh Java heap size.

14:46 scriptdevil: justin_smith: Wouldn't [:div#footer [[:p foo] [:p bar]]] be a problem?

14:46 justin_smith: hoangelos: clojuer uses a LOT of heap, you should up your limit probably

14:47 scriptdevil: justin_smith: [[:p foo] [:p bar]] are returned by my function.

14:47 s/are/is

14:47 hoangelos: justin_smith: even when I set to over 1000M it gives me OOM

14:47 justin_smith: scriptdevil: then return the right thing instead

14:47 scriptdevil: justin_smith: what do you suggest I return?

14:47 justin_smith: hoangelos: 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:48 hoangelos: our app has never required more heap that 60m

14:48 scriptdevil: justin_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:49 Not being lazy here.

14:49 justin_smith: scriptdevil: run a function on the div

14:50 scriptdevil: hiccup just uses normal clojure data structures, so you can use standard functions (like into as I showed above) to build your values

14:50 scriptdevil: justin_smith: Ok. Thanks.

14:51 justin_smith: hoangelos: profiling is the answer I think. Yeah, going from megs to gigs of heap usage is a bad sign.

14:51 scriptdevil: I just realized that I could use ~@ if I returned a list instead of a vector. That looks interesting. Thanks.

14:51 justin_smith: scriptdevil: with a syntax-quote, yeah I guess so

14:52 syntax-quote with ~@ is just a sugar for concat

14:52 scriptdevil: Thanks, justin_smith. This was useful.

14:55 egghead: is there some version of `get-in` that will work with lazy seqs?

14:56 justin_smith: egghead: no, because 'get' does not work on lazy-seqs

14:56 but you can use -> very similarly, with nth

14:56 egghead: ,(get-in {:nums (range 3)} [:nums 0])

14:56 clojurebot: nil

14:56 egghead: is the sort of thing I want to do :/

14:57 justin_smith: ,(-> {:a {:b (range)}} :a :b (nth 0))

14:57 clojurebot: 0

14:57 egghead: hm, I guess I could just write a function that is kind of like get-in but does 'the right thing' ?

14:57 i.e. get vs nth

14:57 justin_smith: egghead: or a macro wrapping -> would be another option

14:58 (dec macro-contagion)

14:58 lazybot: ⇒ -1

15:05 arrdem: lazybot: ping

15:05 lazybot: arrdem: Ping completed in 0 seconds.

15:18 arrdem: anyone 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:22 justin_smith: arrdem: 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:22 https://github.com/cgrand/parsnip/

15:25 arrdem: I 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:26 unless I'm missing something in the implementation of alt

15:26 mj_langford: https://github.com/Engelberg/instaparse ?

15:26 It does all context free grammars, so LR/LALR is in that set right?

15:26 (been a few years)

15:28 arrdem: mj_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:28 mj_langford: Ahh, sorry!

15:28 arrdem: no worries

16:29 mi6x3m: hey, could someone explain this "For Symbols, syntax-quote resolves the symbol in the current context"

16:29 arrdem: what's to explain?

16:29 mi6x3m: I am wondering where I should write clojure.core/conj in my macro

16:29 or just "conj" when I syntax quote

16:29 arrdem: just conj

16:29 it'll resolve to clojure.core/conj if it's referred

16:30 mi6x3m: ok, so it will be resolved at compile time

16:30 arrdem: eh... at macro time IIRC

16:30 mi6x3m: yeah

17:00 amalloy: arrdem: at reader time

17:00 arrdem: amalloy: backquote wrapped symbols are reader-resolved?!

17:01 amalloy: ,`conj

17:01 arrdem: &'`foo

17:01 lazybot: ⇒ (quote clojure.core/foo)

17:01 clojurebot: clojure.core/conj

17:01 * arrdem monkey's uncle

17:01 amalloy: arrdem: everything ` does is at read time

17:10 KeithPM: Any advice on how to survive being forced to learn some python for a coursera course?

17:10 TravisD: Learn python, I suppose

17:11 Wild_Cat: KeithPM: Python's a cool language, and it's omnipresent. Learning it is a good opportunity.

17:12 mdeboard: Clojure and Python share important similarities after all

17:12 KeithPM: Thanks. 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:13 Thanks, I will go forward bravely with your encouragement :)

17:13 mdeboard: Immutability is cheap and easy in Python. It's just not the default.

17:13 KeithPM: OK mdeboard. I will seek out that style

17:14 TravisD: Also, if you’re doing numerical stuff, I think you probably want to have simple datastructures for representing vectors, arrays, etc

17:14 and that makes them expensive to work with immutably

17:14 mdeboard: Python 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:15 justin_smith: TravisD: 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:15 KeithPM: Thanks, I would like to take a functional approach. Language looks powerful, I miss map, reduce, filter, etc. I will be hunting them down

17:16 mdeboard: and of course out of the box it has first-class functions

17:16 KeithPM: map/reduce/filter are non-idiomatic in python. Generators and comprehensions are what's used for such things

17:16 KeithPM: sweet. I am feeling better already

17:17 I am seeing something called broadcasting looks a bit like mapping to me

17:17 TravisD: justin_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:17 mdeboard: KeithPM: I think that's a NumPy specific concept

17:18 about which I know really nothing :D

17:18 KeithPM: Yes it appears to be an adarray feature

17:18 TravisD: KeithPM: 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:19 the major use case is something like adding a vector to every row of a matrix

17:19 KeithPM: Oh yes. That is the plan. We're using numpy and scipy to do FFTs and other sound analysis

17:20 TravisD: you can also use it to apply functions to matrices component-wise, IIRC

17:20 which is something that crops up surprisingly often

17:21 KeithPM: Thanks. I will go bravely, it looks pretty attractive so far.

17:21 mdeboard: in general it's straightforward to structure python code exactly as you would clojure code

17:21 KeithPM: Cool

17:22 mdeboard: (Clojure wins in terms of immutability-by-default though for sure)

17:22 TravisD: mdeboard: are there no performance overheads to writing clojure-style code in python?

17:22 KeithPM: That is MY use case for clojure. Very powerful

17:22 justin_smith: mdeboard: as long as you don't do anything with threads :)

17:22 TravisD: I think function evaluation in python is like, ridiculously expensive

17:22 arrdem: TravisD: there are performance overheads to writing Clojure style code in Clojure :D

17:23 TravisD: true :)

17:23 mdeboard: TravisD: You might be thinking about function lookup or something? I'm not sure wha tyou mean

17:23 TravisD: For numerical code these things can be serious problems, though

17:23 mdeboard: Then again, I'm not writing high performance code in python

17:23 borkdude: in transducers, an iteration is non realized transformation with data supplied?

17:24 TravisD: mdeboard: 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:24 mdeboard: Then again again, I highly doubt for a given problem the bottleneck would even be the language

17:25 TravisD: mdeboard: 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:25 justin_smith: mdeboard: clojure / jvm can do some smart things to inline and optimize function calls if you hint the args and scope things right

17:25 mdeboard: the semantics of python make these optimizations illegal

17:25 mdeboard: Sure

17:25 That's the JIT right? Warming etc.?

17:25 justin_smith: so in clojure we can promise "x is always a primitive int" and the compiler can act on that

17:25 in python, there is no such concept - the type must be checked

17:26 nathan7: PyPy gets quite far

17:26 but it's a pretty damn advanced JIT

17:26 TravisD: Is the JVM responsible for the optimizations that happen when using clojure?

17:26 Or does it all happen at compile time?

17:26 nathan7: a mixture of the two

17:27 Clojure compiler produces bytecode and performs some optimisations at compile time, JVM optimises that at runtime using runtime information

17:27 TravisD: cool

17:27 justin_smith: https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/

17:28 the 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:30 mdeboard: All 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:32 but of course if you're using Python (or Clojure) performance isn't your primary concern anyway

17:34 (runtime performance)

17:36 TravisD: Yeah, 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:39 mdeboard: True. 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:41 (I want to also point out I greatly prefer Clojure to Python for many, many, many reasons for almost every possible application)

17:42 My loyalty cannot be question, Komisar!

17:43 TravisD: hehe yeah, I’ve never written a single piece of production code so I have no perspective on that :)

17:43 hopefully that will change soon

17:50 justin_smith: mdeboard: "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:51 mdeboard: justin_smith: cool

17:51 what was the app doing that ruby itself slowed it down?

17:51 justin_smith: mdeboard: serving pages

17:51 mdeboard: Well, right, but ...

17:52 justin_smith: ruby 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:52 mdeboard: ah

17:52 weird

17:52 justin_smith: which leads to a need for more hardware to serve the same number of requests

17:52 mdeboard: crazy, never heard that before. never used ruby at all

17:52 except in vagrantfile

17:53 justin_smith: also, 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:54 in practice they went from multiple servers for one site, to multiple sites on one server

17:55 mdeboard: sounds awful

17:55 I mean, the former

17:55 justin_smith: yeah

17:55 mdeboard: How much of that is a function of web server choice and the ruby adapter for it?

17:56 justin_smith: mdeboard: both clojure and ruby are providing their own server (http-kit / mongrel)

17:57 mdeboard: mongrel is the zed shaw thing right

17:57 justin_smith: well, unicorn managing multiple mongrels, but that's the gist

17:57 mdeboard: Oh god

17:57 justin_smith: yeah

17:57 mdeboard: Yeah a web server written in ruby (or python) sounds like the worst idea

17:57 ever

17:57 AimHere: I wrote a rudimentary webserver in perl once

17:58 justin_smith: unicorn is a reverse proxy for multiple instances of a ruby web server, written in ruby :)

17:58 mdeboard: oof

17:58 nginx is where it's at. Modern Apache ain't bad either

17:58 right tool for the job etc.

17:58 llasram: justin_smith: I don't believe that's strictly true... Unicorn is a multiprocess Rack Web server

17:58 justin_smith: llasram: OK

17:58 llasram: Each Unicorn process directly serves an instance of the application

17:59 mdeboard: rack is the ruby equiv of wsgi no?

17:59 llasram: Yep

17:59 mdeboard: gateway interface

17:59 llasram: We've still got a few Ruby apps, all using Unicorn and fronted by Apache

17:59 justin_smith: llasram: yeah, you are right of course, I misremembered the details

17:59 mdeboard: unicorn sounds like uwsgi

18:00 llasram: rack :: wsgi :: ring

18:00 unicorn :: gunicorn :: ring-jetty-adapter+jetty

18:00 mdeboard: nginx + uwsgi is speedy and lightweight

18:00 ahso

18:01 llasram: (Well, except that there's no multiprocess JVM Web server, so the analogy is imperfect.)

18:02 justin_smith: llasram: immutant/jboss could be, depending on setup, right?

18:02 llasram: justin_smith: Kind of, but not in the same way, where a parent process manages a herd of worker children

18:02 That kind of model just doesn't make sense for something on the JVM afaik

18:03 justin_smith: llasram: I think it could work, but what would be the point when your vm does threads well already?

18:03 llasram: Exactly

18:03 justin_smith: which gives much more flexibility

18:04 well, does threads well + does not get into shit-tastic states where the best thing is to kill it with a -9 flag

18:04 llasram: Threads + some of the best mainstream GC

18:04 justin_smith: :)

18:04 llasram: heh

18:17 mi6x3m: how fast is assoc with persistent vectors?

18:18 justin_smith: mi6x3m: worst case it's log time iirc

18:18 mi6x3m: I see

18:19 justin_smith: mi6x3m: probably answers all the questions you might have, and then some http://hypirion.com/musings/understanding-persistent-vector-pt-1

18:19 mi6x3m: also, criterium is really good for micro-benchmarking, but profiling is king!

18:20 the steps should be: make it work, notice something is too slow, benchmark, fix the most egregious issue you find in the benchmark

18:23 bbloom: mi6x3m: the correct answer is "very fast"

18:23 mi6x3m: yes, I believe so :)

18:24 bbloom: ,(def a (object-array 100000))

18:24 clojurebot: #'sandbox/a

18:24 bbloom: ,(def v (vec (repeat 100000 nil)))

18:24 clojurebot: #'sandbox/v

18:25 bbloom: ,(time (dotimes [_ 10000] (aset a 50000 123)))

18:25 clojurebot: "Elapsed time: 558.473421 msecs"\n

18:25 bbloom: ,(time (dotimes [_ 10000] (aset v 50000 123)))

18:25 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: aset>

18:25 bbloom: ,(time (dotimes [_ 10000] (assoc v 50000 123))); rather

18:25 clojurebot: "Elapsed time: 16.364501 msecs"\n

18:25 bbloom: boom. fast.

18:25 i'm sure there's some reflection problem in there tho, heh

18:25 ,(time (dotimes [_ 10000] (aset ^objects a 50000 123)))

18:25 Bronsa: bbloom: definitely

18:25 clojurebot: "Elapsed time: 326.54297 msecs"\n

18:25 bbloom: Bronsa: where is it?

18:25 justin_smith: funny how much faster the assoc is

18:26 I wonder if that's because the compiler knows the result of the assoc can't be accessed via static analysis?

18:26 Bronsa: bbloom: the reflector is dumb and it tries to use 123 as unboxed

18:27 bbloom: ,(time (dotimes [_ 10000] (aset ^objects a 50000 (long 123))))

18:27 clojurebot: "Elapsed time: 306.559714 msecs"\n

18:27 bbloom: ,(time (dotimes [_ 10000] (aset ^objects a 50000 (Long. 123))))

18:27 clojurebot: "Elapsed time: 6.773635 msecs"\n

18:27 bbloom: ah, there we go

18:27 wow

18:27 Bronsa: yep

18:27 bbloom: that makes a lot more sense

18:27 justin_smith: differences like that kind of blow my mind

18:27 Bronsa: ,(def b 123)

18:27 clojurebot: #'sandbox/b

18:27 bbloom: mi6x3m: in short, other things will be slow long before vectors are slow :-)

18:27 Bronsa: ,(time (dotimes [_ 10000] (aset ^objects a 50000 b)))

18:27 clojurebot: "Elapsed time: 1.718982 msecs"\n

18:27 Bronsa: bbloom: even faster^

18:28 bbloom: Bronsa: but the vector version has to do the boxing each iteration too, now it's not fair

18:28 Bronsa: bbloom: not sure actually

18:28 bbloom: ,(time (dotimes [_ 10000] (assoc v 50000 b)))

18:28 clojurebot: "Elapsed time: 12.847707 msecs"\n

18:28 bbloom: there you go

18:28 ,(time (dotimes [_ 10000] (assoc v 50000 b)))

18:28 clojurebot: "Elapsed time: 12.511901 msecs"\n

18:28 bbloom: ,(time (dotimes [_ 10000] (assoc v 50000 123)))

18:28 clojurebot: "Elapsed time: 12.752028 msecs"\n

18:29 bbloom: ,(time (dotimes [_ 10000] (assoc v 50000 123)))

18:29 clojurebot: "Elapsed time: 12.50338 msecs"\n

18:29 bbloom: hm

18:29 Bronsa: bbloom: I believe it will just create a boxed 123 in the static initializer

18:29 and use that

18:29 bbloom: i guess the compiler lifts it?

18:29 Bronsa: yes

18:29 bbloom: gotcha

18:29 ooooh computers, you so crazy

18:29 Bronsa: bbloom: the fact that it doesn't do it for aset -- I would consider that a reflector bug

18:30 it should be able to figure out that Object[],int,Object[] is the only arity that makes sense

18:30 bbloom: Bronsa: this may be a good question to ask you....

18:30 Bronsa: and that 123 can be boxed

18:30 Object[],int,Object rather

18:30 bbloom: Bronsa: does the compiler correctly compile primitive invocations for interop method calls?

18:30 especially asking with respect to things like bytes or shorts (ie not doubles or longs)

18:31 Bronsa: it should, yeah

18:31 bbloom: yeah, i assumed it would, but i was seeing some odd profiling data

18:31 Bronsa: but I have to say, the reflector method matching stuff has some weird behaviours

18:31 bbloom: couldn't tell if boxing was or wasnt there, and if it was there, whether it was being attributed to caller or callee

18:31 Bronsa: it might pick a method randomly when multiple match

18:31 or fail to pick one when there's an obvious valid one like in this case

18:32 I gave up trying to fix it and just rewrote the logic from scratch for t.a.jvm

18:32 bbloom: heh

18:32 justin_smith: Bronsa: sounds like a terrible followup to method_missing, method_roulette

18:32 Bronsa: I won't claim my implementation is edge-cases free but it should work better in some cases

18:32 clojurebot: Ok.

18:33 bbloom: justin_smith: i'm still bitter about this: https://github.com/marcel/aws-s3/pull/14

18:34 Bronsa: you know anything about calls to "native" methods?

18:34 ie are they special/different in anyway?

18:36 justin_smith: bbloom: that's terrible

18:38 bbloom: justin_smith: you can say that again

18:39 justin_smith: makes me think they could make a followup to "here comes honey boo boo" about web devs who make bad architectural decisions

18:44 Bronsa: bbloom: native in what sense?

18:47 mi6x3m: I'd say, I really wish recur and try would play nicer together

18:47 I understand the implications, no flame

18:47 danneu: i'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:48 justin_smith: mi6x3m: put the entire body you are recurring to inside the try if the recur needs to be inside the try

18:49 bbloom: Bronsa: like the java `native` keyword

18:49 mi6x3m: justin_smith: nah, this is not the usual use case, I am writing a somewhat complex macro

18:49 doing ... stuff

18:49 Bronsa: bbloom: ah, I have no idea about that

18:49 bbloom: Bronsa: i was seeing some weirdness that looked sorta like boxing in the perf profile when calling a native function

18:50 Bronsa: 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:51 Bronsa: bbloom: I haven't seen any special handling of native methods anywhere so I don't think there should be any difference

18:51 bbloom: Bronsa: k, that's basically what i expected. thanks

18:51 justin_smith: mi6x3m: care to describe what the actual issue is then?

18:52 mi6x3m: justin_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:52 but my solution is a loop / recur loop

18:53 justin_smith: mi6x3m: which part ends up looping?

18:54 mi6x3m: justin_smith: well, you have to check every expression in the bindings vector individually and build up the vector step by step

18:54 justin_smith: oh wait, instead of try-let it's try-loop then?

18:54 mi6x3m: no

18:54 suppose you have (try-let [x 1 y 2 z (throw blabla....

18:54 in your catch clause you want x = 1 and y = 2

18:54 to perform some clean-up

18:55 the gist macro does that by unrolling a large number of bindings

18:55 I do it by using a simple vector and a loop / recur to build up the binding value

18:55 will upload the first version in a second

18:56 justin_smith: mi6x3m: 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:58 oh, and they require using deref explicitly, so you may as well use delay or promise (which have the same deref issue)

18:58 mi6x3m: justin_smith: nah, you don't need all this

19:10 if a part of a lazy seq throws an exception

19:10 why is it thrown every other time?

19:28 ghadisha`: that thing of when you start by trying to "improve" c.c/range but end up modifying the compiler too

19:32 danneu: if 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:21 gfredericks: ,(def cool-nums (map #(/ 42 %) [3 2 1 0]))

20:21 clojurebot: #'sandbox/cool-nums

20:21 gfredericks: ,(last cool-nums)

20:21 clojurebot: #<ArithmeticException java.lang.ArithmeticException: Divide by zero>

20:21 gfredericks: ,(last cool-nums)

20:21 clojurebot: nil

20:21 gfredericks: mi6x3m: you were asking about that? ^

20:22 I 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:23 andrewhr: my mind just blown with this bot evaling clojure

20:23 :o)

22:31 mateus: Hi, 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:32 So, for example, a simple map would be {:1 #{:3 :2}, :2 #{:3}, :3 #{:1 :2}}

22:33 So, 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:34 "(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:34 The map would return a lazyseq of sets.

22:34 How do I merge these sets?

22:51 djames: I'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:52 perhaps simply PROJECT-ROOT/resources?

23:03 Guest55164: +

23:03 TravisD: Aw, I meant to tell mateus that he could use reduce

23:07 hadronzo`: 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:10 nevermind, it wouldn't work

Logging service provided by n01se.net