#clojure log - Oct 15 2014

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

0:13 amalloy: RazWelle1: clojure-clr is on-topic here, but i don't think there are many people here who use it: you may have trouble getting an answer. is there somewhere else you could ask, or some relevant section in the documentation? myself, i don't even understand what the question means

0:15 RazWelle1: amalloy: not that I know of :\ seems most of the people who use clojureclr are either developers or C# experts, I'm a little new to both

0:15 I wanted to learn lisp in a way that was useful to my current project

0:15 which depends on a .net library

0:16 I even tried ironscheme but I'dve made more progress in clojure-clr

0:16 but not by much

0:16 TEttinger: RazWelle1: inspect an assembly as in reflection?

0:16 RazWelle1: TEttinger: yeah basically python's dir()

0:16 So I can see what the repl is able to access

0:16 TEttinger: oh ok

0:17 RazWelle1: I'm trying to translate this http://lib.openmetaverse.org/wiki/IronPython/Simple_Login

0:17 TEttinger: you saw this stuff right? https://github.com/clojure/clojure-clr/wiki/Loading-assemblies

0:18 RazWelle1: Maybe I should try assembly-load-file macro, right now I"m doing it directly with (System.Reflection.Assembly/LoadFrom "libomv/OpenMetaverse.dll")

0:18 justin_smith: RazWelle1: the comment here may be useful https://github.com/clojure/clojure-clr/blob/master/Clojure/Clojure.Source/clojure/core_clr.clj#L199

0:18 RazWelle1: *click*

0:19 xsyn: How do you tell lein to build a dependency against a specific version of something. E.g. spark-core against mvn -Dhadoop.version=2.4.0

0:20 spark-core by default builds against 1.0.4

0:20 justin_smith: RazWelle1: oooh - this one has a promising name... https://github.com/clojure/clojure-clr/blob/master/Clojure/Clojure.Main/Properties/AssemblyInfo.cs

0:20 AssemblyInfo

0:21 oh never mind

0:21 RazWelle1: ooh

0:21 * RazWelle1 looks

0:21 justin_smith: that just *provides* info about the clojure assembly

0:21 reverse of what you want

0:21 * RazWelle1 snaps

0:21 TEttinger: you can call this thorugh interop http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettypes(v=vs.110).aspx

0:24 egghead: grr, I can't find a mustache impl in clojure that will let me configure it to not replace missing vars

0:57 technomancy: does vim interpret Ctrl-i as a tab like emacs and other readline things?

0:58 bbloom_: technomancy: you can do ctrl-v then type what you want directly

0:58 so like if you need a real tab, ctrl-v + tab

0:58 turbofail: ,(do (require 'clojure.walk) (clojure.walk/macroexpand-all ''(-> a b)))

0:58 clojurebot: (quote (b a))

0:59 turbofail: i don't think that should happen

0:59 bbloom_: technomancy: in insert mode, i mean of course

0:59 technomancy: bbloom_: right, but inside a terminal, hitting TAB literally sends a ctrl-i keycode

0:59 bbloom_: does gui vim interpret them as the same thing as well?

1:00 justin_smith: turbofail: that what should happen?

1:00 bbloom_: technomancy: oh i have no idea

1:00 turbofail: justin_smith: it's macroexpanding things within a quote form

1:00 justin_smith: right, it's supposed to do that

1:00 technomancy: any gui vim users care to try?

1:01 turbofail: justin_smith: but that gives wrong results. evaluating '(-> a b) doesn't yield (b a)

1:01 justin_smith: why not?

1:01 it should

1:01 turbofail: justin_smith: notice the two quotes i was using in my macroexpand

1:01 i.e. (macroexpand-all '(quote (-> a b)))

1:02 amalloy: turbofail: clojure.walk/macroexpand-all is not close to being an accurate representation of the compiler

1:02 justin_smith: right, macroexpand ignores one quote - otherwise it wouldn't be very useful

1:02 amalloy: justin_smith: ?????

1:02 turbofail: no, it ignores every quote

1:02 ,(clojure.walk/macroexpand-all '(quote (quote (quote (-> a b)))))

1:02 clojurebot: (quote (quote (quote (b a))))

1:02 amalloy: clojure.core/macroexpand ignores no quotes at all. clojure.walk/macroexpand-all ignores all of them

1:03 justin_smith: amalloy I mean '(+ 1 1) doesn't return (quote (+ 1 1)) - it doesn't show the first layer of quote

1:03 amalloy: justin_smith: macroexpand is not a macro, it is a function. that "first layer" doesn't exist

1:03 bbloom_: technomancy: not sure what you're trying to figure out exactly

1:03 justin_smith: ahh, right

1:03 turbofail: amalloy: that may be the case but it should still at least try and be relatively faithful

1:04 amalloy: turbofail: for a macroexpander that comes close to replicating what the compiler does (but still is not perfectly accurate), try clojure.tools.macro/mexpand-all

1:04 turbofail: it is implemented in the simplest possible way, like everything in clojure.walk

1:04 turbofail: ah

1:05 amalloy: macroexpand-all, like flatten, is (in my opinion) not really a top-quality tool, so much as an example of "check out all this really cool stuff we can do with a small amount of code in clojure! you should try out this language!"

1:05 ie, an advertisement

1:08 oh, pmap is on that list too

1:08 it is impressive that those functions come as close to usefulness as they do; don't get me wrong, they're pretty cool. they do their job well, but once you move beyond toy examples you need something more substantial

1:09 and hey, while you're in c.t.macro, check out macrolet and symbol macros. more fun than a barrel of monkeys

1:18 turbofail: hm. so what remaining discrepancies does c.t.macro/mexpand-all have?

1:21 amalloy: the gist of it is: it's not the compiler. you can't really hope to keep the two separate codebases in sync forever. something might "break" with any update to the compiler

1:21 the only specific issue i can remember is that it doesn't cope with macros which return code objects that you couldn't have typed in as literals, such as sorted maps

1:22 eg, (case x 1 true) expands to something like (case* x {1 true}), except that the map is sorted, not an array-map or a hash-map

1:23 turbofail: ah

1:23 clojurebot: Cool story bro.

1:23 turbofail: silence, bot

1:23 amalloy: so ifyou write a case statement with 8 or more entries, mexpand fails to retain the order

1:23 dbasch: for a good time, macroexpand-all (doseq [a [] b [] c [] d [] e [] f [] g []])

1:23 and read the output when you need help falling asleep

1:24 amalloy: loop loop loop

1:24 turbofail: i've looked into the guts of `for' before, that was an unpleasant experience

1:27 amalloy: i wonder what the guts of CL's LOOP look like

1:28 turbofail: on that note i'd kind of like something like racket's for/fold, for cases in which you're just going to be feeding the result of `for' straight into a reduce

1:29 it'd be nice to not have that intermediate sequence

1:58 aztak: anyone using vim to hack clojure? Sometimes, mostlt when switching windows or using Tagbar, the syntax hilightning gets all screwed up.. anyone else having that problem?

3:42 raspasov: anyone with experience around serializing Clojure's deftype ?

4:01 hyPiRion: amalloy: the CL loop is an amazing macro with some bugginess in it

4:02 dysfun_: is there a pretty-printer for the lein repl?

4:02 for return values

4:02 raspasov: dysfun_: I like this library https://github.com/razum2um/aprint

4:03 dysfun_: that is very nice, but still requires me to manually type it in at the repl

4:03 i'm looking for something that hooks the return value after i execute some code at the repl and pretty prints that

4:03 raspasov: yea, haven't seen anything that does it automatically, it would be awesome though

4:04 dysfun_: well, i may have to, because i'm getting quite annoying trying to deal with a large xml structure

4:04 aha! https://github.com/greglook/whidbey

4:05 raspasov: nice! :)

4:06 razum2um1: raspasov: thanks :) yep, I look to integrate this into repl to format returned value automatically

4:07 raspasov: razum2um1: cool!

4:08 dysfun_: awesome, one line in ~/.lein/profiles.clj

4:08 works like a charm

4:20 zwer: hyPiRion what bugginess?

4:23 hyPiRion: zwer: like https://www.refheap.com/91764

4:24 How to combine the loop clauses are afaik poorly defined and complex

4:36 pluma: Coming from a high-level non-FP background, what is a vector and how is it different from an array or list?

4:43 hyPiRion: pluma: shameless self-plug: http://hypirion.com/musings/understanding-persistent-vector-pt-1

4:43 kungi: hyPiRion: Oh nice!

4:44 hyPiRion: In short. A vector is immutable, but still provides efficient updates and random access lookup compared to an immutable singly linked list

4:44 Also, a vector is always strict, whereas a sequence may be lazy.

4:46 daniel__: ,(cons 5 [1 2 3 4])

4:46 clojurebot: (5 1 2 3 4)

4:46 daniel__: ,(cons 5 '(1 2 3 4))

4:46 clojurebot: (5 1 2 3 4)

4:46 daniel__: ,(cons [1 2 3 4] 5)

4:46 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

4:46 daniel__: ,(cons [1 2 3 4] [5])

4:46 clojurebot: ([1 2 3 4] 5)

4:46 hyPiRion: ,(conj [1 2 3 4] 5)

4:46 clojurebot: [1 2 3 4 5]

4:46 daniel__: right :p

4:46 hyPiRion: ,(conj '(1 2 3 4) 5)

4:46 clojurebot: (5 1 2 3 4)

4:48 pluma: hyPiRion: thanks.

4:49 hyPiRion: np

4:55 CookedGryphon: Does anyone know how core async pipelines work? The docs suggest that transducer state won't be shared, so how would stateful transducers like dedupe work?

5:05 and does anyone have any suggestions for composing pipes? I just want to merge two existing chans, run a transformer on the combined result, and pipe the result into a third existing chan

5:05 and the code's coming out really clunky looking

6:50 kenrestivo: i've got a seq, and i'm dealing with a java thing that wants a java.util.Enumeration. any ideas how to force cast it?

6:54 clgv: ,(ancestors (class (range 10)))

6:54 clojurebot: #{clojure.lang.Sequential clojure.lang.IMeta clojure.lang.Seqable clojure.lang.IPersistentCollection clojure.lang.Obj ...}

6:55 clgv: ,(->> (ancestors (class (range 10))) (map #(.getName %)) sort)

6:55 clojurebot: ("clojure.lang.IHashEq" "clojure.lang.IMeta" "clojure.lang.IObj" "clojure.lang.IPending" "clojure.lang.IPersistentCollection" ...)

6:55 clgv: &(->> (ancestors (class (range 10))) (map #(.getName %)) sort)

6:55 lazybot: ⇒ ("clojure.lang.IHashEq" "clojure.lang.IMeta" "clojure.lang.IObj" "clojure.lang.IPending" "clojure.lang.IPersistentCollection" "clojure.lang.ISeq" "clojure.lang.Obj" "clojure.lang.Seqable" "clojure.lang.Sequential" "java.io.Serializable" "java.lang.Iterable" "java.lan... https://www.refheap.com/91773

6:55 clgv: kenrestivo: you can get an Iterator via java.lang.Iterable interface

6:57 kenrestivo: i have no idea how to do that. tried (.iterator some-seq) and got something, but still same error, it's obviously not acceptable, has to be an Enumation

6:58 Enumeration

6:58 clgv: kenrestivo: if there is no conversion object Iterator -> Enumeration in Java then you can also just (reify java.util.Enumeration (hasMoreElements ...) (nextElement ...))

6:59 kenrestivo: oh, sure, thanks, guess i could just write my own. that should work.

7:03 clgv: kenrestivo: (defn ->enumeration [^java.lang.Iterable xs] (let [it (.iterator xs)] (reify java.util.Enumeration (hasMoreElements [_] (.hasNext it)) (nextElement [_] (.next it)))))

7:05 kenrestivo: clgv: thank you. that is awesome. worked. is that in a util library somewhere?

7:06 clgv: kenrestivo: no idea. just wrote it right now

7:06 kenrestivo: it's a couple lines longer than what i was writing, and it works whereas mine did not. anyway, thanks

7:06 clgv: :)

7:20 dysfun_: is there a clojureish library that takes in an XML DTD and makes it easier to work with xml conforming to it?

7:24 clgv: dysfun_: that's pretty vague

7:25 dysfun_: yes, i know. i don't work with xml much so i'm not sure how it may be made more useful. i do know that my code is a mess. i suppose xml validation would be a good start

7:26 rweir: what did you want it to do beyond validating that the xml is uh valid

7:26 clgv: dysfun_: data.xml converts the xml to a clojure data structure

7:27 dysfun_: ideally some abstraction that allows easy transformation. zippers ended up making it more complex when i tried that last

7:27 yes, i have that and i have messy code that works with it

7:27 dtd validation would at least enable me to kill the error checking

7:27 clgv: dysfun_: maybe use a transformation language like xslt?

7:28 dysfun_: hrm, i think what i want could be quite simple in xslt actually

7:28 thanks

7:29 clgv: dysfun_: maybe that one helps if you need to integrate it within a clojure project https://github.com/pjt/saxon

7:29 dysfun_: brilliant, thanks

7:30 perplexa: hello

7:31 dysfun_: "You can download an evaluation copy of the software from here.". Maybe not :(

7:31 perplexa: i have a (dorun (for ...)) form, that i want to execute in parallel. should i use core.async or just get fancy with pmap?

7:35 clgv: dysfun_: oh well...

7:35 perplexa: clojure.core.reducers

7:36 dysfun_: thanks

7:37 perplexa: clgv: i have multiple functions take take a couple of minutes for computation

7:37 and i want them to run in parallel ;x

7:38 clgv: perplexa: example?

7:38 perplexa: actualy, they just submit the work to a cluster and then wait for the result

7:38 clgv: cascalog queries :P

7:39 but some just don't use the entire cluster, so that i have more map/reduce slots for more queries, therefor i want to execute them in parallel

7:39 clgv: perplexa: well, you can probably submit them asynchronously and just start waiting for the results after you submitted all

7:39 perplexa: that's what i want to do

7:39 but i don't know what the right way would be ;/

7:39 clgv: but then you do not need anthing in addition to the cluster lib

7:40 or does it not support asynchronous submits?

7:40 the easy trick would be to wrap those submits into futures then

7:41 perplexa: i don't think it does

7:41 but i don't care about the results either, it's just fire&forget basically

7:41 clgv: you just want to heat the server room, eh?

7:42 well do you need to wait for completion of those tasks?

7:42 perplexa: haha :) nah, the queries read from hdfs and write to hdfs, and i don't need any of the info in clj

7:42 nope :)

7:42 clgv: ok just use futures and forgot about them ;)

7:42 * perplexa checks out futures

7:43 perplexa: i just hope the application doesn't terminate while they're still running ;p

7:43 when using futures

7:43 so.. i put a bunch of futures in a vector and then check if they're finished or something?

7:44 clgv: yeah.

7:44 well then you need to wait for completion by dereferencing the futures...

7:47 perplexa: clgv: soooo. just (let [x (for [..] (future ...))]) and then (map #(@%) x) afterwards or sth?

7:50 clgv: perplexa: no you need to eagerly create those futures, e.g. (doseq [f (mapv #(future ...) coll)] (deref f))

7:51 perplexa: if you absolutely need that `for` wrap it in `vec`

7:51 perplexa: i don't think i do :)

7:53 clgv: what's the difference between your example and mine?

7:56 clgv: perplexa: you have lazy stuff in there such that futures won't be created until that `for` is forced, so you effictively create the future when you are trying derefing it such that no parallelism is happening

7:57 perplexa: ah! thx

7:57 that's what mapv is for i guess :)

7:57 (inc clgv)

7:57 lazybot: ⇒ 30

7:57 * perplexa probably still has -1 from an inappropriate joke he cracked when first joining the chan ;p

7:57 clgv: perplexa: in my example yes. in general there are other use cases as performance ;)

7:58 $karma perplexa

7:58 lazybot: perplexa has karma -1.

7:58 clgv: hehe

7:58 perplexa: haha

8:54 visof: hi

8:55 is there anybody used apache-s4 beforehand?

9:00 clgv: ~anyone

9:00 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

9:02 luxbock: in leiningen templates when passing the data map to the ->files function, how are functions as the values of the map used?

9:02 in the chestnut template there's a line like this: `:not-om-tools? (fn [block] (if (om-tools? opts) "" block))`

9:03 and then in the core.cljs file there's a line: `(dom/h1 {{#not-om-tools?}}nil {{/not-om-tools?}}(:text app))`

9:03 so I understand what it does, but I'm still confused about the role of the `block` argument that the function gets

9:05 ah think I get it now

9:06 the block is the text between the mustache block as defined by #not-om-tools and /not-om-tools

9:13 perplexa: 14:34:38 perplexa | Java.lang.RuntimeException: No such var: impl/logical-comp, compiling:(cascalog/logic/ops.clj:46:3)

9:13 14:35:02 perplexa | i randomly get that error on a query that otherwise works, any ideas where this might come from?

9:13 14:55:53 perplexa | it's there in line 46: https://github.com/nathanmarz/cascalog/blob/develop/cascalog-core/src/clj/cascalog/logic/ops.clj

9:13 14:56:05 perplexa | but i don't see why it would randomly spew the above error

9:14 is that actually a bug in clojure? i don't see why it would fail ;p

9:18 clgv: perplexa: you said that's executed on a cluster, are you sure the versions of cascalog are the same everywhere?

9:19 perplexa: clgv: yeah, i build an uberjar with lein, which includes the deps and then just run it via `hadoop jar`

9:19 hyPiRion: so nothing in :provided?

9:20 perplexa: actually, when it starts compiling stuff there, could it be that the cleanup interferes between futures ?

9:20 hyPiRion: I've heard of some issues with hadoop related to that

9:20 perplexa: hyPiRion: hadoop-core and hadoop-common are provided

9:21 and those versions match the cluster's.

9:21 it only happens randomly, too ;/

9:21 and i saw it just now that i started using futures, hmm

9:21 hyPiRion: alright, then idk

9:22 perplexa: when it says compiling, it's actually compiling stuff?

9:22 clgv: perplexa: but you only use the futures on the client side right?

9:22 perplexa: yes

9:22 clgv: and there error is server/cluster side?

9:22 perplexa: yesnope client-side

9:22 doesn't even start the query

9:23 s/yesnope/nope/

9:23 clgv: perplexa: does the code within the future dynamically load namespaces?

9:23 perplexa: yes

9:23 ;x

9:24 clgv: that's likely the reason - can you change it to depend statically on those namespaces?

9:24 perplexa: something like

9:24 (require (symbol type-ns))

9:24 ((resolve (symbol type-ns "bootstrap")) id config input)

9:24 it's gonna be hard to have them loaded statically :/

9:24 clgv: perplexa: yeah require is not transactional

9:25 perplexa: I use that one https://gist.github.com/guv/ac76b9ab1878705062c6

9:25 perplexa: nice, i'll see if that helps :)

9:25 clgv: but I think loading of namespaces should be made transactional

9:26 ah well, remove the println ;)

9:27 perplexa: my dirty work around would have been to add a sleep to the execution so that the bootstrapping happens with a 1sec delay between each query :D

9:27 hyPiRion: loading of namespaces transactionally is really hard, just fyi

9:27 stuartsierra: Basically impossible since Clojure allows arbitrary side-effects at the top-level.

9:28 dnolen_: ,*clojure-version*

9:28 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}

9:29 dnolen_: ah hmm, oh well, anyways nice to see using transducers w/ parallel fold "just works" - (r/fold + ((map inc) +) (vec (range 1000000)))

9:29 clgv: stuartsierra: what do you mean exactly?

9:30 Bronsa: dnolen_: nice

9:30 stuartsierra: clgv: "loading a namespace" in Clojure just means loading a file, which means evaluating each of the top-level forms in that file in order. You can do *anything* in a file, no constraints. No way to define a "transaction" around that.

9:31 clgv: stuartsierra: ok. just limit it to require which currently manages to keep track of the namespaces it loaded

9:32 stuartsierra: but it only manages the names in a `ref` - nothing more

9:32 at that point there could be logic to load every namespace (as defined in context of `require`) only once in a thread-safe way

9:34 dnolen_: Bronsa: btw is the JS analyzer work good enough to sync up cljs.core.async w/ clojure.core.async?

9:37 Bronsa: dnolen_: I'm actually waiting on CLJS-857 before cutting a first stable release

9:39 dnolen_: I can work around it if you decide that's not going to make in cljs btw, even though I'd rather not

9:42 dnolen_: Bronsa: re: 857, question, why doesn't this affect the Clojure analyzer?

9:42 Bronsa: or is what 857 proposes what Clojure already does?

9:44 Bronsa: dnolen_: deftype in clojure expands to (deftype* name class.name [fields] :implements [interfaces] (method [..] ..))

9:45 so the inline method impls are in the local scope of the fields, that's what I'm proposing with 857 for cljs

9:45 dnolen_: Bronsa: ok I'm cool with 857

9:47 Bronsa: just tried to apply - emits a lot of analyzer warnings - a I'd take new patch that addresses this

9:47 Bronsa: dnolen_: ok I'll take a look

9:48 dnolen_: Bronsa: looks like a locals thing - analyzer complains about the fields as undeclared vars

10:03 verma: does cursive have insta-repl? like lighttable?

10:06 dnolen_: verma: no only a more traditional REPL - but it's a pretty nice one

10:08 verma: dnolen_, nice! I have to talk to a group of js guys tomorrow, lighttable's insta-repl is pretty nice to show some funky clojure moves :)

10:08 * verma tries cursive

10:10 mping: hi guys

10:11 I'd like some advice

10:11 I'm parsing a ~400mb json file

10:13 and I'm trying to speed up the parsing and processing

10:13 but it's still a bit slow

10:13 Bronsa: dnolen_: did resolve-var's impl change recently?

10:15 verma: mping what are you using to load the json file?

10:16 dnolen_: Bronsa: confirm-var-exists changed, not resolve-var

10:17 Bronsa: we used to not check that vars actually exist from other namespaces, not the case anymore

10:42 csd_: How can I do a try/catch and have a statement execute conditional on an exception not being thrown?

10:43 stuartsierra: csd_: one way (when (try … true (catch Exception _ false)) (do-the-thing))

10:44 csd_: oh will the catch prevent the last statement from executing if there is an exception?

10:44 LauJensen: For those interested I made a screencast showing how to port a visual swing UI app to Clojurescript and HTML5/Canvas http://www.bestinclass.dk/blog/brians-brain-clojurescript

10:45 stuartsierra: csd_: No, I just used the result of the entire try/catch block as the test in the `when`

10:45 TimMc: csd_: (try (let [ret ...] (do-a-thing) ret) (catch ...))

10:45 csd_: i want to have things log differently depending on whether the action succeeds or fails.. i imagine there's an idiomatic way to do that

10:46 stuartsierra: i see, clever

10:46 stuartsierra: A try/catch block returns a value, just like everything else in Clojure.

10:48 csd_: in your example, I assume `ret` is the action that i want to execute conditional on success?

10:48 meant to direct that to you TimMc

10:49 Bronsa: dnolen_: the patch didn't handle correctly defrecord's args, I just attached an updated patch. I don't see any warnings now

10:57 xsyn: using conj should stop me from having a stackoverflow in a recursive function, right?

10:58 gfredericks: uhm

10:58 depends on the details? conj is not lazy though if that's what you're after

10:59 pretty much any function call can give you a stackoverflow if you set it up for success correctly :)

11:01 dnolen_: Bronsa: thanks

11:08 xeqi: gfredericks: identity?

11:12 gfredericks: xeqi: sure

11:12 xeqi: just call it with a bulging stack

11:13 justin_smith: gfredericks: that sounds like something I should look up on urbandictionary

11:14 gfredericks: justin_smith: I cannot condone any such activity

11:19 perplexa: is (some (partial = source) (keys input)) preferable over (nil? (get input source)) ?

11:19 just wanna know if "source" is a key of "input"

11:20 xeqi: (doc contains?)

11:20 clojurebot: "([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."

11:21 perplexa: xeqi: haha thanks :P

11:28 TimMc: csd_: No, ret is the return value from other work you were doing, if you wanted it.

11:30 hiredman: /win 26

11:32 Bronsa: hiredman: http://sprunge.us/BGhG

11:33 justin_smith: Bronsa: clearly it's a secret code

11:35 m1dnight_: Damnit, I wanted to buy a clj sticker for my laptop but I'm missing 0.05 dollars on my prepaid mastercard

11:35 * m1dnight_ waves fist

11:37 hiredman: Bronsa: I have been data mined

11:37 perplexa: clgv: seems the thread safe require solved my problem, much apreciated!

11:37 (inc clgv)

11:37 lazybot: ⇒ 31

11:38 clgv: perplexa: great :)

11:44 TimMc: Bronsa, hiredman: More data: http://sprunge.us/YdDh

11:46 clgv: TimMc: guess he lost now? :P

11:46 perplexa: haha what

11:47 hiredman: reverse engineering my irssi setup

11:47 perplexa: somebody tell him about meta+[1-9] ;/

11:47 ;x

11:47 oh hai

11:47 TimMc: perplexa: ...that doesn't help with more than 10 windows

11:48 justin_smith: TimMc: what, you don't have a "15" key on your keyboard?

11:48 hiredman: actually it does, M t is the same as /win 15

11:48 perplexa: TimMc: there's also meta+qwertyuiop

11:48 TimMc: justin_smith: I know a guy who has a keybiard with F1–F25 and uses all of them.

11:50 verma: is there somewhere, where clojure benchmarks are listed?

11:51 Bronsa: TimMc: hah

11:51 clgv: verma: http://benchmarksgame.alioth.debian.org/

11:53 verma: clgv, thanks, you think clojure was type annotated for these benchmarks?

11:55 clgv: verma: andy fingerhut optimized some (even all?) of those benchmark implementations

11:56 verma: ah no, maybe I confused it. the example I opened says alex miller ;)

11:57 Jaood: verma: extremely annotated

11:57 verma: nice, benchmarks are not bad :)

11:57 nice

11:57 clgv: verma: that one feels like cheating badly: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=pidigits&lang=clojure&id=5

11:58 verma: haha, that qualifies as java

11:58 but I guess that's the point, if need be fallback to raw java

11:58 clgv: even more it uses ASM to generate a class on the fly :P

11:58 verma: wait what?

11:59 clgv: that one is better http://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=clojure&id=1

11:59 verma: oh nice!

11:59 which javascript was there

12:00 wish*

12:00 but I guess this site is convincing enough, that clojure is not slow

12:00 at least compared to what web-dev people do right now with Ruby/Python

12:00 would definitely be interesting to see cljs and javascript added in there

12:00 Jaood: verma: you mean non-idiomatic clojure is not slow

12:01 clgv: Jaood: ah you can get it pretty idiomatic looking and fast, through macros or inline functions

12:01 verma: Jaood, if I use qualifiers people will get confused (context: I am doing a talk about clojure with a bunch of js guys).

12:01 noonian: even idiomatic clojure is not slow, its just not *as fast* as java

12:02 verma: I think this is a pretty picture: http://benchmarksgame.alioth.debian.org/u32q/which-programs-are-fastest.php

12:04 mping: talking of speed, guys can I have your opinion on some clj I have?

12:04 I'm parsing a ~400mb json

12:04 and I don' have alot of clues on how to speed it up

12:04 I've used pmam and reducers

12:04 llasram: mping: A single JSON object or 400MB of separate JSON objects?

12:05 mping: *pmap

12:05 llasram: separate

12:05 one per row, newline separated

12:05 llasram: mping: Which JSON parser?

12:05 mping: cheshire

12:05 but htop shows me that the cpus have alot of headroom

12:05 and visualvm shows me assoc and such as dominators

12:05 llasram: Then are you sure you aren't IO-bound?

12:05 mping: yes; Im pretty sure

12:06 Ive measured the time to parse the json

12:06 llasram: Are your JSON objects generally record-like, with largely the same keys across objects, or are they more map-like, with arbitrary data as JSON object keys?

12:07 mping: record-like

12:07 I can provide the code if you guys want to take a look

12:07 llasram: Sure -- I've run out of reasonable questions to ask :-)

12:07 mping: my task is to read json files with an array path like [a b c d e f]

12:08 and generate "n-grams" such as [a b c] [b c d ] ...

12:08 then sum the whole thing and count

12:08 my lines are like this: {"path":["a","b","c","d","e","f"],"pageviews":7,"visits":1,"duration":97878}

12:09 I'm using lein-exec

12:09 but I am a clojure n00b, so forgive any bad code

12:10 here it is: https://gist.github.com/mping/180343e9c745c9c446d6

12:11 Jaood: mping: are you using laziness?

12:11 mping: yes

12:11 for reading the lines

12:12 llasram: mping: Independent of performance, the way `lazy-file-lines` depends on the lazy seq being fully-consumed to close the file is morally equivalent to depending on GC to release the resource

12:13 mping: There used to be similar helpers in monolithic contrib, but they're pretty much always a bad idea

12:13 Anything like `take` which produces an early-ending wrapper seq leaves the resource dangling until/if GC cleans it up

12:15 mping: Letting cheshire produce keyword-keys for maps is more convenient, but if you're aiming for performance is slower than just leaving the keys as strings

12:16 dnolen_: Bronsa: patch has a bug

12:16 Bronsa: dnolen_: ?

12:17 dnolen_: Bronsa: Caused by: java.lang.RuntimeException: Unable to resolve symbol: op in this context

12:17 Bronsa: dnolen_: gah, I probably have forgot to add that line to the commit

12:17 one sec

12:18 yeah

12:18 llasram: mping: Is your goal just "make it faster" or do you have specific performance benchmarks you need to hit?

12:19 Bronsa: dnolen_: removed old & updated

12:24 dnolen_: Bronsa: applied

12:27 Bronsa: dnolen_: awesome. I'll get t.a.js up to date with the changes that went into cljs over the last month

12:27 dnolen_: once you cut a new cljs release I can release a new beta, then we can talk about porting core.async if you want

12:27 dnolen_: Bronsa: cool sounds good!

12:29 verma: would be nice if people could take a look at this and point out obviously incorrect stuff: https://www.dropbox.com/s/9t8xt6x20oabpjg/ClojurePres.pdf?dl=0

12:29 Bronsa: dnolen_: http://dev.clojure.org/jira/browse/ASYNC-86 is a blocker for that btw.

12:29 verma: any feedback is much appreciated

12:29 dnolen_: Bronsa: ok thanks will look into that

12:30 Bronsa: dnolen_: I'm updating the patch to depend on 0.6.1 ATM, will probably need the ok of tbaldridge

12:30 dnolen_: Bronsa: sure, I'll make sure to check with him

12:36 justin_smith: verma: what does "Language Age ratio" mean?

12:37 verma: I read it some where, how old a language is vs. how popular it is

12:37 can't find source :(

12:37 justin_smith: ahh, so that means "it is popular for its age"

12:37 verma: popularity : age, age

12:37 yes

12:37 may be should just say that

12:38 justin_smith: if Language Age ratio is something people know about it's fine, I had just never heard the term before

12:38 verma: yeah, you're right, I changed the text

12:38 justin_smith: ahh - it's Popularit : Language Age ratio

12:38 verma: oh :P

12:38 I made it italics

12:38 so that it stands out

12:39 justin_smith: I thought Popularity: was a heading

12:39 heh

12:39 verma: but may be make it bold

12:39 justin_smith: yeah, I misread it

12:39 verma: I bold-italicised it

12:40 this is a 10 minute intro slide to just get stuff started, all action will happen in repl

12:40 slides*

12:41 justin_smith: verma: potential alternate target for the benchmark link http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=clojure&data=u64q

12:41 one that specifically highlights clojure

12:41 verma: yeah, I thought about that, the linked one actually says that its potentially as fast as go, where everyone seems to be flocking towards lately

12:42 but that's just a get into the site URl and then I will browse around, but two links don't hurt, so I will add that too

12:42 benzap: So I was wondering, how hard is it to find a software development job which uses clojure?

12:42 verma: benzap, that's an excellent point as well, people are concerned that if they invest time in clojure they won't find a job

12:44 benzap: well, I know there are jobs

12:44 very few though

12:44 justin_smith: verma: "You can write your server side stuff in Clojure inter-ops with Java like its a no-brainer." - multiple issues with this sentence

12:45 verma: justin_smith, sure :) now I see them :)

12:45 justin_smith, I changed it to: You can write your server side stuff in Clojure: it inter-ops with Java.

12:46 benzap: I'm currently working on my own side-project in clojure, which i'm hoping could be marketed sometime

12:47 but it would be awesome if I could find a remote job that used clojure

12:47 nullptr: easier to make jobs in something "new" than to find jobs

12:47 benzap: hmm yeah

12:48 verma: benzap, I pitch clojure all the time to people who pay me (consulting) ..

12:48 most new stuff I am doing is mostly in clojurescript

12:48 noonian: someone was looking for part time clojure developers the other day, i don't remember who though

12:48 benzap: yeah, i saw that

12:48 seemed way out of my league, I think it was staples?

12:49 nullptr: a job that involves only one language does sound pretty lame, though :)

12:49 verma: yeah saw that too

12:49 benzap: agreed

12:49 maybe i'm just sick of my current working situation

12:49 legacy code, with years upon years woth of refactoring

12:49 verma: justin_smith, what did you think overall? a good intro? anything obvious I missed out/

12:49 mping: llasram: sorry for MIA, was busy with some other stuff

12:50 llasram: my goal is to show my Java colleague that clojure can be performant and more elegant :)

12:50 verma: mping, I would think telling them, its not java would suffice :P

12:51 mping, I've had a few people I've told this to and it has somewhat worked.

12:51 justin_smith: verma: a good intro over all - one more copy thing, calling Chestnut a boilerplate - boilerplate is a pejorative term, may be better to call it a template

12:52 verma: justin_smith, thanks! will do

12:53 justin_smith, you've earned a beer, send me btc address and I will send you beer worth of btc :D

12:53 benzap: verma: you working on an article?

12:53 verma: benzap, no I gotta go present clojure at a js meetup

12:54 benzap: oh nice

12:54 you should mention flyer.js just for kicks

12:54 i joke

12:54 verma: nice!

12:57 justin_smith: verma: it's all good, thanks anyway though

12:59 "it's all good" - why yes, I did spend some formative years in chicago

12:59 verma: justin_smith, sure, thanks for your help

12:59 there should be a list of irc -> btc

13:00 * verma goes to create a clojure app for a irc -> btc list

13:02 mping: verma: problem is that my colleague wrote the equivalent of my code and it runs on 1/5 of the time or so

13:02 although he didn't even parsed json

13:02 I just find it strange that the cpus are not maxed out

13:02 verma: mping, he loaded json without parsing?

13:03 that's a little presumptuous of me

13:03 he/she

13:03 technomancy: hello people

13:03 dopamean_: hello

13:04 technomancy: I have disabled SSL 3.0 on clojars due to http://poodlebleed.com

13:04 please let me know if you experience any connection issues

13:04 justin_smith: "poodlebleed" - what a terrible name

13:05 technomancy: justin_smith: and a terrible logo

13:05 verma: I like how these vulnerabilities get their own pages now

13:05 and domains

13:05 mping: verma: yep, since the records are simple he splits the string and other stuff

13:06 verma: mping, you can do the same can't you?

13:06 justin_smith: verma: mping: that's a terrible, and fragile way to do it

13:06 verma: justin_smith, yes yes, but we're racing for speed here I would think

13:07 mping, you can't win if the other person is taking crappy shortcuts

13:07 justin_smith: well in that case go ahead and attach a booster rocket to your backpack, and ditch the helmet, you'll be more aerodynamic that way

13:08 verma: lol

13:09 my hair would cause drag, a helmet would be nice since it'd reduce drag

13:12 justin_smith: mping: for a more clojure-friendly comparison: is each version thread safe? how hard is it to make each version thread safe if not?

13:15 mping: verma: i don't want to win I just want to do a good job

13:16 justin_smith: what do you mean thread safe? we both try to parallelize using threads

13:16 justin_smith: mping: is this up to date with what you are doing? https://gist.github.com/mping/180343e9c745c9c446d6

13:16 mping: after parsing the json into well-defined records , everything is fair game

13:16 justin_smith: yep

13:16 justin_smith: mping: by thread safe I mean won't do weird broken stuff if you run it in many threads simultaneously

13:17 mping: justin_smith: yep its thread safe

13:17 llasram: mping: I'd try separating out the I/O -- benchmark just slurping the entire dataset into memory as a vector of strings is vs processing that data

13:17 verma: mping sure :)

13:18 mping: we don't share state "normally", only through core (reducers, pmap) or java's Array.parallelStream, blockingqueue and such

13:18 justin_smith: json slurping is 8 secs

13:18 justin_smith: mping: small thing - you can use zero? instead of = 0

13:18 on line 55

13:18 mping: slurping + doing the "n-grams" thing for n = 3 is 22 secs

13:18 justin_smith: thanks!

13:19 verma: mping: line-seq sort of does what lazy-file-lines is doing

13:19 justin_smith: mping: also I have heard nothing but bad things about pmap

13:19 mping: I think reducers are preferable

13:19 mping: justin_smith: I was wondering why pmap was not reducing the time...

13:20 heheh

13:20 justin_smith: also #(map f %) is better performance wise than (partial map f) if you know you only get one arg

13:21 llasram: mping: How fast is the Java version? <5 seconds?

13:21 justin_smith: and (map #(println %)) should be (map println)

13:21 mping: the Java version takes a minute on my machine

13:21 llasram: pmap is weird, but reducers is not not ideal here because the input is IO. You can only do a parallel `fold` over vectors in clojure.core.reducers

13:22 Now I'm confused -- I thought you said your version was taking 22 seconds :-)

13:23 mping: llasram: I'm using a chunked version of pmap for parsing lines and partitioning

13:23 llasram: 22 seconds for only slurp + partitioning

13:23 total time last time was 4 or 5 mins

13:23 verma: mping, you could enable reflection warnings, and then type annotate some of the things

13:23 mping: llasram: and I'm doing r/fold for summing

13:23 llasram: mping: Ah

13:24 justin_smith: llasram: what about a map over a sequence of dereffed futures? because if it's IO bound we don't want the semi-laziness of pmap

13:24 llasram: mping: `fold` only runs in parallel if the ultimate input is a vector. It's just `reduce` over a lazy seq

13:25 mping: pmap has several problems, even when doing the chunking: (a) http://dev.clojure.org/jira/browse/CLJ-862

13:26 and (b) it maintains the order of the output even when you don't need that property, which reduces throughput

13:26 mping: llasram: so what are my alternatives?

13:27 llasram: justin_smith: Futures of what?

13:27 justin_smith: llasram: the calculation to be done on each input

13:27 making sure it is not chunked, of course...

13:27 llasram: justin_smith: That's kind of what `pmap` is, just with a bunch of juggling which tries (poorly) to keep #CPUS+2 futures running at a time

13:27 stuartsierra: transducers and the new core.async pipelines are what you want.

13:28 mping: stuartsierra: I've tried to wrap my head around transducers but I still don't got it :(

13:28 llasram: mping: Because I/O seems to be such a small portion of the overall process, I'd slurp the entire dataset into a vector then use reducers ending in a `fold`

13:28 nullptr: mping: did you watch hickey's strangeloop presentation? it's quite accessible.

13:28 llasram: The entire pipeline should run in the forkjoin pool, utilizing all available CPUs

13:29 mping: nullptr: I skimmed over it but I have to watch it again

13:30 llasram: mping: You can also use all the same "manual" threading APIs available to and used by the Java version, but leverage e.g. Clojure first-class functions to simplify the code

13:32 mping: It seems that the (apply concat) is taking ages.

13:33 I was using flatten but it seems overkill

13:34 llasram: mping: `(apply concat)` is the appropriate thing to do in the lazy-seq case. It does the most efficient thing possible given that it needs to both consume and produce lazy seqs

13:34 mping: 16s for slurping+partitioning vs 2mins for slurping+partitioning+apply-concat

13:35 I might as well skip that and handle it within the r/fold

13:38 thanks guys I'm gonna go back to the drawing board, see if I can use core.asyn and transducers

13:46 Fender: can any of you estimate the size of a vector of ~10 doubles/ints in memory?

13:46 a coarse estimate is good enough, I reckon it's 8byte*10+size(vector)

13:47 hiredman: Fender: no

13:47 Fender: as rule of thumb, unless otherwise noted, collections on the jvm box primitives

13:47 mi6x3m: clojure is there a way to preserve new lines in macro defs?

13:47 Fender: "no" as in "no coarse estimate is good enough"? :)

13:48 "no" as in "nobody cas estimate that"??

13:48 hiredman: so each int or double will also have associated object headers and such

13:48 lazybot: Fender: What are you, crazy? Of course not!

13:49 justin_smith: mi6x3m: the reading stage does not preserve newlines

13:49 mi6x3m: justin_smith: so I guess i'd have to use pprint?

13:49 or something when I output macro generated source

13:49 hiredman: Fender: no as in "8byte*10+size(vector)" is not even close

13:49 Fender: hmm

13:49 justin_smith: mi6x3m: I think there exist pretty printing rules for code - I forget if they are in pprint or elsewhere

13:50 Fender: so double the size of the Numbers

13:50 and the size of vector is approx??

13:50 lazybot: Fender: Definitely not.

13:50 Fender: hmm, slapping doesnt work in pidgin D:

13:50 hiredman: depending on what you are measuring for, another wrinkle is most jvms cache some number of boxed numbers, so like the objects in memory for the first 50 numbers will actually be the same

13:50 Fender: right, lazybot??

13:50 mi6x3m: justin_smith: yes, thanks!

13:50 lazybot: Fender: Uh, no. Why would you even ask?

13:51 Fender: so hiredman, can you give an estimate?

13:51 hiredman: and clojure also provides primitive versions of vectors, but I am not sure I would recommend using them

13:51 Fender: no

13:51 justin_smith: Fender: it would help to look at how vectors are implemented, the internals may not look like what you think http://hypirion.com/musings/understanding-persistent-vector-pt-1

13:51 SagiCZ1: when i call "lein deps" where do the dependencies end up?

13:52 Fender: I thought its like chunks of 32 references

13:52 justin_smith: SagiCZ1: ~/.m2/

13:52 Fender: plus some points left and right

13:52 pointers that is

13:52 hiredman: it isn't C though, there are no raw pointers

13:53 justin_smith: Fender: it's more like a tree - that article shows a simplified version

13:53 martinklepsch: With things like rails you benefit from improved dev tooling as soon as you upgrade, with leiningen templates this is not as straightforward — did anyoneof you think about this?

13:53 hiredman: it is all jvm objects with headers, which I am not sure, but I think the size of the object header depends on if you are on a 32bit or 64bit machine

13:53 SagiCZ1: justin_smith: thanks, found them.. it doesnt add the dependencies to classpath automatically?

13:54 justin_smith: SagiCZ1: that's what lein does - it's a tool that puts artifacts in the classpath

13:54 hiredman: Fender: there are tools for estimating the size of an object in memory, but I've never used them

13:54 SagiCZ1: strange

13:54 justin_smith: SagiCZ1: the deps command just ensures that they have been downloaded

13:54 other tasks ensure that they are downloaded, and then run clojure with those files in the classpath

13:54 hiredman: generally if I really care about the size of something, I'd use a ByteBuffer

13:55 justin_smith: via the command line (check out the ps output for lein commands - you see a huge list of jars under .m2)

13:55 SagiCZ1: justin_smith: i see.. i found my mistake.. i didnt run the leiningen REPL, just the regular REPL

13:55 justin_smith: right, like I said, lein is the tool that adds those things to the classpath

13:56 SagiCZ1: justin_smith: thank you

13:58 justin_smith: np

13:58 mi6x3m: could someone of you people check out this macro def and tell me if it's a smart idea to call it like that (with keywords but in fixed positions)

13:58 http://pastebin.com/M4MRqPg6

13:58 clojurebot: It's greek to me.

14:01 llasram: mi6x3m: It's pretty bizarre

14:01 mi6x3m: llasram: can you suggest a better layout for the args?

14:01 Fender: ok, guys, I suppose to get an estimate I will just have to spam my memory with that stuff and see how many fit

14:01 maybe I just use a record with primitives if that is possible

14:02 that should keep a lid on the size of the thing

14:02 llasram: mi6x3m: Just either usse keyword args or positional args, not args which must be indicated by both position and keyword

14:03 SagiCZ1: how would i find all functions that can be applied to a given object?

14:03 mi6x3m: llasram: this will not allow me to have a body of forms

14:04 SagiCZ1: lets say i have this incanter type called "Matrix" ..

14:04 Fender: SagiCZ1: (comp seq #(.getMethods %) class)

14:04 justin_smith: SagiCZ1: knowing all types a clojure function could take is not generally easy

14:05 Fender: that's for methods of that class, not clojure functions - maybe I misunderstand the question

14:05 SagiCZ1: justin_smith: maybe just functions that make up some protocol?

14:06 llasram: mi6x3m: Wah? Take a look at `reify`

14:06 Fender: yeah, maybe you're right

14:06 mi6x3m: llasram: excuse me?

14:06 Fender: well it will show you notifyAll() and such useful methods

14:06 justin_smith: ,(require '[clojure.reflect :as reflect])

14:06 clojurebot: nil

14:06 shem: is there any compendium of core.typed annotations for untyped libraries? it seems like a lot of wasted effort when everybody does their own.

14:06 justin_smith: ,(:bases (reflect/reflect []))

14:06 clojurebot: #{clojure.lang.APersistentVector clojure.lang.IReduce clojure.lang.IObj clojure.lang.IEditableCollection}

14:06 mi6x3m: I want to be able to pass n arguments after :include-source

14:07 justin_smith: that will tell you about interfaces it implements

14:07 llasram: mi6x3m: Well, `deftype` is a better example. It's a macro which accepts keyword arguments followed by any number of body forms

14:07 Crap, no not `deftype` either

14:07 One of those actually does accept some frikkin options :-)

14:07 mi6x3m: well how is it done? :)

14:08 llasram: Oh, they do both parse their arguments that way -- they just neither have any documented options right now

14:09 jeremyheiler: mi6x3m: basically you can to & body all the parameters, popping off keyword arg pairs until you don't find anymore. then the rest is the actual body

14:10 mi6x3m: jeremyheiler: yes, this was the previous version

14:11 llasram: mi6x3m: Then what was the problem with it?

14:11 mi6x3m: I thought it's weird of course

14:11 lemme revert

14:11 thanks a lot!

14:12 verma: in (def v 0) .. is "variable" the right term for "v"?

14:14 technomancy: verma: it's a var

14:14 "variable" is an overloaded term that we don't use

14:15 xeqi: technomancy: not a symbol?

14:16 justin_smith: xeqi: depends on what you mean by v - the argument to def, or the thing dev outputs that is named v

14:16 *def outputs

14:16 technomancy: heh, well at one point it's a symbol, at one point it's a string, at one point it's bytes on disk

14:16 llasram: So say we all

14:20 dbasch: the rose is not the same as the name of the rose

14:21 justin_smith: and The Name of the Rose is an excellent book

14:21 technomancy: (inc umberto-eco)

14:21 lazybot: ⇒ 1

14:23 mmeix: help for learning newbie again:

14:23 (trying to reimplement map)

14:24 (defn map- [fun s] (cons (fun (first s)) (lazy-seq (map- fun (rest s)))))

14:24 gets me a NullPointerException - why?

14:24 llasram: mmeix: Where's your base case?

14:24 xeqi: mmeix: what happens when s is [] ?

14:24 llasram: Gotta have a base case

14:25 dbasch: justin_smith: indeed. I read it when it came out but I was probably too young to appreciate it fully.

14:25 parenjitsu: (apply semiotics)

14:26 justin_smith: dbasch: that, Baudolino, Island of the Day Before... excellent immersion in the medieval mind

14:29 dbasch: mmeix: (defn map- [fun s] (when (seq s) (cons (fun (first s)) (lazy-seq (map- fun (rest s))))))

14:37 mmeix: ok ... thanks; I had tried (map- inc [2 3 4] and got the NullPointer - had thought since there was a "s" ([2 3 4]) this would start the sequence - wrong thinking obv.

14:38 dbasch: mmeix: that’s because at some point you get to the empty sequence, and (inc (first [])) is (inc nil)

14:39 mmeix: ah ...! thanks

14:39 "(inc lightbulbs)"

14:40 really appreciate ongoing help here :-)

14:52 brianwong: how do i get pprint to return the string it would print to *out* instead of actually printing to *out*?

14:52 with clojure.pprint

14:52 sorry if it is obvious

14:53 technomancy: brianwong: with-out-string is one way

14:53 brianwong: technomancy: thanks.

14:54 justin_smith: technomancy: not to be confused with without-string (another cantidate for the useless library)

14:54 kenrestivo: raynes: can i bug you with a conch question? https://www.refheap.com/91799

14:55 brianwong: technomancy: that worked perfectly

14:55 kenrestivo: but, the above code just hangs, it opens the output file, but appears not to actually push any input into the program.

14:55 technomancy: justin_smith: you're full of good bad ideas today

14:55 justin_smith: (defmacro without-string [& body] `(do (with-out-string ~@body) nil))

14:56 technomancy: http://www.theawl.com/2014/10/interpreting-the-animal-choices-on-the-worlds-most-popular-programming-books

15:01 muraiki: that aardwolf is pretty cool

15:01 can eat 150,000 termites in a night. wow

15:01 oh, 250,000. even better

15:02 amalloy: kenrestivo: it's super-weird that you call input-stream on each input twice, and close one of them but pass the other to this thrashcat thing

15:02 kenrestivo: amalloy: the internals of java are still mystifying to me, true.

15:03 basically this is the way i was able to guess is how you do "foo < *.bar > baz"

15:04 the globbing is done in clojure, and i get individual file streams, and i had to use this SequenceInputStream thing, and i stopped before it got into factories and helpers and such...

15:04 amalloy: kenrestivo: sure, it's a reasonable approach, but again what is the point of the 'iss binding? i'm saying all you do is open them and then close them

15:05 kenrestivo: i wasn't sure how to close them after they were done. i was under the impression that input-stream opens the file descriptor, and it has to be closed. maybe i've got that wrong?

15:05 justin_smith: kenrestivo: if it gets collected, it gets closed

15:05 amalloy: kenrestivo: you are not understanding what i am saying. you open some streams, assign them to iss. then you open some *totally different* streams, and give those to thrashcat

15:06 then you close the streams in iss

15:06 kenrestivo: oh, cool, thanks.

15:07 amalloy: other than that, what you're doing here looks broadly correct. if thrashcat is not writing its output where you want...how am i supposed to help with that? i've never heard of a program named thrashcat; maybe it's broken. try with smoething simpler, like cat

15:08 kenrestivo: it operates just like cat, so i can subsitute cat for it.

15:08 for testing.

15:08 just takes stdin, does some work, poots the results to stout, and some status messages to stderr

15:09 i'll beat on it some more. i just wanted a second opinion whether i was heading in the right direction, thanks.

15:09 amalloy: kenrestivo: if you are seeking help with conch, try to simplify your problem to the minimum necessary to reproduce it. with thrashcat, ->enumeration, and format-show-save all totally undefined, i can't guess what's wrong

15:10 kenrestivo: will do. minimum repro case would involve plain old cat.

15:11 geoffs`: If I wanted to define a function to look up an arbitrary symbol in the namespace that the function was defined in, can I just use *ns* within it to reference that namespace?

15:11 Like so: (defn get-postfix-cmd [cmd-sym]

15:11 (let [cmd-sym (symbol (str (name cmd-sym) "-cmd"))]

15:11 (cmd-sym (ns-publics *ns*))))

15:11

15:11 justin_smith: geoffs`: *ns* will get the current namespace at run time, which will be pretty much useless

15:12 geoffs`: That's what I thought

15:12 hiredman: *ns* is set at compile time, not run time

15:13 geoffs`: justin_smith: So is there a way to reference the namespace a function is defined in?

15:13 justin_smith: hiredman: but calling a form that contains a reference to *ns* will get the ns of the caller

15:13 s/form/fn

15:14 ,(defn getns [] *ns*)

15:14 clojurebot: #'sandbox/getns

15:15 justin_smith: ,(ns sandbox2)

15:15 clojurebot: nil

15:15 justin_smith: ,(sandbox/getns)

15:15 clojurebot: #<Namespace sandbox>

15:15 justin_smith: weird - that is not what it does in my repl...

15:15 ,*ns*

15:15 clojurebot: #<Namespace sandbox>

15:15 justin_smith: oh, bleh

15:16 amalloy: justin_smith: the bots would like to remind you they are not normal execution environments

15:17 dbasch: also, the bots like to be antropomorphized

15:17 anthropomorphized, my fingers

15:17 justin_smith: https://www.refheap.com/91804 this is what I was talking about

15:18 patrkris: hi folks. i've created a data_readers.clj in my src directory, and in it I have defined another reader for the inst tagged literal. but when I fire up 'lein repl' and enter a #inst literal, it complains that the function I have designated for inst literals is unbound. as soon as I (use 'namespace-of-literal-fn) it works. is this expected behavior?

15:18 amalloy: dbasch: they like to be treated like ants. formicopomorphized?

15:19 dbasch: leiningen vs the bots

15:19 justin_smith: patrkris: are you requiring the defining namespace in data_readers.clj?

15:19 patrkris: justin_smith: no i am not. just a (require 'namespace) at the beginning of the file?

15:20 justin_smith: patrkris: yeah, as long as the name of the namespace reflects its place relative to the classpath

15:20 normal clojure namespace location rules

15:21 geoffs`: justin_smith: thanks for the confirmation. I think I've got it figured out.

15:22 justin_smith: geoffs`: maybe resolve would help?

15:22 patrkris: justin_smith: hmm... if i put (require 'name.space/read-instant) before the tag map, it complains that it is not a valid data-reader map

15:23 justin_smith: that's not how require works

15:23 and as to the latter - maybe you need an injection to make sure your ns is available before that file is loaded?

15:24 it would be (require 'name.space) then you can call name.space/read-instant

15:24 patrkris: justin_smith: yeah, my mistake. i did write only the namespace, not including the symbol of the namespace. gives the mentioned error.

15:24 *symbol inside the namespace

15:25 justin_smith: total hack - {:read-instant-key (do (require 'name.space) name.space/read-instant)}

15:25 but there has to be something better than that

15:28 patrkris: justin_smith: yeah. according to http://clojure.org/reader, section Tagged Literals, it should be straight forward

15:31 justin_smith: ahh, so you don't need the ns to be loaded in side that data_readers file, but you do need to ensure it is loaded before that tag is found

15:31 so require the ns that defines that tag in any namespaces that use that literal (or load data that uses the literal)

15:32 *defines that tag reader

15:33 patrkris: justin_smith: ok, that was what I thought might be required. alright, thanks :)

15:53 kenrestivo: ok here is a minimum failing case: https://www.refheap.com/91807 . i am kind of exhausted so it wouldn't be surprising if there were something very obviously wrong in there

15:56 justin_smith: kenrestivo: so format-show-save gets a path and creates a file name in that path?

15:56 kenrestivo: yep

15:57 justin_smith: ,(clojure.java.io/file "foo" "bar" "baz")

15:57 clojurebot: #<File foo/bar/baz>

15:57 justin_smith: that may help you

15:58 this isn't relevant to your main issue, just thought I would point it out

15:58 kenrestivo: thanks, always happy to do a little bikeshedding :-)

15:58 justin_smith: so you can do :out (jio/file save-path (str name \- date))

15:59 kenrestivo: i'm more curious why it's not writing any data. if it's not something dumb i'm doing, maybe it might be a bug in conch? i dunno.

16:00 justin_smith: if you deref that future, do you get an exception?

16:03 piranha: hey! Can somebody recommend a simple configuration library? I'm using weavejester's environ right now and I like it except for the part that I can't distribute defaults with uberjar, which I really want to do.

16:05 kungi: piranha: If you find one please tell me. I am also using environ and have the same problem.

16:05 piranha: ok :)

16:06 kungi: piranha: How about distributing a start.sh script running the uberjar?

16:06 piranha: hmmm... I wonder if modifying environ so that I can supply defaults from normal file additionally to project.clj makes sense

16:06 I thought about that a bit but I really like the idea of having just one file for distribution

16:06 two files are already "many" (vs "single" uberjar)

16:06 kungi: piranha: makes perfect sense

16:07 piranha: Can't you just read a config.edn in your resources on startup and get your defaults from there?

16:07 hiredman: https://github.com/sonian/carica

16:07 piranha: I guess that's an option

16:07 justin_smith: kenrestivo: OK, I am running it locally and it is hanging

16:08 kungi: hiredman: Looks interesting

16:09 piranha: hiredman: seems like what I need

16:09 justin_smith: kenrestivo: jstack tells me that the app is waiting for the future, and the process thread is waiting on the cat process to exit

16:09 piranha: thanks

16:13 hmhm, I wonder if it's going to be easier to extend carica to read env vars or environ to read from config.edn :)

16:15 hiredman: https://github.com/sonian/carica#middleware

16:29 mgaare: piranha: to get it into environ, maybe write a lein plugin in the vein of lein-environ

16:30 piranha: well, if I want it to be in uberjar, certainly not lein plugin

16:30 I think I got it right, just need to test now... will report in few minutes :)

16:31 mgaare: right on

16:33 arohner: piranha: kungi: you could use https://github.com/circleci/lein-jarbin and export env vars from a shell script

16:33 but I wouldn't recommend that for config

16:34 kenrestivo: justin_smith: thanks! not sure where to go from here.

16:34 justin_smith: kenrestivo: I'd say maybe some tracing via tools.trace

16:34 it's suspicious that the unixprocess for cat is sitting open

16:38 piranha: http://paste.in.ua/9934/ - ended up with this for having defaults in config.edn and it works fairly well for me

16:38 so I guess I'll stick with environ, couldn't figure out how to add environ variables to carica, this seemed easier :)

16:38 sveri: Hi, I have a web application and every time I refresh it using the tools.namespace function my tests are run, any ideas why that happens? I am using midje for testing, if that is of any help.

16:40 hiredman: ~midje

16:40 clojurebot: midje is :(

16:41 technomancy: midje has some weird ideas about how to structure your code

16:42 tuft: sveri: i'm not familiar with midje, but you don't have a (run-tests) in any of your namespaces do you?

16:42 technomancy: did I say weird? I meant wrong.

16:42 sveri: tuft: no, I only started it from the command line

16:42 arohner: sveri: midje's tests are expressions, not functions

16:42 nullptr: technomancy: do you use clojure.test or something else?

16:42 arohner: sveri: so they'll run every time the code is eval'd

16:42 technomancy: nullptr: yeah, with difftest

16:42 nullptr: though I guess the thing now is humane-test-output

16:42 sveri: arohner: well, that explains it

16:43 arohner: sveri: also, yes, midje is :-(

16:43 sveri: well, I should ask clojurebot next time before I choose a lib

16:43 ~clojure.test

16:43 clojurebot: No entiendo

16:43 arohner: yeah :-(

16:43 I wrote http://blog.circleci.com/rewriting-your-test-suite-in-clojure-in-24-hours/

16:44 an almost-working version of the source code is on github, but I wouldn't recommend it unless you have > 10k LoC

16:44 sveri: yea, I see

16:45 arohner: clojure.test isn't terrible. it isn't great, but it's a decent default

16:45 technomancy: I'd rather have something slightly primitive than something overachitected

16:45 sveri: seems like there is more on the road for me :D

16:45 thanks every1

16:45 technomancy: because at least the primitive thing can be a good foundation to build on

16:46 bbloom_: +1 to arohner and technomancy's comments here

16:47 sveri: technomancy: I agree with you, however, by looking at the github page its not that obvious

16:47 which autotest lib do you use?

16:47 for clojure.test I mean?

16:48 technomancy: sveri: I just trigger tests from inside emacs

16:48 it's faster than waiting for autotest to pick them up

16:48 sveri: ok, next? :D

16:48 arohner: and works better when you have slow integration tests

16:48 bbloom_: and forces you to *think* about what code will be impacted

16:48 if you run your full test suite and get a failure in a test you didn't think to run, then you probably have discovered a design flaw in your architecture :-)

16:48 nullptr: arohner: interesting article, thanks. i see you used core.match, which also gets mixed reviews -- any thoughts on that?

16:49 arohner: nullptr: it worked in that application. I don't think I've used it since

16:49 I think just because I haven't had to solve a prolog problem recently

16:50 core.match is slightly strange because it has a lot of macro magic, and it's not all that obvious when you can use a normal expression, or a normal variable

16:51 amalloy: arohner: i was surprised to read that article: i would have thought half the ponit of using midje is its "provided" mocking, which doesn't translate to clojure.test at all

16:51 ie, for a majority of uses of midje, i would expect your transformation script to be unusable

16:52 arohner: we had a lot of problems with the several ways to mock midje, so those had already been replaced with https://github.com/circleci/bond

16:53 using 'provided' was already a "immediately fails code review" for several months before that translation ran

16:55 sveri: arohner: hm, why? That was one of the reasons I chose midje

16:56 amalloy: it's the only reason i can imagine to choose midje. but it sounds like arohner's team decided to stop using midje, and it was a gradual process

16:57 bbloom_: amalloy: you really can't imagine that people just like the cute => syntax?

16:57 arohner: sveri: 1) it was buggy 2) (trying to avoid getting dogmatic testing) the syntax complects mocking and stubbing

16:57 amalloy: bbloom_: in my model of the universe, everyone likes the same things as i do, so that sounds impossible

16:57 nullptr: i think bbloom_ is on the right track here

16:57 arohner: also, => syntax is a bad idea

16:57 bbloom_: clearly

16:58 arohner: it's not lispy, which breaks editors, and several of the translations are ambiguous

16:58 bbloom_: can't eval form to test an individual assertion == terrible

16:58 arohner: in the post I explain one of them, but there are several more

16:58 bbloom_: there are problems with clojure.test's is macro too: they create shadow assertion worlds

16:58 piranha: if I have NPE when trying to run uberjar with java -jar, what do I do to figure out what's wrong?

16:58 clojurebot: No entiendo

16:58 bbloom_: at least the `is macro defaults to just checking a damn boolean

16:58 and relegates the shadow world to error reporting

16:59 piranha: 'lein run' works like a charm, but uberjar throws NPE and I really can't figure out what's wrong there...

16:59 bbloom_: i know all about computing booleans, but in midge code, you friggin gotta know some magic alternative syntax

16:59 piranha: it also fails strangely: http://paste.in.ua/9935/#20:22

17:01 hah, I think I figured it out

17:02 sveri: ~enlive

17:02 clojurebot: enlive is for generating HTML from pure-markup templates: http://wiki.github.com/cgrand/enlive/getting-started

17:02 sveri: Just asking, is enlive suspicious for being a bad guy in a good town too?

17:03 arohner: sveri: which role do you need? enlive does several things, and there are other options, depending on what you're trying to do

17:03 I personally avoid it because the docs used to be bad

17:03 sveri: I used it for template generation on server side

17:04 *use

17:04 arohner: if it's working and you understand how to use it, it's probably fine

17:04 sveri: took me some time, but I got used to it

17:08 schmir: I'm using clojure.jdbc and I'm trying to create the inital tables inside an sqlite database. Therefor I'd like to issue multiple create table statements. but If I run them via a single jdbc/excute! only the first table is created. in python I do have executescript, is there something like that in clojure.jdbc? or am I doing something else wrong?

17:12 danneu: schmir: i use (jdbc/execute! conn [(slurp "mass-of-sql.sql")]) all the time

17:13 schmir: you sure it's not bailing on an error?

17:13 schmir: danneu: it doesn't throw

17:16 danneu: schmir: i dont remember the idiosyncrasies of when things are thrown in jdbc. but i recall dealing with silent failure

17:17 schmir: https://github.com/danneu/bulletin/blob/master/src/bulletin/db.clj#L345-L348

17:18 schmir: danneu: ok. let me test if wrapping my code in (with-db-transaction...) helps.

17:19 danneu: i dont really remember, but perhaps execute! fails silently when one of the statements in the sql string fails

17:20 schmir: i think that's why i had this code: https://github.com/danneu/bulletin/blob/master/src/bulletin/db.clj#L468-L473 - so my "reset-db!" fn prints out the created tables so i could easily see if it failed

17:21 pretty sad that i can't remember what was on my mind when i wrote code that's just 1 month old

17:22 schmir: danneu: :)

17:22 thanks for your help

17:23 danneu: schmir: i hope you figure somethin out. when i look at the jdbc api, a 'right way' never really jumps out at me

17:26 schmir: danneu: I'm now executing each sql statement one by one

17:31 danneu: schmir: also nice to have `DROP TABLE IF EXISTS <table> CASCADE;` before your creation sql

17:37 schmir: danneu: I'm starting with an empty table.

17:37 s/table/database/

17:38 TimMc: danneu: Yes, I've struggled with this as well -- I don't think JDBC provides a way to say "run this script". :-(

17:38 Much sadness.

17:38 Very split-on-semicolon.

17:43 schmir: https://stackoverflow.com/questions/10929369/how-to-execute-muliple-sql-statements-from-java says I need to call executeBatch. db-do-commands seems to do that.

17:50 TimMc, danneu: jdbc/db-do-commands works with multiple statements. but I have to pass in each statement as a separate string :(

17:52 tuft: which version of clojure has transducers?

17:53 gfredericks: 1.7.0 alpha2 or something

17:54 TimMc: schmir: Lovely.

17:57 justin_smith: schmir: sounds like a job for apply + line-seq?

17:59 schmir: justin_smith: line-seq doesn't work. splitting by semicolons may be better (until one adds a semicolon inside a comment). but basically you'd have to implement your own sql parser.

17:59 justin_smith: schmir: my assumption was acquiscing to one statement per line

17:59 which may be onerous, sure

18:06 arrdem: why not just use fnparse and the specification SQL grammar...

18:06 s/fnparse/instaparse/g

18:08 schmir: arrdem: that's overkill for my 4 create table statements...

18:08 justin_smith: in that case statement per file? which kind of sucks

18:09 arrdem: shrug. I'd think that actually using _real_ SQL would be less onerous and more general than imposing artifical constraints on the language just so you can do something "simpler".

18:15 amalloy: arrdem: remember, worse is better

18:15 * arrdem facedesk

18:16 danneu: schmir: there you go. roll a sql parser real quick.

18:16 dbasch: amalloy arrdem hence JSONx

18:16 tuft: gfredericks: thanks

18:18 danneu: schmir: since you're using clojure, you're probably retired and just rewriting your personal blog.

18:18 schmir: danneu: I'll have to finish my rosi sql parser first...

18:18 actually I'm getting paid to write clojure

18:19 (and read rosi sql...which is pretty terrible) http://www.99-bottles-of-beer.net/language-rosi-sql-1140.html

18:22 danneu: schmir: but honestly, if splitting on semicolon isn't good enough because of sql comments, then maybe the next simplest thing is to str/replace "/(--.+)\n/g" with "" before splitting on ;

18:23 though sometimes it's nice to leave gifts for your future self and let things break in a weird way

18:23 clojurebot: Cool story bro.

18:24 bostonaholic: lol clojurebot

18:24 schmir: danneu: :)

18:25 amalloy: huh. clojure.sourceforge.net redirects to clojure.org. i didn't know it used to be on sourceforge

18:26 technomancy: I thought you were an old-timer =)

18:27 hiredman: I dunno, was it ever in source forge? I mean, it was in google code

18:28 justin_smith: could be that clojure.sourceforge.net redirects for the same reason that george-w-bush.i.am does

18:29 amalloy: that doesn't even resolve :(

18:30 {blake}: I come across this pattern a lot: I have a map, and I want to fn[val] each map-entry and return a new map with the original keys mapped to the results of fn[val].

18:31 arrdem: {blake}: flatland|amalloy/useful update-vals

18:31 {blake}: I want to do it this way: "map #({(key %)(fnx[val %)}) my-map"

18:31 justin_smith: amalloy_: huh, it did the other day - used to be *.i.am went to will.i.am

18:33 {blake}: arrdem, OK, so I'm not missing something elegant that's inherent to Clojure's built-ins.

18:33 arrdem: {blake}: sadly you are not

18:33 {blake}: however given the number of different people who have re-invented that function...

18:33 {blake}: arrdem, Seems like there should be something, no? Like....

18:33 Hell, I don't know. =P

18:34 I'll crib from amalloy_ (once again).

18:34 arrdem: this is the age-old debate over whether a language should be a kernel with libraries that make it usable or whether it should include the kitchen sink..

18:35 {blake}: Is it? Maybe so. One gets used to having tremendous power in unexpected places in Clojure. Something obvious and simple--it's shocking for it to be missing!

18:35 justin_smith: any classy language should include a water fountain, a gromet factory, and a bidet

18:35 technomancy: this isn't exactly kitchen sink

18:36 arrdem: technomancy: but it can be written in terms of other language primitives, so neither is it fundimental. arguably.

18:36 technomancy: arrdem: clojure explicitly reject's scheme's fundamentalism

18:37 weavejester: Out of interest, what is this not-primitive, not-kitchen-sink?

18:37 technomancy: but yeah, I agree

18:37 {blake}: weavejester, Creating a new map from values of an old one, such that "key->value" in the old map becomes "key->(fn value)".

18:38 weavejester: {blake}: Oh, like a map-vals

18:39 I’m kinda of the opinion there should be one, if not in Clojure core than in a separate clojure.* namespace

18:39 It’s not trivial to write efficiently.

18:39 Or it takes 5 lines or so

18:40 Because where possible, you want to use transients, but some map types can’t be converted to transients

18:40 And reduce-kv is more efficient than just into {}

18:40 {blake}: It just felt like something that could be done with a zipmap.

18:41 weavejester: {blake}: keys and vals aren’t guaranteed to be ordered the same

18:41 {blake}: weavejester, Well, I always have that suspicion, which is why I never use zipmap. But it must work sometimes. =P

18:42 weavejester: {blake}: Sure, it works, IIRC, but only due to implementation details

18:42 To do it right you want something like: https://github.com/weavejester/medley/blob/master/src/medley/core.cljx#L49

18:43 And even that’s wrong for any non-hash non-array maps

18:43 Bronsa: weavejester: keys and vals are guaranteed to be ordered consistently

18:43 ,(doc keys)

18:43 clojurebot: "([map]); Returns a sequence of the map's keys, in the same order as (seq map)."

18:43 weavejester: I need to add in some additional conditions. I think one of the other utility libraries has a slightly more comprehensive version

18:43 Bronsa: ,(doc vals)

18:43 clojurebot: "([map]); Returns a sequence of the map's values, in the same order as (seq map)."

18:44 weavejester: Ohh

18:44 It never used to be

18:44 Bronsa: weavejester: it's a recent addition to the docstrings

18:44 weavejester: I guess they changed it from “implementation detail” to “defined behavior”

18:46 Bronsa: I'm still not 100% satisfied with that docstring though. What if `seq` is implemented in such a way that its ordering might change between invocations?

18:47 weavejester: Bronsa: Yeah, it implies (seq map) is consistent, but…

18:47 ewingd: I'm trying to learn clojure and am working my way through some of the problems on hackerrank. Is anyone willing to help me figure out a NullPointerException I'm getting while compiling?

18:48 weavejester: ewingd: No promises, but post the code and I’ll take a look :)

18:48 dbasch: ewingd: paste a gist / pastebin / refheap

18:48 ewingd: https://gist.github.com/ewingd/f71cf27b90bd231d179b

18:48 thanks

18:48 weavejester: Like a seq, I reserve the right to be lazy

18:48 TimMc: (realized? weavejester)

18:49 weavejester: #<weavejester: pending>

18:49 Wait

18:49 false

18:49 :)

18:50 ewingd: So, you might want to format the code in a more standard way… And there’s a def in a doseq there…

18:50 arrdem: &(Long. 0xFFF5)

18:50 gfredericks: ,0xFFF5

18:50 clojurebot: 65525

18:50 weavejester: ewingd: Though those aren’t a NPE

18:50 gfredericks: ,(Long. 0xFFF5)

18:50 clojurebot: 65525

18:51 * arrdem grabs his own repl

18:51 ewingd: When I run the code I get the correct output, but the first test run gets the NPE thrown. The rest all pass

18:52 hiredman: def defines a top level name, clojure is not like scheme

18:52 weavejester: ewingd: The first test run?

18:53 ewingd: Like clojure.test?

18:53 ewingd: weavejester: the test cases that hackerrank.com runs on the submitted code

18:54 weavejester: ewingd: Do you have a link to the question?

18:54 ewingd: weavejester: https://www.hackerrank.com/challenges/service-lane

18:54 weavejester: ewingd: If the wrong data is put in, any part of it could be nil potentially.

18:58 ewingd: You’ve mixed up N & T in the test case, which might be the problem

19:00 The definition of this problem is really hard to read

19:00 ewingd: weavejester: Yes it is.

19:01 myguidingstar: hi all, I have a noob question

19:01 can tranducers be used to alternate all reducers? if yes, is it recommended to do so?

19:03 weavejester: myguidingstar: At the risk of being wrong, I believe transducers cover the functionality of reducers. It’s a more general abstraction.

19:04 That said, I haven’t played around with them much

19:04 ewingd: Okay, I think I see what the question is asking for now

19:05 Find the minimum value between two indexes of an array

19:05 ewingd: yes, which is exactly what I am attempting to do in that solution

19:06 weavejester: ewingd: I think your problem is that the first line is “N T”, and you run (read-string “N T”) which gets you N

19:07 myguidingstar: weavejester, I 'feel' the same, and my current guess is that traducers are a re-design of reducers

19:07 weavejester: You then use N in place of T to get the number of tests

19:08 ewingd: weavejester: thanks, I'll give that a try. Is there a better approach I can take to reading the test case input lines?

19:09 weavejester: ewingd: Yeah, so, a few pointers. First, formatting - it really helps to format your code in the normal way. Makes reading it a lot easier. So that means vars-with-hyphenated-names, and no lone parentheses on their own lines.

19:10 ewingd: It might sound trivial, but programs are written once, read many times. Readability is super important.

19:10 ewingd: weavejester: I completely understand. I just haven't seen examples of normal code yet

19:11 weavejester: ewingd: Second, Clojure is a functional language, and while it doesn’t strictly enforce it, you’re encouraged to separate out the stuff that handles I/O and side effects from the functional parts of your code.

19:12 ewingd: Give me a minute and I’ll put together an example of code

19:13 ewingd: weavejester: Thanks, I was just about to ask for one.

19:13 dnolen_: myguidingstar: not sure what you are saying

19:13 cfleming: macroexpand can't come soon enough :)

19:14 cfleming: dnolen_: Hehe, ok, I'll get on it.

19:14 dnolen_: I'm working on some formatting problems right now which will make pretty printing expansions much nicer.

19:15 dnolen_: cfleming: nice, thanks for the indenting flag btw, it's great

19:16 cfleming: dnolen_: Yeah, people had been asking for that for a while, I'm embarassed to admit how long it took to implement in the end.

19:16 myguidingstar: dnolen_, are transducers the new, 'better' reducers?

19:17 amalloy: myguidingstar: broadly, yes

19:18 myguidingstar: so is it recommended that one should start with transducers instead of reducers?

19:18 amalloy: yes. don't bother with reducers; they haven't seen any major changes since their original introduction, and not much use since then either

19:18 myguidingstar: okay, thanks lot

19:19 nkozo: amalloy: transducers totally replaces reducers?

19:20 I mean, using transducers you can do everything you can do with reducers? I must study both yet :)

19:20 dnolen_: nkozo: more or less - you can use transducers w/ parallel fold anyway - so you're not missing out on anything

19:20 nkozo: great

19:20 amalloy: nkozo: to the best of my knowledge that's true. certainly in theory; in practice there may be a function or two left to implement, i dunno

19:21 but transducers are a more general concept; reducers are a special case of transducers, so to speak

19:25 weavejester: ewingd: Take a look at: https://gist.github.com/weavejester/040fa26b7fc1918f9144

19:25 ewingd: I’ve tried to minimise new concepts in that gist

19:26 ewingd: weavejester: Thanks

19:29 weavejester: ewingd: And this is the same code, just written with some more advanced features of the language: https://gist.github.com/weavejester/040fa26b7fc1918f9144

19:30 ewingd: But the basic idea is: read everything in first, get the input out of the way. Then when you just have data, you can work on it with pure functions. Finally, when you have your data, handle the output.

19:30 ewingd: weavejester: Thank you for all the effort you have put into this. It's a little overwhelming coming to a functional language from PHP and Python

19:31 weavejester: ewingd: It definitely is.

19:32 ewingd: The idea with functional languages is to try and silo side effectful code. So we get our hands dirty with I/O, then transition to using pure functions where the bulk of the logic usually happens.

19:35 ewingd: weavejester: Sounds good. I'm sure I'm going to have enough to keep me busy for a while with those samples

20:09 arnaudsj: Hi, silly question about interop with Scala. Any ideas why I see this kind of options in the repl when trying to autocomplete the Scala function TwitterUtils/createStream => TwitterUtils/createStream TwitterUtils/createStream$default$3 TwitterUtils/createStream$default$4

20:10 justin_smith: arnaudsj: that's how inner classes are specified in clojure interop

20:10 arnaudsj: In Scala the function has different arities by in Clojure it seems to only show one, with default values for argument 3 and 4 - any ideas?

20:11 arrdem: arnaudsj: it looks like Scala is generating a different class for each arity of the function.

20:12 arnaudsj: arrdem: that's what I thought, but then I get this in the REPL

20:12 => (TwitterUtils/createStream$default$3)

20:12 #<Nil$ List()>

20:13 which seems to match only this first definition: https://github.com/apache/spark/blob/master/external/twitter/src/main/scala/org/apache/spark/streaming/twitter/TwitterUtils.scala#L38-L45

20:14 arrdem: arnaudsj: I suspect you're hitting line 82 not 38

20:16 ed-g: Hello. I'm using core.async in cljs, and I don't understand what arguments to pass to alts!, or what exactly it evaluates to. I'm familiar with select() from POSIX, and I've read Rich's examples but they're too advanced for me.

20:16 arnaudsj: https://www.irccloud.com/pastebin/1b2nzcFi

20:17 I think in this case it is line 55

20:17 ed-g: Is there a basic tutorial out there somewhere? (not the one in core.async/examples git)

20:17 arrdem: arnaudsj: looks right to me.

20:17 arnaudsj: single line pastes like that are OK in channel

20:18 arnaudsj: arrdem: my question is how I can verify it is hitting the right function / arity because I want to pass a second arg (filters)

20:18 bbloom_: ed-g: generally, you want to use alt! which is macro sugar over alts!

20:18 ed-g: you only need to use alts! when you have a dynamic set of channels to read from, which is reasonably rarae

20:18 rare*

20:18 arrdem: arnaudsj: you should be able to hit that same static method with different arities and have it behave.

20:19 arnaudsj: you could always take the disassembler to the bytecode and verify what it does by hand :P

20:19 arnaudsj: because passing a second args does not seem to do the trick:

20:19 => (TwitterUtils/createStream sc ["test"])

20:19 IllegalArgumentException No matching method found: createStream clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80)

20:19 ed-g: bbloom_: thanks! yes I do have dynamic channels but I am merging them using mix / admix

20:19 arnaudsj: arrdem: because in this last case I would expect those lines to be hit: https://github.com/apache/spark/blob/master/external/twitter/src/main/scala/org/apache/spark/streaming/twitter/TwitterUtils.scala#L68-L70

20:19 arrdem: arnaudsj: is that a "raw" Java array or is that a Scala "Array" class?

20:20 arnaudsj: because that looks like a type missmatch error to me

20:20 brb FPGA build done debugging

20:20 bbloom_: ed-g: the alt! macro doc string may help https://github.com/clojure/core.async/blob/48bf181cd194a182ec303611bdfa2e54f86f3743/src/main/clojure/clojure/core/async.clj#L326-L353

20:21 arnaudsj: arrdem: well that's the part I am a little bit fuzzy here. How do I cast the argument as a Java array or Scala array?

20:21 TEttinger: scala's Array IIRC is a class, not a primitive. Java's is a primitive

20:22 arrdem: arnaudsj: http://grimoire.arrdem.com/1.6.0/clojure.core/to-array

20:22 arnaudsj: no idea about making a Scala array out of it sorry

20:23 TEttinger: also, http://grimoire.arrdem.com/1.6.0/clojure.core/make-array/

20:24 justin_smith: arnaudsj: into-array if the array needs any type other than Object

20:24 TEttinger: Scala Array should just involve a constructor...

20:24 arnaudsj: arrdem: this seems to work

20:24 (TwitterUtils/createStream sc (into-array ["test"]))

20:24 TEttinger: nice, arnaudsj!

20:24 arrdem: arnaudsj: yeah that was my guess

20:24 TEttinger: (inc justin_smith)

20:24 (inc arrdem)

20:24 aw, lazybot is down

20:25 arrdem: T_T THE KARMA NOOOOOO

20:25 :P

20:25 TEttinger: Raynes ping

20:25 arnaudsj: arrdem: thank you! There is much I still need to learn about Clojure Java/Scala Interop.

20:25 TEttinger: thank you!

20:25 TEttinger: clojure java interop is... easier

20:25 no prob!

20:25 arrdem: arnaudsj: I'm like 80% scala interop from Java isn't generally possible

20:25 ed-g: bbloom_: I'm reading it now, it just isn't clear to me what operation the example (alt! [c t] ([val ch] (foo ch val)) ... ) accomplishes. In particular, what is the difference between a chan and a port, and is the val the result of TAKE from one of the channels?

20:25 arrdem: but Clojure/Java interop is gr8

20:26 Java/Clojure interop.... is improving

20:26 TEttinger: (inc justin_smith)

20:26 (inc arrdem)

20:26 arnaudsj: arrdem: yes, I have done a few project and I had no problems with Clojure/Java interop, but with Apache Spark, which is a mix Scala/Java it is a little bit more challenging ;)

20:26 bbloom_: ed-g: a port is either the read end or write end of a channel. that feature seems to not have been finished, but it doesn't matter b/c a channel counts as a port for both ends of that channel

20:27 lazybot: ⇒ 93

20:27 ⇒ 37

20:27 TEttinger: how is arrdem's karma not higher? you make grimoire!

20:27 arrdem: this is an open question :P

20:27 TEttinger: $karma TEttinger

20:27 lazybot: TEttinger has karma 25.

20:28 bbloom_: ed-g: so as for that particular example, the square brackets of the [c t] is a vector, and teh docs say: " a vector of ports as per alts!" so let's head over to that doc string

20:28 arrdem: I think the real answer is that I tend to answer low hanging fruit questions from newbies who don't know how to inc ;P

20:28 TEttinger: same here

20:28 ed-g: bbloom_: gotcha. And it looks like I can tell which channel was selected since it can be bound to within each expression.

20:28 TEttinger: since that's all I can answer, no core.async or macro answers for me

20:28 bbloom_: ed-g: from the alts! doc string: " ports is a vector of channel endpoints, which can be either a channel to take from or a vector of [channel-to-put-to val-to-put], in any combination."

20:28 arrdem: clearly we need to patch lazybot to detect "thanks!?" messages and auto-inc

20:29 bbloom_: so that [c t] is a vector of two channels to take from

20:29 TEttinger: I just added a feature to my lazybot fork that augments its quotegrabs

20:29 you can now get all quotes by a nick dumped to pastebin

20:29 arrdem: o nice!

20:30 bbloom_: ed-g: and the [[out val]] example is a vector of "puts", where a put is just a two-item vector of channel and value to put. so [x y [[z 123]]] says take from channel x or take from channel y, or put 123 on channel z

20:30 TEttinger: mostly the quotes are grabbed when someone says something terrible, but one guy says some great stuff https://www.refheap.com/91824

20:30 bbloom_: ed-g: if you it's just a raw symbol without any vector brackets, it's the same as a single item vector put

20:31 ed-g: got it?

20:31 arrdem: TEttinger: .....

20:31 TEttinger: this is hillarious. thank you.

20:31 verma: would it be ok if I use clojure logo on my presentation?

20:31 TEttinger: verma: I think it's CC-licensed

20:32 verma: ah nice TEttinger, thanks

20:32 ed-g: bbloom_: okay this is starting to make sense. It's a nice terse syntax. I really appreciate the help.

20:32 verma: (inc TEttinger)

20:32 lazybot: ⇒ 26

20:32 TEttinger: I'll check the wiki, verma

20:34 bbloom_: ed-g: frankly, i think the syntax is a tad too terse, but the documentation is pretty clear after you see a couple examples

20:35 TEttinger: wikipedia seems to think it's public domain, verma https://commons.wikimedia.org/wiki/File:Clojure-icon.gif

20:35 technomancy: it's not public domain

20:35 TEttinger: I was wondering

20:35 technomancy: but you're probably fine as long as you're not using it for your own product

20:35 TEttinger: yeah

20:35 arrdem: Thinking of which. Grimoire 0.3.10 is getting close to ready. Feature requests/ideas welcome.

20:35 technomancy: (like a consulting course or a user group)

20:36 ed-g: bbloom_: yes with examples it's not too bad. I just wasn't finding well-documented examples with my web searches, other than that from the docstring.

20:36 TEttinger: is it's a talk about clojure, then it would make sense to use the appropriate logo. using something like a swastika to represent clojure's logo would not be appropriate

20:36 verma: TEttinger, lol

20:37 thanks technomancy, TEttinger

20:37 I am using it for a community meetup presentation

20:37 or planning to rather

20:37 justin_smith: arrdem: I go for low hanging fruit questions all the time too. I think I just waste more time on IRC than you do

20:37 TEttinger: no prob then

20:37 arrdem: justin_smith: or something

20:37 TEttinger: you might also want to grab the typed clojure logo, verma

20:37 just in case for later

20:38 verma: what is that?

20:38 TEttinger: http://typedclojure.org/images/typed-clojure-an-optional-type-system-letterbox.png http://typedclojure.org/

20:39 numberten: is there a way to specify that 'lein test' ignore an entire file?

20:39 technomancy: numberten: yeah, check out test selectors

20:39 numberten: thanks :)

20:43 arnaudsj: https://www.irccloud.com/pastebin/cyhmYtLK

20:44 justin_smith: lein has some catching up to do http://thespacereporter.com/2014/10/maven-orbiter-finds-hydrogen-layer-that-spreads-21000-miles-from-mars/

20:44 arnaudsj: This is in reference to: http://twitter4j.org/javadoc/twitter4j/FilterQuery.html

20:44 brb

20:45 justin_smith: arnaudsj: there is no actual constructer that is just a number, which constructor are you trying to use?

20:46 it tried the only one-arg constructor, which takes an array of long (that is what caused the error message you see)

20:46 arnaudsj: justin_smith: just passing a long, which should default to the follow param if I look at the definition

20:46 verma: TEttinger, thanks! will do

20:46 justin_smith: arnaudsj: there is no such constructor

20:47 long[] follow means array of long

20:47 arnaudsj: FilterQuery(long[] follow)?

20:47 justin_smith: right, that means array

20:47 arnaudsj: ok my bad

20:47 TEttinger: verma: a possible big advantage of typed clojure is in teaching newbies (because it gives better error messages), especially clojure newbies who are used to statically typed languages already.

20:47 justin_smith: (FilterQuery. (into-array Long [123123]))

20:49 ed-g: well that code managed to lock up my browser

20:53 is it okay to run (go (loop [] (alt! ...) (recur)) in a browser or is that a guaranteed denial of service? I was hoping the thread of control would return to the browser when cljs was stopped on the channels but maybe not.

20:54 bbloom_: ed-g: the thread of control is returned to the browser, but if you write a truly blocking loop w/o any waiting channel ops in it, it will loop for ever and the browser is still cooperatively threaded

20:54 arnaudsj: justin_smith: hmmm, still no go => (FilterQuery. (into-array Long [123123]))

20:54 ClassCastException [Ljava.lang.Long; cannot be cast to [J

20:54 bbloom_: ed-g: is your alt! writing to any sliding or dropping channels? or is there a :defualt clause?

20:54 ed-g: bbloom_: gotcha

20:55 bbloom_: ed-g: chances are you're just writing repeatedly forever in to some place that won't ever block

20:55 ed-g: what's in your alt?

20:55 ed-g: bbloom_: I am only reading from channels ( cljs-http get operations) but they are also merged in an mix which may change things

20:55 TEttinger: ,(into-array long [123123])

20:55 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.core$long cannot be cast to java.lang.Class>

20:56 ed-g: bbloom_: large. is there a pastebin for this channel?

20:56 TEttinger: ,(long-array [123123])

20:56 clojurebot: #<long[] [J@e5e57b>

20:56 bbloom_: ~paste

20:56 clojurebot: paste is https://refheap.com/

20:57 TEttinger: arnaudsj: [J is a primitive array of longs. [Ljava.lang.Long; is the JVM internal code for an array of objects, not primitives, of class java.lang.Long

20:58 arnaudsj: TEttinger: thank you, I needed to understand the difference between (into-array [123]) and (long-array [123])

20:58 TEttinger: arrays are a little black-magic in clojure. there are some good guide out there

21:00 ed-g: alt! block https://www.refheap.com/91826

21:01 TEttinger: http://www.learningclojure.com/2010/09/macros-and-type-hints-metadata-and.html arnaudsj

21:01 also, arnaudsj: http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays.html

21:04 arrdem: TEttinger: Grimoire takes PRs (and soon articles) for community docstrings :P

21:05 TEttinger: arrdem: what was that in reference to?

21:06 arrdem: TEttinger: you just dug up a bunch of crap about arrays that could go in the notes while someone here still remembers it

21:06 TEttinger: oh ok

21:06 uh, should I fork grimoire?

21:07 seems a bit convoluted

21:07 arrdem: TEttinger: just go to into-array's page and click the "edit" link on the community docstring :P

21:07 TEttinger: oh phew

21:07 arrdem: TEttinger: that does all the forking/merging crap for you.

21:09 oh balls I totally broke my edit links

21:09 whelp

21:10 TEttinger: edit link 404s yeah

21:10 arrdem: guess I'm rushing out a half baked 0.3.10 tonight then

21:10 TEttinger: https://github.com/clojure-grimoire/grimoire/edit/develop/resources/store/org.clojure/clojure/1.6.0/clojure.core/into-array/extended-docstring.md

21:11 TEttinger: You need to fork this repository to propose changes.

21:11 I need to eat dinner to propose changes.

21:11 arrdem: lol

21:16 ed-g: okay what's happening is that the stops-data-chan gives data from my page once using cljs-http.client/get, then it gives me an infinite number of nil's.

21:19 nullptr: ed-g: this looks a bit suspicious (def stops-data-chan (http/get stops-url {:channel stops-data-chan}))

21:21 ed-g: nullptr: it does, doesn't it? I'll rewrite as a let and without self-reference

21:23 bbloom_: ed-g: a nil means the channel is closed

21:23 ed-g: bbloom_: I've heard that, but why then is it still returning data in alt! ?

21:24 bbloom_: ed-g: it's not returning data, it's reported that it's closed

21:25 TEttinger: arrdem: do I need to fork the repo?

21:25 ed-g: bbloom_: oops I should rephrase that. why is alt! executing blocks for closed channels?

21:25 bbloom_: ed-g: it does exactly the same thing as trying to read from a closed channel outside of an alt!

21:26 ed-g: there's no other way to tell if a channel is closed other than to attempt to read from it and to get a nil

21:28 ed-g: bbloom_: so I should be careful never to close channels which may be read in a loop? or is there some way to detect if all channels being selected upon in an alt! block have been closed in which case I can exit my loop?

21:29 bbloom_: ed-g: you can just exit the loop if one of your inputs has been closed...

21:29 ed-g: you can detect that by examining the value that was given to you

21:29 ed-g: if it's nil, the channel was closed, and now your alt! is no longer sensible to re-enter

21:29 if you use alts! and had a dynamic set of channels, you could remove the closed channel from the set, but that's almost always not necessary

21:29 ed-g: bbloom_: okay that makes sense. What if I want to read data from all the channels until they are all closed? I think I'm still stuck in a posix select() mentality.

21:30 bbloom_: it really depends on your use case

21:30 nullptr: in the one you presented, you could have separate go blocks to avoid having to maintain a dynamic list of non-closed chans

21:31 bbloom_: ed-g: but you can just use the merge function

21:31 ed-g: https://github.com/clojure/core.async/blob/master/src/main/clojure/cljs/core/async.cljs#L674

21:31 ed-g: nullptr: oh that would be great! I didn't know that was possible.

21:32 bbloom_: ed-g: you do know you don't need to use alt! to read from a channel, right?

21:32 ed-g: the two major differences between a typical unix select loop and core.async usages are 1) first class channels and 2) threads are cheap

21:32 ed-g: bbloom_: I had considered using merge but didn't want to tag each result with it's type. although that might be a more flexible way to go.

21:33 bbloom_: ed-g: what do you mean tag results?

21:33 ed-g: you want to know what channels they came from?

21:33 just map over the channels to "tag" them: https://github.com/clojure/core.async/blob/master/src/main/clojure/cljs/core/async.cljs#L638

21:33 then merge the mapped channels

21:33 you gotta start thinking higher level than C :-)

21:34 nullptr: map without transducers?! what is this, early 2014?

21:35 ed-g: bbloom_: yes I need to know the source channel, since results from various JSON url's are handled differently.

21:35 nullptr: i think separate go loops will make this much simpler for your use case

21:35 bbloom_: ed-g: yeah, you can trivially make multiple go loops

21:36 ed-g: you may also want to watch Rob Pike's talk about Go: https://talks.golang.org/2012/concurrency.slide#1

21:36 ed-g: nullptr: it certainly looks like it would be much easier. I assumed that was not available in javascript since it was single threaded.

21:36 bbloom_: ed-g: and part 2 http://blog.golang.org/advanced-go-concurrency-patterns

21:36 ed-g: half the entire point of core.async is to give you multiple threads of control cheaply

21:36 nullptr: ed-g: yes, it does feel a bit weird but you'll get used to it

21:36 ed-g: bbloom_: cool, that would be a great starting place.

21:36 bbloom_: ed-g: you can easily have thousands of running go loops

21:37 ed-g: bbloom_: I gathered that, but I assumed all loops had to be running lexically under one go macro.

21:38 bbloom_: ed-g: no, all of the puts and takes have to be lexically within any go macro

21:38 ed-g: okay time to do some homework.

21:38 (inc bbloom_)

21:38 lazybot: ⇒ 2

21:38 bbloom_: ed-g: each go creates a new thread of control

21:38 ed-g: (inc nullptr )

21:38 lazybot: ⇒ 1

21:38 bbloom_: aw, can i get my inc over at bbloom without the udnerscore? :-)

21:38 ed-g: (inc bbloom)

21:38 lazybot: ⇒ 46

21:39 bbloom_: cheers, good luck

21:42 amalloy: (dec bbloom_) ; can't have counterfeit karma floating around

21:42 lazybot: ⇒ 1

21:42 bbloom_: (inc amalloy_)

21:42 lazybot: ⇒ 1

21:42 bbloom_: (inc amalloy_)

21:42 lazybot: ⇒ 2

21:42 bbloom_: $karma bbloom_

21:42 lazybot: bbloom_ has karma 1.

21:42 bbloom_: $karma bbloom____

21:42 lazybot: bbloom____ has karma 0.

21:42 bbloom_: amalloy: i'm still up 1

21:54 TimMc: (inc _______)

21:54 lazybot: ⇒ 1

21:59 arrdem: TEttinger: if you have to fork then I've got the workflow wrong

22:00 TEttinger: in the past you've just been able to click the "edit" link and go

22:00 TEttinger: it's not a huge surprise that stuff is broken... major internal transitions are underway

22:00 TEttinger: heh, ok

22:00 arrdem: but nonetheless it should be fixed.

22:00 /should get fixed

22:01 the intent is that this is a zero fork workflow. if I can't get that working then I'll be abandoning the current data representation

22:02 TEttinger: D:

22:09 Bruce_Wayne: hey guys

22:09 anyone know datomic?

22:09 bbloom_: ~ask

22:09 clojurebot: The Ask To Ask protocol wastes more bandwidth than any version of the Ask protocol, so just ask your question.

22:10 Bruce_Wayne: how do you write: {:db/id #db/id[:db.part/user]

22:10 without the #

22:11 arrdem: &(/ 1300 0.78)

22:11 lazybot: ⇒ 1666.6666666666665

22:13 Bruce_Wayne: so no datomic knowledge out there?

22:14 arrdem: #clojure is not paid support, no

22:14 bbloom_: Bruce_Wayne: why can't you use the tagged literal? (that's what that # thing is called in that context)

22:15 Bruce_Wayne: and i think this is the fn you want: http://docs.datomic.com/clojure/index.html#datomic.api/tempid

22:15 Bruce_Wayne: aparently No reader function for tag db/id

22:16 bbloom_: Bruce_Wayne: well you should have told us the error message you were getting, b/c lots of folks can help w/ that w/o datomic knowledge

22:16 Bruce_Wayne: basically clojure is saying how do you read that in a map

22:16 bbloom_: you don't need the tempid function

22:16 Bruce_Wayne: what do I need

22:16 ?

22:17 bbloom_: Bruce_Wayne: a quick google suggests that the tempid function is recommended: https://github.com/Datomic/day-of-datomic/blob/master/samples/literals_vs_code.clj

22:17 and the same search results yield https://groups.google.com/forum/#!topic/datomic/Fi7iXps2npw

22:59 cddr: What's the best approach for depending on home brew libraries that aren't yet ready to push to clojars? I know about lein local-install but is there anything else I should know about?

23:24 justin_smith: cddr: lein install

23:24 maybe that's what you meant by local-install

23:29 dopamean_: i was in here the other day asking about what to do for a situation in a library im writing where there is a failed http request made using clj-http

23:29 and i said originally that since my function returns a map if successful i wanted to return some sort of failure map

23:29 but was discouraged from doing that and i dont recall why. can someone explain why that is a less than attractive option?

23:31 justin_smith: what does clj-http return on failure?

23:32 pw_: (defprotocol IFoo (foo [this & args])) doesn't work, does defprotocol support fn-like destructuring?

23:32 arrdem: pw_: no

23:32 pw_: arrdem: ok, thanks

23:32 jeremyheiler: dopamean_: it's throwing an exception, right?

23:33 dopamean_: currently thats what i have it doing. i use try to make the request and then catch the exception and throw my own if ther eis a problem

23:33 which doesnt work all the time because its possible to get a 200 response but with nothing in the body because of the api this thing is working with

23:33 so i was hoping to be able to sort of handle for all types of situations in one way

23:35 jeremyheiler: dopamean_: you can.

23:36 specifcy `:throw-excpetions false` in the opts map

23:37 dopamean_: hmm. iirc technomancy thought it might not be a good idea to return a map with an error key and message. i think he described just throwing the exception as "more civilised"

23:39 jeremyheiler: heh ok. just do what you want lol

23:39 dopamean_: i want to return the map regardless of what happened to the http request. i just wanted to be clear on why some people thought it wasnt a good idea

23:40 ill do it anyway

23:40 jeremyheiler: i don't know. i think it's perferctly fine.

23:40 dopamean_: cool

23:40 thanks.

23:41 jeremyheiler: np. if it helps, that's what i do.

23:41 at least when i need to handle the responses more effectively

23:41 err.. i guess differently

23:41 dopamean_: i knew what you meant. i write a lot of ruby for work and its something i do somewhat frequently there.

23:42 so it seemed natural here

23:42 jeremyheiler: cool

Logging service provided by n01se.net