#clojure log - May 13 2014

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

0:11 muhuk: ambrosebs: there's 247 lines of code there. If you sum up the code I have read in my entire life, it wouldn't come close to that number.

0:13 ambrosebs: the problem is line 120

0:13 it's obviously a symbol, but the reader does something crazy to it

0:13 I couldn't reproduce with a smaller vector

0:14 look for NonEmptySeqable

0:14 could someone confirm for me?

0:14 just dump that vector into your REPL and run the interactions at the bottom

0:15 I'm running 1.5.1

0:15 amalloy: ambrosebs: you have an errant ` at the end of line 116

0:15 ambrosebs: amalloy: <3

0:16 amalloy: the seq/concat/list stuff is the telltale sign that syntax-quote is involved; after that you can just search for `

0:17 ambrosebs: amalloy: thanks

0:17 git blame told me I just committed it.

0:17 ouch

0:23 _oggy: what's the standard clojure way of delaying an evaluation of an expression? i.e., the counterpart of ML's "fn () => exp"?

0:25 TimMc: amalloy: Sorry to hear about the Geni team. Anything you can share?

0:25 amalloy: TimMc: oh, this was months ago. back in october

0:25 catern: _oggy: it might be (delay expr)

0:25 amalloy: er, november

0:25 catern: but I'm new

0:25 TimMc: Oh huh.

0:25 amalloy: i'm at factual now, Raynes is at scopely. ninjudd is trying to do some startup

0:26 Raynes: God help us all amirite amirite

0:26 TimMc: We is all doin' fine tho :3

0:26 amalloy: lancepantz is rolling around on a giant pile of money, according to Raynes

0:26 muhuk: _oggy: catern is right. (def d (delay expr)) then @d to execute

0:26 TimMc: Oh, LinkedIn tells me what happened.

0:26 muhuk: _oggy: wrapping the expression in an fn also works

0:27 TimMc: ...no it doesn't, never mind.

0:27 _oggy: catern, muhuk: thanks!

0:27 muhuk: _oggy: there's also agent & future with concurrency

0:27 yw

0:28 _oggy: muhuk: i'm not looking at concurrency

0:29 i essentially want to build a procedure f with 3 arguments, create "(f a b c)" and then call it later

0:30 muhuk: _oggy: got it. delay then. Here's the implementation: https://github.com/clojure/clojure/blob/028af0e0b271aa558ea44780e5d951f4932c7842/src/clj/clojure/core.clj#L705

0:31 catern: muhuk: out of curiousity did you just search for that? or get a link to it some other way?

0:31 _oggy: muhuk: does this always cache the result? since i might be using global state in there

0:32 muhuk: catern: I keep this page open all times http://clojure.github.io/clojure/clojure.core-api.html :)

0:32 _oggy: i.e. i don't want caching :)

0:32 catern: muhuk: like any good clojurist!

0:33 muhuk: _oggy: that's why I mentioned agent & future, they're all IDeref's

0:33 _oggy: why don't you want memoizing? Will you defer something with side effects?

0:34 _oggy: muhuk: yes

0:34 muhuk: catern: yes, a.k.a noobs ;)

0:35 _oggy: how about wrapping with fn? I'd try that before creating a delay-like macro.

0:35 _oggy: also, if side-effects are involved, perhaps you can find and elegant solution with a lazy-seq instead of a callable.

0:36 _oggy: muhuk: actually that's probably what i want. i failed to realize i can do just fn [] - noob :)

0:37 i was thinking along the lines of "what arguments do i give to fn" (in ML you'd commonly give the unit), but i don't need to give any

0:39 catern: _oggy: are you coming from Ocaml?

0:39 _oggy: no, SML and haskell

0:40 catern: ah, my experience is all with SML as well :)

0:47 muhuk: I'm trying to create a checker (Midje) and use it like this: (make-foo) => (implements-protocols A B C)

0:49 catern: in that case, you could do (partial implements-protocols A B C)

0:49 muhuk: I tried this: (defn implements-protocols [& protocols] (checker [obj] (let [t (type obj)] (every? #(extends? % t) protocols)))))

0:49 catern: I'm trying to avoid partial

0:49 catern: that's why implements-protocols is an fn that returns a checker (not a defchecker)

0:50 catern: well, okay

0:50 muhuk: I see now that my every? fails, it seems Midje does what I expect.

0:51 (added true at the tail of checker, tests pass)

0:51 ah, sorry I'm calling type on the left hand side like an idiot.

0:56 kenrestivo: if i wanted a clojurey nosql database that might have high write loads (i.e. not datomic), what would be good?

0:59 for running on a vps with limited ram too (ruling out dbms's that require keeping everything in ram)

1:53 rshetty: Hey

1:54 I was going through the concepts related to Functional Programming, Mainly Monoids and Monads. Could someone point me to some references which delineate the concepts such as Monads and its usage. Thanks

1:56 And also some of the commonly used Monads in Clojure

1:56 amalloy: nobody outside of haskell really uses monads formally

2:00 beamso: scala?

2:00 clojurebot: {((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}

2:04 beamso: i forgot about that clojurebot functionality

2:04 c?

2:04 :(

2:18 sm0ke: is it possible to import a clojure record in a java class without :aot ?

2:27 muhuk: sm0ke: when you defrecord, it compiles, no?

2:28 rshetty: I'm no expert on monads etc. But I think it's more likely to get an answer if you ask a more specific question.

2:29 sm0ke: muhuk: yes but i said without :aot

2:29 rshetty: muhuk: How to get started to understand monads ? :)

2:30 ddellacosta: rshetty: why do you care about learning monads? If you really want to understand them, I would suggest #1 go hang out in #haskell, and #2 read this: http://dev.stephendiehl.com/hask/#monads

2:30 rshetty: which is to say, you're not going to get much value in learning about monads until you understand what problems they are good at solving--and these problems are not nearly as pressing in Clojure as they are in Haskell.

2:32 rshetty: ddellacosta: I do hangout on #hashkell and I have asked similar question waiting for the answer. Yeah, I want to understand their usage and what makes them special and mysterious

2:32 ddellacosta: So are you telling that monads are not used so much in #clojure ?

2:33 ddellacosta: rshetty: no, as amalloy was saying

2:33 muhuk: rshetty: I've found this video to be a very good intro http://vimeo.com/20717301

2:34 rshetty: muhuk: Thanks Let me check

2:34 muhuk: rshetty: also there are really good articles on monads, implementation of monads, monads in clojure here: clojure.net

2:35 sm0ke: what do you mean without :aot? Are you creating your record without calling defrecord?

2:35 ddellacosta: I still don't understand why people are so obsessed with monads, but I'll go away before I start grumbling too much about how you should learn how Haskell's type system works first before you should give a crap about them...

2:35 * ddellacosta grumbles as he wanders off into the distance

2:35 amalloy: fwiw, rshetty, even if the articles you've just been sent are great, they probably won't help you that much. nobody gets it on the first try; the fifth time you read a monad article it finally clicks, and then you share it with everyone else, thinking it was this one great article. really it was all the articles added together that finally clicked in your brain

2:36 the one that did it for me was http://cdsmith.wordpress.com/2012/04/18/why-do-monads-matter/

2:37 rshetty: ammalloy: Thanks Let me check

2:38 muhuk: amalloy: LOL, I can't help but agree with you.

3:21 sm0ke: How do i create a IFn in java class?

3:21 i want simple function, like #(my.org.Class. %) kind of function

3:25 muhuk: sm0ke: there's a new Java API in 1.6

3:25 sm0ke: see changes.md in source

3:26 sm0ke: no i want to be able to support 1.4+

3:26 beamso: sm0ke: muhuk means that clojure v1.6 has a new java api.

3:28 muhuk: sm0ke: then you need to implement clojure.lang.IFn I suppose. Seems like too many methods to implement just to throw ArityException.

3:29 maybe there's an easier way

3:29 pyrtsa: clojure.lang.AFn?

3:30 muhuk: ha!

3:30 pyrtsa: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFn.java

3:30 Glenjamin: is there some sort of Traits type thing so you can implement IFn without extending AF

3:31 *AFn

3:31 sm0ke: i need to implement that?

3:32 i dont think that is required, i can use Compile.load on a string too?

3:32 muhuk: Glenjamin: why would you need that? You can just extend AFn and implement the relevbant arities.

3:32 Glenjamin: muhuk: because perhaps you already extend something else?

3:33 class MyFancyMap extends java.util.HashMap { or whatever

3:33 muhuk: Glenjamin: right. I would accept that as a dependency then.

3:33 Glenjamin: if you want to implement a few large interfaces, you'll have to write a load of code

3:34 muhuk: Glenjamin: welcome to the Java land.

3:34 Glenjamin: not in java 8 apparently :)

3:35 but yeah, clojure does enough code generation already that it could help with this scenario - although it wouldn't want to be seen to encourage nested class inheritance i'm sure

3:37 pyrtsa: I think the most important question here is, why do you want your Java class to implement IFn? Can you not just wrap it with something like #(.myInvoke my-instance %)?

3:37 Glenjamin: (inc pyrtsa)

3:37 lazybot: ⇒ 5

3:38 sm0ke: pyrtsa: no, i will have a cyclic dep

3:38 between java and clojure

3:38 pyrtsa: Clojure itself builds its data structures quite tightly coupled around AFn: PersistentHashMap extends APersistentMap extends AFn, and the rest are interfaces.

3:39 sm0ke: i can go though the Iterable in java class and `map` it but then i will lose laziness

3:39 Glenjamin: sm0ke: sounds like you need to implement clojure.lang.Seqable

3:39 sm0ke: i am not sure if this will help http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Iterables.html

3:39 looks pretty interesting

3:40 Glenjamin: ugh

3:40 Glenjamin: can you describe what you're trying to acheive in a bit of a wider picture?

3:40 sm0ke: there is a transform there

3:41 Glenjamin: i have a lazy seq from clojure coming into my java fucntion, but i want to transform it a bit in java function

3:41 before returining it back

3:41 makes sense?

3:42 Glenjamin: yes

3:42 well, no

3:42 why not just do it in clojure

3:42 sm0ke: the transformation is like converting it to a Java Class, but i would be compiling java after clojure

3:42 so thats why i can not do it in clojure

3:42 now?

3:44 Glenjamin: sorry, i didn't follow that last bit

3:44 sm0ke: hurm

3:44 ugh how come i never though this

3:45 sorry i think i can refer java classes from clojure, it would be cyclic but should work

3:47 but still that google library looks interesting

4:04 adulteratedjedi: .

4:09 maxthour1ie: what does this section of numeric tower do? https://github.com/clojure/math.numeric-tower/blob/master/src/main/clojure/clojure/math/numeric_tower.clj#L57

4:10 maxthoursie: shouldn't (first [-' -]) always return -' ?

4:11 i.e. what's the relevant difference between 1.2.x. and 1.3 here

4:15 amalloy: maxthoursie: 1.2.x and below didn't allow ' in symbols

4:15 so it parsed as [- '-]

4:16 maxthoursie: oh, nasty

4:16 ambrosebs: haha

4:16 maxthoursie: feel's like one of those html tricks

4:16 ambrosebs: that's insane

4:19 maxthoursie: it could deserve a comment in that piece of code

4:23 amalloy: ambrosebs: i think i was the one who suggested using that as a 1.3 detector. could be a false memory, though, it's a bit fuzzy

4:24 ambrosebs: amalloy: it's awesome.

4:24 amalloy: if not, i at least helped popularize knowledge of it to library authors :P

4:24 ambrosebs: thank god 1.2 is ancient history

4:28 maxthoursie: shows the need for something like feature expressions

4:55 ddellacosta: I no longer know what it is appropriate to test

4:55 * ddellacosta *sobs*

5:46 turbopape: Hi, Any Idea why C-c C-S (go to source) in emacs / cider would return source not found ?

6:03 sm0ke: may be code is :aot'd turbopape

6:03 and :omit-source true is set

6:04 turbopape: nope, It isn't... think it is something I messed up with my setup...

6:04 sm0ke: or may be your setup is faulty

6:04 :D

6:04 jar -tvf my.jar | grep *.clj

6:04 try this

6:04 to be sure

6:05 turbopape: I'm not even at the "jar " stage,

6:05 it is a project I'm editing...

6:06 I'm trying to see "my fns" sources :)

6:28 sm0ke: what more idiomatic for empty/nil check? (seq x) or (not-emtpy x)

6:28 martinklepsch: sm0ke I think (seq x)

6:29 at least that's what I've been told

6:30 sm0ke: hurm, not-empty is useful if you want to preserve collection as is i guess

6:30 ,(seq [1 2 3])

6:30 clojurebot: (1 2 3)

6:30 sm0ke: ,(not-empty [1 2 3])

6:30 clojurebot: [1 2 3]

6:30 pyrtsa: I too think it's (seq x), but I would prefer (if-not (empty? x) ...) over that.

6:31 sm0ke: yea but (if-let [y (not-empty x)] ..)

6:31 is very useful imo

6:31 pyrtsa: (not-empty xs) is for similar uses as (empty xs).

6:32 sm0ke: Yes, but you weren't asking that.

6:32 sm0ke: :P

6:32 pyrtsa: empty/nil check is different from if-let.

6:32 sm0ke: ok then whats ideal inside if-let ?

6:33 seq or not-empty?

6:33 pyrtsa: For if-let, I'd use not-empty.

6:33 sm0ke: why is that?

6:33 you just like long names? dont you

6:33 :D

6:34 pyrtsa: Because I might know that the input must be a vector, thus random-accessible, and I might want to use that fact inside the if-let.

6:34 The result of (seq xs) won't have random access.

6:34 And no, I don't particularly like long names.

6:34 sm0ke: (inc pyrtsa)

6:34 lazybot: ⇒ 6

6:35 sm0ke: 50% of your karma has come by me i think

6:35 pyrtsa: Thanks! :)

6:52 clgv: $source not-empty

6:52 lazybot: not-empty is http://is.gd/2jyOzN

6:52 clgv: pyrtsa: sm0ke: have a look^^

6:53 `not-empty` is a trojan `seq` :P

6:59 sm0ke: haha funny

7:00 Bala_: Hello

7:00 sm0ke: and why isnt he using `if`

7:00 whats with then when

7:00 with the*

7:01 clgv: sm0ke: it is idiomatic use `when` in case you have no "else" clause

7:02 sm0ke: oh didnt know that, makes sense

7:02 you wont be searching for else cluse

7:04 clgv: sm0ke: and you do not need a (do ...) within the when clause

7:07 sm0ke: yea that i know

7:08 martinklepsch: is there a function to go into a namespace in the repl? ideally it'd also supply all the :as mappings from the ns binding

7:09 sm0ke: (ns name.space) doesnt work?

7:10 clgv: martinklepsch: (require 'my.ns) (in-ns 'my.ns)

7:10 the first one to make sure the namespace is loaded

7:12 sm0ke: how is it different from (ns my.ns)? clgv

7:12 clgv: sm0ke: that creates a new namespace

7:13 sm0ke: if you look at editor-REPL-integration code they use in-ns

7:13 sm0ke: ok

7:53 gfredericks: &(- 1400000000000 (System/currentTimeMillis))

7:53 lazybot: ⇒ 18142727

8:01 clgv: ,(/ 18142727 1000 3600 24)

8:01 clojurebot: 18142727/86400000

8:01 clgv: ,(/ 18142727 1000 3600 24.0)

8:01 clojurebot: 0.20998526620370372

8:01 clgv: ,(/ 18142727 1000 3600)

8:01 clojurebot: 18142727/3600000

8:01 clgv: ,(/ 18142727 1000 3600.0)

8:01 clojurebot: 5.0396463888888885

8:01 clgv: so that's in 5 hours ;)

8:04 gfredericks: ,(let [t (- 1400000000000 (System/currentTimeMillis))] (apply format "%02d:%02d:%02d.%03d" (map (fn [[q m]] (mod (quot t q) m)) [[3600000 100000000] [60000 60] [1000 60] [1 1000]])))

8:04 clojurebot: "04:53:48.833"

8:10 gfredericks: why have I not read about this in the news? there must be some sort of media coverup

8:10 clgv: :D

8:10 pyrtsa: https://news.ycombinator.com/item?id=7736739

8:13 Morgawr: how can I conj an element inside an atom holding a [] and know at which position in the vector the element was put?

8:14 if I check before adding and then atomically swap or if I check after atomically swapping I have no guarantee that some other thread didn't conj too

8:14 should I use refs?

8:14 gyim: you can use reset!

8:14 Morgawr: that sound like a bad idea :|

8:14 gyim: why?

8:14 clojurebot: why is startup slow is busy compiling the `for` macroexpansion

8:14 gyim: oh, sorry

8:14 pyrtsa: Morgawr: The result of swap! will be the new vector. It's length minus one is the position.

8:14 gyim: i meant swap!

8:14 Morgawr: pyrtsa: ah, right

8:15 pyrtsa: good point, thanks! :)

8:15 gyim: so you can pass a function to swap! that does all of this

8:15 pyrtsa: There are times, though, when you need to know after the swap! what the value had been right before the call. Then the only help in clojure.core is compare-and-set!, and a hand-written retry loop.

8:16 Morgawr: pyrtsa: yeah, not a problem in this case

9:06 is there an easy implementation/library to use sqlite with clojure?

9:06 jeremyheiler: Morgawr: like jdbc?

9:07 https://github.com/clojure/java.jdbc

9:07 Morgawr: jeremyheiler: I never used jdbc so I don't know, is that the java API for databases?

9:07 jeremyheiler: it is, and that's the clojure wrapper lib.

9:07 sqlite is one of the examples

9:08 Morgawr: jeremyheiler: I see, I'll give a look at it, I've also seen this http://sqlkorma.com/docs

9:09 jeremyheiler: that's built on top of java.jdbc

9:10 it servers as an abstraction for sql, where jdbc is about connecting and using the sql. i use honeysql for generating the sql.

9:10 Morgawr: jeremyheiler: ah, cool, I'll check this stuff out then, thanks

9:11 jeremyheiler: np!

9:12 mdrogalis: If anybody here is using Dire, I have a new technique for runtime aspect injection you might want to check out: http://michaeldrogalis.tumblr.com/post/85617979546/getting-a-grip-on-the-small-things

9:16 emil0r: does anyone know of a clojure migration library that can handle data migrations?

9:17 ssideris: emil0r: https://github.com/macourtney/drift

9:17 jeremyheiler: emil0r: also https://github.com/weavejester/ragtime

9:17 ssideris: Morgawr: I personally think that https://github.com/jkk/honeysql is a better approach to korma

9:19 mdrogalis: Yeah, agreed, ssideris.

9:19 clgv: mdrogalis: interesting. let's see what you got. unfortunately I did not use that lib much lately

9:21 emil0r: thanks

9:21 mdrogalis: clgv: Finally found the last piece of the puzzle I wanted to make aspects not-so-scary.

9:23 clgv: mdrogalis: I liked the lib earlier on but stopped using it because it did not catch the Exceptions properly since it was hard to figure out the exceptionclass at the level where I wanted to catch it ;)

9:24 mdrogalis: clgv: Yeah, that's another thing to be worked on at some point. No time right now though. D:

9:32 martinklepsch: I'm implementing a system that parses and indexes xml snippets that are read from disk. I now want to make it fast to re-indexing everything could be done quickly. I use a queue with multiple worker processes but I fail to better understand the performance implications of my code and how to properly make use of the resources I have available.

9:33 mdeboard: martinklepsch: I have that problem a lot

9:33 martinklepsch: mdeboard, what do you tend to do then?

9:33 mdeboard: "I fail to better understand the performance implications of my code and how to properly make use of the resources I have available"

9:33 In fact that's just my steady state

9:33 martinklepsch: Read, ask questions.

9:34 martinklepsch: mdeboard, just out of curiousity, do you have formal CS education?

9:34 mdeboard: martinklepsch: I do not

9:34 If you want to better understand the resources you have available I can recommend a very good book

9:35 Systems Performance by Brendan Gregg

9:35 martinklepsch: mdeboard, I neither

9:38 mdeboard: I think pretty much every programmer ever experiences a failure to better understand the performance implications of their code and how to properly make use of the resources they have available

9:38 So don't feel bad

9:38 BTW that is really just an amazing accidental quote. :P

9:41 martinklepsch: Yeah, I don't feel bad about it, just wondering how to change that :)

9:42 mdeboard, what quote?

9:43 mdeboard: "I fail to better understand the performance implications of my code and how to properly make use of the resources I have available."

9:43 martinklepsch: ah

9:43 mdeboard: Perfect summary of programming :P

9:46 martinklepsch: any other things that I should checkout? I suck at reading books... they sometimes feel like "premature learning", esp. when they are like 500 pages long

9:46 mdeboard: Systems Performance is not

9:47 It's more of a reference material but some chapters are worth reading

9:47 catern: I have multiple predicates and exprs, and I want to check all the predicates and do all the exprs for which the predicates are true. Is there a clojure builtin for this?

9:47 mdeboard: Like how to gather system information at runtime of your program etc.

9:50 clgv: martinklepsch: first you should start measuring in which parts of the code your program spends the most time. JVisualVM or Yourkit are tools tha can be used for that

9:54 martinklepsch: clgv, yourkit isn't free is it?

9:56 clgv: martinklepsch: no. though they provide free licenses for opensource projects. there should be a limited trial version so that you can tackle your current problem

9:56 martinklepsch: clgv, I might just try jvisualvm first

9:56 (which seems to be oss)

9:57 clgv: yeah just try it out

10:16 devn: technomancy: Someone newish to Clojue just asked me: "Where is Clojure 1.6 on clojars?" -- I found you pushed 1.5.0-alpha3 to clojars awhile back. Do those need to be up there? Just curious.

10:22 clgv: devn: no they are on maven central

10:22 devn: http://search.maven.org/#search|gav|1|g%3A%22org.clojure%22%20AND%20a%3A%22clojure%22

10:23 hyPiRion: hrm, we should probably have a mirror on Clojars though

10:26 meng_1h: #jquery

10:35 User120: stu "d!ckless" lantz betrays all; trannys & queers(chaste Homos/a$$holes), rule; http://en.wikipedia.org/wiki/Lists_by_country

10:36 gone

10:36 farhaven: uhm

10:36 spam is weird...

10:38 silasdavis: I'm trying to push to clojars with lein deploy clojars

10:38 and I'm getting ReasonPhrase: Forbidden.

10:38 I've reentered my armored public key multiple times into clojar's profile page

10:38 is there any other reason it could be happening

10:38 It's only a 4k jar file

10:43 jcromartie: I'm having a hard time splitting runtime from config

10:43 my uberjar compilation should not depend on config

10:44 I guess it's the universal advice: don't use globals

10:44 since some of the config stuff manifests itself as globals

10:53 connor28: Hello everyone. I'm getting back into programming after many years (and even back then, I knew just some basic C/Java). I want to learn something that's fun, and quite different from what I know. Do you recommend Clojure?

10:54 systemfault: Sure ;)

10:55 hyPiRion: connor28: You're asking in #clojure, what answer do you expect? :p

10:55 tim_: connor28: no, here in #clojure we never recommend the language, it's utter crap :-P

10:55 systemfault: We all hate Clojure

10:55 connor28: Haha LOL

10:56 systemfault: connor28: Seriously, just play with it, you might love it.

10:56 hyPiRion: connor28: I think it sort of depends on what you want to do. Do you want to make some specific thing, or do you want to learn new a way to look at programming?

10:56 clgv: honestly, [they] hacked most of it together with Perl.

10:56 connor28: No, I mean - I have no commercial aspirations, I'd just like to learn something that's fun, so that's one factor out of the variable. I also want to learn a language that's different enough from C/Java, so it'll be like learning to program again.

10:56 clgv: http://xkcd.com/224/

10:57 hyPiRion: connor28: then I would at least recommend it. It's very different from C/Java in many aspect

10:57 systemfault: Different in a good way :P

10:58 connor28: I see. That's good to know.

10:58 hyPiRion: While syntax may seems like the most crazy thing, I think the hardest is to work with immutable values. I remember I had serious issues working with it

10:58 It's super valuable for me nowadays though

10:59 connor28: What would be the best books you'd recommend for Clojure?

10:59 silasdavis: I am getting Forbidden errors trying to push to clojars, it's driving me mad

10:59 it's worked before

10:59 hyPiRion: http://www.clojurebook.com/ is the one I've heard is the best, but that was some time ago

11:00 silasdavis: I've checked my password... I've tried with registered email and username (which should you use?))

11:00 hyPiRion: Not much has changed in the language though, so it's not (too) outdated

11:00 silasdavis: username

11:00 cbp: You could try the clojure cookbook

11:02 clgv: connor28: choose either "Clojure Programming" or "Programming Clojure (2nd edition)" depending which writing style suits you best

11:04 connor28: OK I'll check that books out. Thanks guys

11:07 clgv: mdrogalis: interesting. though there is no possibility to deactivate one of the aspects, right?

11:08 mdrogalis: clgv: There is. remove-<whatever>

11:08 Not sure if I ever updated the docs.

11:08 clgv: mdrogalis: no, I mean in the component setup you describe in the above linked post

11:09 mdrogalis: clgv: Oh. I believe you can reach into the 'started' system and stop individual components. Probably a stuartsierra question though

11:09 I havent tried it

11:09 clgv: yeah. that's right. component would have to provide something like that

11:10 hmm well, dire could provide some grouping of handlers as well such that all hooks are de-/activated via one function call

11:10 stuartsierra: clgv, mdrogalis: You could reach into the system and stop individual components, but be aware that any changes to those component records returned by `stop` will not propagate to their dependencies.

11:10 devn: emacs24 on linux AMI -- how do? I cannot find an RPM anywhere.

11:11 mdrogalis: Seems fair if used with caution.

11:11 I haven't run into a situation where I wanted to do that, though.

11:15 hyPiRion: devn: I don't use AMI, but for my work machinges I usually fetch the build dependencies and build from source.

11:23 gfredericks: the latest-version.svg images from clojars are thwarted by github caching things

11:26 llasram: gfredericks: is github not respecting cache-control headers?

11:27 gfredericks: no idea

11:28 I don't see any cache-related headers from clojars

11:28 llasram: Oh

11:29 hyPiRion: gfredericks: last modified?

11:29 gfredericks: Server/Date/Content-Type/Connection/Set-Cookie/X-Frame-Options/Content-Length

11:32 https://github.com/ato/clojars-web/blob/master/src/clojars/routes/artifact.clj#L57-60

11:32 prolly not hard to fix there; I am not a knows-much-about-http though

11:33 TimMc: gfredericks: I thought those were passthrough, not proxies!

11:33 *proxied

11:34 gfredericks: those?

11:35 TimMc: Images included in github doc files.

11:36 gfredericks: https://github.com/github/markup/issues/224

11:37 a cursory glance at that suggests an appropriate heading could fix it

11:37 header*

11:44 TimMc: Maybe. According to that thread, setting Cache-Control may not be enough...

11:44 gfredericks: I'll go file an issue with clojars

11:46 https://github.com/ato/clojars-web/issues/207

11:50 oh snap somebody made a PR before I could even file an issue

11:50 clgv: awesome :D

11:55 gfredericks: at least you were faster than travis-ci ;)

12:05 jcromartie: when I start a clojure app with lein run

12:05 the pid that I get from my shell ($!) is for a bash process that starts lein

12:06 and when I kill that bash process, it doesn't kill the java process

12:06 technomancy: jcromartie: try lein trampoline run

12:07 jcromartie: there we go

12:09 squidz: does anybody here have any experience making apps for android? I was planning on making an app that relies on a compojure backend with react front end using phonegap. But after hearing that phonegap is a pain in the ass, I was wondering if anybody knows of any alternatives?

12:11 kenrestivo: squid: i used clojure to make an android app

12:11 squidz: ^

12:11 the disadvantage is the startup time is very long, but this was a streaming radio player so startup time wasn't such a big deal.

12:14 squidz: kenrestivo: what did you use?

12:15 or has anybody here had any success using something like phonegap?

12:15 kenrestivo: squidz: i used clojure :-) clojure-android

12:16 no gap or any of that

12:17 https://github.com/kenrestivo/spazradioapp <- squidz

12:18 squidz: kenrestivo: how long is the startup time usually?

12:23 stompyj: Just checked out braveclojure.com today. It’s written *exceedingly* well

12:36 PigDude: really?

12:37 it seemed sort of all overthe place to me, amit rathor's book seemed better for beginners

12:38 technomancy: I really didn't like clojure in action

12:38 Glenjamin: i'm not keen on teaching emacs and clojure at the same time

12:38 technomancy: at least for an early draft I read; I ended up more confused about multimethods after reading its explanation than when I started.

12:39 maybe the final draft was better, but I'd still recommend clojurebook.com over it

12:39 Glenjamin: i started learning both, admittedly not from one source, and abandoned emacs with the intention of returning later

12:39 still havent

12:39 PigDude: technomancy: its treatments of multimethods and protocols are long-winded and kind of confusing, i agree

12:40 aaelony: 09:24 *** lw JOI

12:40 PigDude: technomancy: i found the other early material accessible and a good ramp into "joy of clojure" and other stuff

12:40 aaelony: what's folks' favorite manner to sort a map by value?

12:41 Glenjamin: aaelony: maintain an index as another sorted map of value => key

12:41 but the proper answer is: it depends how you need to access the data

12:42 aaelony: Glenjamin: That's a good idea, but I wish there was something more perlish...

12:42 PigDude: Glenjamin: what does that look like?

12:42 Glenjamin: PigDude: (def my-map {:a 123}) (def index (sorted-map 123 :a))

12:43 or, more likely:

12:43 PigDude: Glenjamin: i mean the index maintenance part. i know how i might do it but i'm curious how you do it

12:43 stompyj: PigDude: what book is amits?

12:43 Glenjamin: oh

12:43 coventry`: aaelony: Do you mean something like (sort-by second my-map)?

12:43 Glenjamin: i have a function that updates both

12:43 PigDude: stompyj: "Clojure in Action" by Manning Press

12:43 stompyj: checking

12:44 ahhh interesting

12:44 PigDude: Glenjamin: ok making sure i wasn't missing something, tha'ts how i'd do it too

12:44 stompyj: I’m looking for resources to get people ramped up / excited bout clojure

12:44 Glenjamin: maybe it's doable with watches and metadata or something

12:44 stompyj: the oreilly one was the best I had found so far

12:44 Glenjamin: but i keep it simple

12:44 aaelony: coventry: yes!! that's my favorite so far :)

12:44 Glenjamin: stompyj: i generally recommend http://aphyr.com/tags/Clojure-from-the-ground-up to everyone

12:44 PigDude: stompyj: i like to grab them all :) each has its flaws

12:44 aaelony: very elegant

12:45 stompyj: clojure from the ground up is quite good too

12:46 PigDude: Glenjamin: hehe the "welcome" page sure blind-sided me :)

13:01 mr-foobar: happy 1400000000

13:02 dan: "lein compile" on macos takes 60s+ to run when it's asked to compile a top-level call to (clojure.java.shell/sh "/bin/true")

13:02 anyone seen that or know why?

13:02 martinklepsch: why isn't my clojure program ran by lighttable showing up in visualvm?

13:03 dan: (if you're wonderiong why I'm running shell commands at compile time, it's because I haven't found a better way to compile C code from leiningen yet)

13:04 technomancy: dan: yeah, there are a lot of things wrong with that

13:04 dan: far as I can work out from dtruss, it's waiting on some condition variable or something?

13:04 technomancy: the root cause is that sh spins up a thread pool which keeps the JVM from exiting for 60s

13:04 dan: psynch_cvwait

13:04 ah, that'd be it, yes

13:05 technomancy: but that doesn't mean shutting down the thread pool is the right fix

13:05 you should add a lein-shell invocation to :prep-tasks in project.clj instead

13:06 dan: ok, thanks. I have a somewhat convoluted build, where some clojure code generates a C program source file then compiles and runs it and parses the output

13:06 clgv: martinklepsch: for benchmarking you should build a jar and run that.

13:07 martinklepsch: clgv so not even run it from the repl?

13:07 dan: this is all in the interest of reliably getting struct element offsets for use with jna

13:07 martinklepsch: gtg

13:07 cheers, clgv

13:08 clgv: martinklepsch: usually not because leiningen uses several optimizations for faster startup. you can switch those off in project.clj via :jvm-opts ^:replace []

13:08 martinklepsch: k, cool

13:08 good to know

13:08 thanks!

13:09 dan: but thanks, I'll look at prep-tasks

13:12 technomancy: dan: it sounds like what you're describing is a circular dependency though

13:12 that can be a lot trickier to express

13:16 cbp: is there a time lib for cljs? goog.date.Date is mutable when doing something like (.add (Date.) (Interval. Interval/MONTHS 1)) and me no likey

13:17 ToxicFrog: So, with multimethods, I can use (defmethod key args & body) to create a new dispatcher.

13:17 Is there a way to do that with an existing fn?

13:17 E.g. (defmethod my-multimethod :foo identity) rather than (defmethod my-multimethod :foo [x] (identity x))?

13:19 technomancy: not with defmethod; might be possible by falling back to java methods though

13:22 ToxicFrog: ...also, if there are multiple handlers with the same dispatch value for a multimethod, is it specified which one takes precedence, absent the use of prefer-method?

13:22 Experimentation says "the most recently defined one", but I don't know if I can rely on this.

13:23 technomancy: if you need to rely on it, you should make it explicit with prefer-method I think

13:24 coventry`: I haven't yet been burned by mutable time objects. How does it end up happening? You use a library which has its mutating way with a date you pass it?

13:25 cbp: coventry`: I have to use .clone a lot and doto when doing stuff like swap!

13:26 coventry`: I guess that is the safe thing to do.

13:26 aaelony: For various reasons related to SQL fluency, I'm not using a DSL for SQL generation but rather have functions that emit SQL strings. Because its simple. I've also attached meta-data to each function that emits SQL, identifying which tables underlie the queries. The advantage of this is that I can now query the meta data to determine how many such functions use certain tables and how often. https://www.refheap.com/8

13:26 5429 Curious what people think...

13:26 https://www.refheap.com/85429

13:28 stompyj: Clojurists are mappers, Haskellians are packers. How fast does that to get to the top of HN?

13:32 l1x: :D

13:32 Raynes: aaelony: You nearly gave me a heart attack.

13:32 I thought the paste counter had somehow reset and was overwriting pastes because you linked to paste 8.

13:33 Don't do that to me, man.

13:33 l1x: has anybody ever implemented a Kafka consumer in Clojure?

13:33 Raynes: amalloy_ and I once implemented their file format in Clojure :D

13:34 That was an exciting afternoon.

13:38 bchar: (reverse (str 9009)) returns (9 0 0 9) ?

13:39 aaelony: Raynes!! Sorry about that.. I blame my emacs setup ;))

13:39 bchar: shouldn't it be "9009"?

13:40 wink: Americans, how do you pronounce "zfs"? :)

13:40 cbp: it returns (\9 \0 \0 \9)

13:40 Raynes: bchar: It isn't returning a reversed string.

13:40 'reverse' is a general function that works on anything that you can call seq on.

13:40 As such, it returns a seq.

13:41 jhulten: wink: zee eff ess

13:41 squidz: zee efff es

13:41 cbp: ,(clojure.string/reverse "9009")

13:41 clojurebot: "9009"

13:41 Raynes: &(clojure.string/reverse "abc")

13:41 lazybot: ⇒ "cba"

13:41 Raynes: cbp: My lawn. Get off it.

13:41 ;P

13:41 cbp: :-(

13:41 bchar: thanks so much :) super new to clojure

13:41 wink: jhulten: squidz: so with a little softer zee than CFS? :P

13:41 bchar: trying out some euler problems

13:41 jhulten: zee vs see

13:41 wink: this zee/zed thing is so weird

13:42 I see, thanks.

14:02 stuartsierra: ToxicFrog: If you redefine a defmethod it replaces the old method for that dispatch value.

14:04 ToxicFrog: stuartsierra: sweet.

14:04 Thank you.

14:16 If I have a macro that I want to emit multiple statements - say, a defmulti followed by a defmethod - how do I do that? Just wrap them in (do)?

14:18 llasram: ToxicFrog: Yes

14:18 ToxicFrog: There's actually special handling in the compiler for top-level `do`s, handling their direct sub-forms the same as independent top-level forms

14:20 amalloy: ToxicFrog: make sure you *emit* wrapping them in a do. ie, it's `(do ~x ~y ~z), not (do x y z)

14:21 llasram: there's actually a few places in core that emit (let [] ...) instead of (do ...) in order for the special handling of 'do to not apply

14:22 llasram: amalloy: Interesting. I'll have to find those -- hadn't explicitly noticed them on any of my expeditions through core

14:22 amalloy: specifically in core_deftype.clj. i don't really understand *why* they need to do this

14:22 llasram: hmm

14:22 Bronsa: amalloy: IIRC it has to do with the classloader

14:23 amalloy: ohhhh, because each top-level form gets its own DynamicClassLoader?

14:23 Bronsa: yeah

14:23 hiredman: right, and classes can get gc'ed before they are used

14:24 amalloy: oh man, that sounds familiar. and HORRIBLE

14:24 hiredman: right, I think there was a ml thread about it

14:25 Bronsa: https://github.com/clojure/clojure/commit/2ac93197e356af3c826ca895b5a538ad08c5715a relevant commit

14:25 the downside is that this fix causes AOT and JIT deftypes to interact badly.

14:26 * technomancy sticks his fingers in his ears

14:26 martinklepsch: when benchmarking w/ visualVM clgv advised me to run a jar — do I need to run the uberjar?

14:26 technomancy: it's best I don't hear this

14:28 cbp: augghh. I keep getting "Uncaught TypeError: Cannot read property 'parentNode' of undefined". This is like impossible to debug

14:31 coventry`: cbp: It means you've got a nil somewhere.

14:32 cbp: =(

14:32 justin_smith: and you are trying to get the "parentNode" property of nil, HTH

14:33 coventry`: cbp: Perhaps you searched for a DOM element, and came up empty?

14:37 ToxicFrog: llasram, amalloy: awesome. Thanks.

14:40 cbp: I am making a datepicker and this error only occurs on august 2015...

14:41 this makes a lot of sense

14:41 amalloy: cbp: that's when the world ends

14:41 obviously

14:43 cbp: i shall baptize it nostradamus

14:44 ToxicFrog: Is there something wrong with using hyphens in namespace names?

14:45 cbp: no

14:45 ToxicFrog: Hmm.

14:46 It looks like it's looking for "spellcast/game/collect_players.clj" rather than "spellcast/game/collect-players.clj"

14:46 coventry`: ToxicFrog: Only that any java references to them, including via the filenames, have to use underscores instead.

14:46 ToxicFrog: So maybe using hyphens is ok but you need to replace them with underscores in the filename?

14:46 technomancy: vote for http://dev.clojure.org/jira/browse/CLJ-1297

14:46 ToxicFrog: coventry`: does (require) count as a "java reference"?

14:46 cbp: ToxicFrog: yes

14:46 technomancy: ToxicFrog: yeah, it is a really stupid quirk of the compiler

14:46 ToxicFrog: Because that's what's blowing up here

14:47 coventry`: ToxicFrog: If you use dashes in place of underscores in the filenames, require breaks in exactly that way.

14:48 ToxicFrog: That is exactly what I'm doing.

14:48 Blargh.

15:04 technomancy: does haskell have juxt?

15:06 amalloy: technomancy: yes

15:06 technomancy: what's it called?

15:06 amalloy: it's like an arrow thingy. i forget if it's &&& or ***

15:08 &&& is what i think of as juxt

15:08 lazybot: java.lang.RuntimeException: Unable to resolve symbol: && in this context

15:09 technomancy: cool, thanks

15:09 amalloy: yeah. http://www.haskell.org/ghc/docs/7.6.3/html/libraries/base/Control-Arrow.html

15:09 it's really hard to search for &&&. every search engine in the world hates it

15:10 cbp: Oh I get it. It's react trying to get a component that no longer exists. So apparently I'm using Om in a way I'm not supposed to. My table thing goes from 5 rows (<tr> components) to 4 and it goes boom.

15:16 Raynes: amalloy: symbolhound

15:19 amalloy: yes, that's what i eventually did. it doesn't index hoogle, apparently

15:20 stompyj: hooli?

15:22 coventry`: Stepping into a multimethod in clojurescript using the chrome debugger is sort of educational the first time, but extremely cumbersome.

15:23 Morgawr: mmm.. if I start a lein repl I get an nREPL server too, how can I avoid that?

15:24 also does nrepl only listen to the local interface?

15:26 ah ok nvm, read it from the lein help repl prompt, solved my problem ^^

15:47 timothyw: Anyone using https://ws.apache.org/wss4j/ ?

15:47 using leiningen: :repositories [["apache.public" "http://repository.apache.org/content/groups/public/&quot;]]

15:47 I get an org.sonatype.aether.transfer.ArtifactNotFoundException

15:47 "Could not find artifact org.apache.wss4j:wss4j:jar:2.0.0 in central (http://repo1.maven.org/maven2/)"

15:48 … weird, because the artifact is there

15:51 llasram: timothyw: I'm failing to recall the fix, but the problem seems to be that that is a POM-only artifact, not a JAR artifact

15:51 sdegutis: I am about to use lazy sequences and functional programming to solve a problem I would have solved with imperative mutable state in the past!

15:51 timothyw: @llasram. Oh, so I just can't use wss4j?

15:52 @llasram, or perhaps I have to download, install locally?

15:52 llasram: timothyw: You should be able to use it, and shouldn't need to install anything locally

15:53 timothyw: @llasram. This dependency doesn't work … [org.apache.wss4j/wss4j "2.0.0"]

15:53 amalloy: what is there to use, in wss4j? it doesn't have any code, and its pom has no dependencies

15:54 timothyw: @amalloy … let me verify

15:56 sdegutis: But it is hard to think in functional programming.

15:56 Maybe I can use &(reduce) here.

15:56 amalloy: it's just a collection of maven plugins, which presumably do some nonsense to add code from some other artifacts

15:57 llasram: timothyw: Assuming the dep actually does *something* other than maven plugin funtimes, check out the resolution here: https://github.com/technomancy/leiningen/issues/1451

15:57 sdegutis: Or &&(reduce).

15:57 What's that command for ClojureBot?

15:57 timothyw: @amalloy you're right. I've been trying every mvn repo I can get my hands on.

15:58 ToxicFrog: ,(doc reduce)

15:58 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val i...

15:58 timothyw: @amalloy Can't seem to find a good one

15:58 ToxicFrog: That wasn't as useful as I thought.

15:58 And I don't remember how to do it inline.

15:58 amalloy: timothyw: i think maven central is the right one. it's hard to imagine that it's "the wrong repo"

15:58 it's just that the code in wss4j isn't what you want

15:59 gfredericks: does lein have any flags for inspecting the eval-in-project code?

15:59 timothyw: @amalloy ???

15:59 lazybot: timothyw: Oh, absolutely.

15:59 timothyw: @amalloy. Ultimately, I just want to some SOAP XML Signing

15:59 amalloy: timothyw: as i said a moment ago, org.apache.wss4j/wss4j does not contain any code. it is just a collection of maven plugins

16:00 you are not using maven, so those plugins will do you no good

16:00 timothyw: :/

16:00 amalloy: if you were using maven, they would probably download all sorts of clever code

16:00 timothyw: right, i see

16:00 mimieux_:

16:00 timothyw: in the background, I was trying to find an actual jar

16:01 amalloy: you can probably find the code it would add to your project in a maven repo, under some other artifact id(s)

16:01 but i have no special knowledge of wss4j, so i can't help you find the code it depends on

16:02 timothyw: ok, I'll dig around a bit more

16:04 technomancy: gfredericks: you can set :eval-in :pprint

16:04 gfredericks: technomancy: oh sweets

16:05 technomancy: disclaimer: that might only exist on master?

16:07 timothyw: @llasram, thanks for that link. that answers some questions.

16:08 but still need to figure out to how to pull that code into my project

16:10 gfredericks: technomancy: it exists on what I'm running

16:11 should :injections work well with :main? I.e., should they get run before the main namespace is loaded when doing e.g. `lein repl`?

16:20 kenrestivo: squidz: it's like a minute, depending on device. there's more info here http://clojure-android.info/

16:20 technomancy: gfredericks: couldn't tell you off the top of my head which happens first

16:20 tias

16:22 gfredericks: technomancy: I've tried it on two different machines and gotten different results :P

16:22 oh wait

16:22 technomancy: o_O

16:22 gfredericks: maybe I know why that happened

16:23 okay I think the normal thing is for the main to get loaded first

16:23 so I was asking because I don't see why that would be a good idea?

16:23 I thought the idea with injections was to be able to do sneaky shit before anything else happened

16:24 technomancy: yeah that is surprising. loading :main is specific to the repl task, and :injections is general

16:24 gfredericks: sounds like a legit issue then?

16:25 technomancy: oh man...

16:25 no, I remember now. init-ns is kinda craaaaaazy

16:25 because it needs to apply to every single repl connection for a given server

16:25 so it's implemented as a middleware

16:26 init-ns being a thing that :main normalizes into

16:29 gfredericks: oh right because you want every new client to startup there

16:39 sdegutis: I'm sure this can be done in a clever way.

16:40 I have a function which is paginated, but not by number, only by the last ID it returns. I think I can use lazy infinite sequences to get all the relevant results and return the concatenated results.

16:41 Because it uses the last ID, I think I have to use reduce, and then take-while in order to stop at the final result.

16:41 This will be fun!

16:42 Oh wait, maybe I can use iterate!

16:45 gfredericks: I've done that before with just manual lazy-seq usage

16:46 (fn next-page [...] (lazy-seq (let [p (get-page)] (concat records-from-p (next-page p)))))

16:46 with a (when ...) somewhere in there to get the end

16:48 hiredman: what you want is unfold, which I am sure someone has a clojure implementation of somewhere

16:48 justin_smith: sdegutis: reduce and take-while? reduce is eager, but there is reduced to short circuit with

16:49 hiredman: http://cvs.haskell.org/Hugs/pages/libraries/base/Data-List.html#9

16:49 gfredericks: technomancy: I still don't understand why nrepl middleware would get run before the :injections code?

16:50 or is it that eval-in-project does the original require, while the middleware just switches namespaces?

16:50 so still plausible for :injections to run first?

16:50 technomancy: hm; actually good point

16:50 you're not using :eval-in :nrepl, are you?

16:50 gfredericks: no

16:52 technomancy: oh, init-ns is actually handled in the server setup too, not just when clients connect

16:52 ;; TODO: remove in favour of :injections in the :repl profile


16:53 llasram: I frequently wish my past and present selves would communicate a bit better

16:53 technomancy: yeah, this is not particularly well thought-out; there's no reason it should be its own thing

16:53 gfredericks: if it were an injection then this matter would be sensitive to what order the profiles get merged in?

16:54 technomancy: yeah, but you could use ^:replace to override it

16:54 huh

16:54 I wonder if there should be a ^:reverse that you could attach as well

16:55 gfredericks: do we need to steal cemerick's concept of middlewares requiring and expecting each other?

16:55 sdegutis: gfredericks: that sounds like a good middleground

16:55 justin_smith: ah hah

16:55 hiredman: obviously you should provide a map of names to injections, and a map of names to depedencies, and then do a topo sort

16:55 gfredericks: damn

16:56 technomancy: gfredericks: I would just skip the init-ns stuff and use injections exclusively for now

16:56 gfredericks: hiredman: require/expect suggests the dependencies are bidirectional :)

16:56 technomancy: what is it you're injecting anyway?

16:56 gfredericks: this is repl util setup via adding shit to clojure.core

16:56 technomancy: ~guards

16:56 clojurebot: SEIZE HIM!

16:57 gfredericks: so ideally it gets done before your ns gets loaded

16:57 hey man it's not me it's for a friend

16:57 I do this myself but I handle it by re-requiring in my repl init, I think

16:57 technomancy: http://p.hagelb.org/nope.gif

16:57 gfredericks: it occurred to me this morning I could have convenient repl access to stuff by putting it in a namespaced called -

16:58 technomancy: if your init ns needs something to function... it should be declared

16:58 gfredericks: these are repl utilities, I just want them for myself

16:58 in whatever ns I happen to be in

16:58 technomancy: hm; then why does the order matter?

16:58 coventry`: gfredericks: I use one-character namespaces like that all the time, but have you seen vinayasa?

16:59 gfredericks: well if the mechanism for convenience is that the vars are placed in clojure.core so they can be naked everywhere

16:59 coventry`: that's actually what my "friend" is using

16:59 then they won't be magically available if a namespace gets loaded before the vars get setup in clojure.core

17:00 you have to do another (require '[clojure.core :refer :all])

17:00 technomancy: but if they're convenience repl defns then they shouldn't be refered by code on disk anyway

17:00 martinklepsch: how can I run a profile accross multiple namespaces using timbre? is that possible at all?

17:00 technomancy: that's kind of exactly what you want to avoid

17:00 gfredericks: technomancy: they aren't

17:00 technomancy: if they're used by files on disk then they need to be declared

17:00 gfredericks: they aren't

17:01 technomancy: hm; I don't get it then

17:01 gfredericks: I want to say `lein repl` and have my happy sugar convenience function immediately available

17:01 as well as whenever I switch namespaces for any reason

17:02 technomancy: so why can't you use :injections?

17:02 gfredericks: the resulting order is

17:02 (do (load 'my.main.namespace) (magically-add-convenience-fn-to-clojure.core))

17:03 so my.main.namespace does not see the new core functions

17:03 technomancy: so just add a refer call to your magic function

17:03 hm; unless *ns* isn't bound or something?

17:03 gfredericks: yeah I think that is prollably the answer

17:03 technomancy: anyway, what you really want is nrepl-discover though

17:03 because doing this in clojure is kind of crazy

17:03 gfredericks: I do?

17:04 technomancy: aboccarily

17:04 *absoccarily

17:04 I mean, you want nrepl-discover, except finished and working

17:05 gfredericks: so here's another thing

17:05 if my.main.namespace requires the rest of my project

17:05 technomancy: I suspect you don't actually want functions you can call in the repl; it's just easier to implement than Emacs commands which invoke Clojure functions in your project's JVM

17:05 but what if I told you ... it's actually not that hard

17:05 gfredericks: then all of the dependent namespaces have this same problem

17:05 technomancy: oh yeah, that kinda chews. (all-ns) is a thing though

17:05 but don't do that

17:05 gfredericks: lollerskates

17:05 technomancy: do this: https://github.com/technomancy/nrepl-discover

17:06 or at least think about it

17:06 gfredericks: my "friend" is not using emacs

17:06 technomancy: perfect; we need someone to write a vim frontend.

17:07 sdegutis: Ahh, I had my hopes that I could do this without recursion, but alas, it may be the simplest of all ways.

17:07 *always

17:14 martinklepsch: anyone here some experience profiling with timbre? is it possible to profile accross multiple namespaces?

17:21 Frozenlock: yogthos: Is there a way to specify https instead of http in cljs-ajax?

17:22 kenrestivo: i'm trying to port a library from cljs to clj, but it relies on ISequable, IHash, IEquiv, etc, being protocols not interfaces. any words of wisdom (other than "don't do that")?

17:26 amalloy: how does it depend on that, kenrestivo? by extending protocols it doesn't own to types it doesn't own?

17:27 kenrestivo: right, it redefines -hash, -seq, -equiv so that deep in other code, when those get called, the overriden versions get called

17:27 the more i look at this, the more i feel like this might not be worth the effort.

17:28 Frozenlock: yogthos: Nvm, I was using an Iframe with simple http inside an https document and it was messing everything.

17:29 yogthos: Frozenlock: ah gotcha

17:30 Frozenlock: also Julian Birch has taken over the project recently as I haven't had time to work on it

17:31 Frozenlock: yogthos: I see, I'll direct questions to him then. Thanks for the library btw, quite useful! :-p

17:32 amalloy: kenrestivo: that sounds like a pretty unpleasant thing to do: it's really recommended to own either the protocol or the type, when extending one to the other

17:32 yogthos: Frozenlock: glad to hear it, an Julian can take most of the credit for the current state of it :)

17:33 amalloy: with interfaces you have to own the type; protocols let you own either of them. they also let you own neither, but using that is kinda bad form

17:33 kenrestivo: yep, they're extend-type'ing on core interfaces/protocols. i can see why, but i can also see why it's problematic too

17:37 sdegutis: Here is my solution: https://gist.github.com/sdegutis/e18a06dbdaca9546dc9f

17:42 amalloy: seems okay, sdegutis. i wouldn't hard-code the call to 'last; it can be part of id-fn. really it would be best for f to return both a seq of things and a next-id

17:42 i guess at that point it's basically unfold, as hiredman suggested

17:42 sdegutis: I had not seen this suggestion.

17:43 I see it now.

17:44 Thanks.

17:46 amalloy: eg, if you use https://github.com/flatland/useful/blob/develop/src/flatland/useful/seq.clj#L128, then you can write (apply concat (unfold (fn [last-id] (when-let [results (seq (...look it up...)))] [results (find-id (last results))])) initial-seed))

17:46 sdegutis: Interesting.

17:46 Why is that not part of Clojure.Core?

17:47 amalloy: i dunno, no good reason that i know of

17:49 sdegutis: You have a Jira account, that should be sufficient to file an issue to add it.

17:49 pyrtsa: sdegutis: I don't think it reads well but you can use mapcat + iterate for this case.

17:50 sdegutis: pyrtsa: I'm not sure how that would work, since each iteration requires the last element of the previous iteration but each iteration must be concatenated to one another in full and the result returned.

17:50 pyrtsa: (mapcat first (iterate (fn [[_ x]] (let [xs (f x)] [xs (last xs)])) nil))

17:51 sdegutis: Ah yes, indeed!

17:51 I had not thought of that technique. Although I did use it yesterday or the day before, so I should have thought of it.

17:51 pyrtsa: I've used it with reductions before.

17:52 Many times, actually. But just realised it works with iterate too.

17:52 sdegutis: I've used it with reduce actually.

17:52 Thanks!

17:53 amalloy: pyrtsa: it's a cute trick, but when i use iterate or reductions like this (ie, using half the accumulator as an intermediate state, and the other half as a return value), it always ends up looking worse than just writing a recursive function with lazy-seq

17:53 pyrtsa: amalloy: Like I said, I don't think it reads well.

17:54 sdegutis: Also it's nice that nil (the else-clause of an if or if-not) can be used with concat, which makes this code very prerty.

17:57 pyrtsa: Yeah, looking at the flatland link above now, unfold would be a welcome addition.

18:00 aaelony: is there a guide to useful flatland?

18:00 jwm: (clojure.pprint/cl-format nil "~0f" (* (/ 7 15 ))) = 47.

18:00 I do a parse-int around that is that the best way of doing divison?

18:01 sorry I left out the 100 in there

18:01 (clojure.pprint/cl-format nil "~0f" (* (/ 7 15 ) 100)) = 47.

18:01 I am just getting percentage basically

18:06 amalloy: aaelony: http://flatland.org/useful/

18:06 there's no "guide", because it's just a pile of unrelated functions. but this is an overview

18:07 that doc is new as of yesterday (thanks Glenjamin!); i may regenerate it while removing the most useless stuff

18:08 aaelony: amalloy: looks great

18:08 Raynes: amalloy: I suddenly want to write a guide to useful that is themed as an adventure into an unexplored cave.

18:09 aaelony: raynes: yes yes yes

18:09 amalloy: Raynes: "you are likely to be eaten by a glue"?

18:09 Raynes: glue

18:09 That was the best thing you've ever said.

18:10 aaelony: I often think I should be using useful, if I knew when I should be using it better

18:10 gtrak: does useful have rseq over a queue in there?

18:10 Raynes: amalloy: Man, I'm still not totally sure I get what glue does.

18:10 amalloy: gtrak: is that even possible?

18:10 gtrak: maybe not :-)

18:10 i've only thought about it for a few minutes.

18:10 gfredericks: I had to pick a util lib at work and eventually chose prismatic/plumbing; I don't know if I could say why though

18:10 amalloy: it might be. i dunno

18:11 Raynes: amalloy: I was very pleased that you guys managed to create that abstraction though. It took me by surprise. I sure didn't see an obvious abstraction there!

18:11 aaelony: I like useful flatland especially for the double entendres

18:11 amalloy: &((juxt peek seq) (into clojure.lang.PersistentQueue/EMPTY [1 2 3]))

18:11 lazybot: ⇒ [1 (1 2 3)]

18:11 Raynes: Glenjamin: Yo.

18:11 gtrak: clearly we need a PersistentDeque

18:12 amalloy: yeah, looks like peek goes in the same order as seq, so i don't think you can possibly rseq efficiently

18:13 jwm: anyone here use d3/c2?

18:13 just curious how well c2 is at doing what d3 does

18:14 aaelony: jwm: I would look at gorilla-repl that uses vega

18:14 numberten: i'm reading about gensym and I have a question. when binding a symbol to (gensym) in a let statement. doesn't the symbol you use to refer to the unique symbol suffer from the same problems you're trying to avoid?

18:14 gtrak: maybe I'm just using the wrong thing, been using queues for convenience in om tables, push on one side, pop off the end.

18:14 amalloy: i don't do much/any front-end stuff, so take this with a grain of salt, but i've heard c2 is underwhelming

18:14 numberten: that is making sure the symbol doesn't exist in some outter scope?

18:14 jwm: nah it even says on the github c2 is underwhelming

18:14 numberten: s/outter/outer

18:14 jwm: that is why I asked the question :)

18:15 yeah I should not be allowed to do frontend but apparently neither should most people

18:15 amalloy: numberten: no, because you'll be keeping that symbol inside the macroexpansion, rather than introducing it to the expanded code

18:15 aaelony: http://gorilla-repl.org/renderer.html and http://trifacta.github.io/vega/

18:15 amalloy: eg, consider (defmacro foo [] (let [x (gensym)] `(let [~x 1] (inc ~x))))

18:16 you don't need to worry about x colliding, because it never appears in the expanded code

18:16 jwm: you know I think gorilla is exactly what I wanted but seems unrelated to my question

18:16 you answered my question without me asking it lol

18:16 thanks

18:16 aaelony: it's pretty stellar

18:16 jwm: yeah it looks sick

18:16 aaelony: kudos to the author

18:16 jwm: I was thinking of recreating it

18:16 numberten: amalloy: that makes sense

18:17 jwm: I think I even saw it before but did not pay any attention since it was one of 200 tabs

18:17 numberten: I was looking at this example over and over and just didn't see it, but that helps. thanks

18:17 aaelony: another cool viz project that could be great in clojure would be something like dc.js http://nickqizhu.github.io/dc.js/

18:18 synchonicity of charts

18:18 synchronicity

18:18 jwm: you know I am waiting on famo.us

18:18 pretty slick looking though they dont have any vector graphic stuff it seems like yet at least

18:35 l1x: when i am using a java lib that requires log4j and i place a log4j.properties into the resources folder but it still complains about missing log4j config what am i doing wrong?

18:36 i havent done a lein uberjar

18:36 i love this channel, so easy to get answers :D

18:37 amalloy: there's some funny stuff in useful i'd forgotten about. https://github.com/flatland/useful/blob/develop/src/flatland/useful/time.clj#L5 makes me laugh

18:38 noonian: l1x: i'm definitely not an expert on logging, but i think you also need to add log4j to your dependencies so that it is on the classpath

18:39 l1x: noonian: nah it was just lein uberjar because the log4j.* files get compiled into the jar so when you invoke the jar it has access to it

18:39 noonian: ah, cool then

18:39 l1x: i just forgot to rebuild the app with the log4j.prop added to the resources/

20:00 Glenjamin: Raynes: sup?

20:01 Raynes: Glenjamin: Your script for generating documentation and handling all the branch juggling. It's beautiful. I need more of it in my life. We need to turn this into a generalized leiningen plugin, man.

20:01 Glenjamin: that somewhat defeats the point of the linear bash script :p

20:01 although technomancy's plans for lein change / lein release are similar

20:01 Raynes: I'd rather have a reusable leiningen plugin than a linear bash script.

20:02 I am, of course, not telling you that you have to write it :p

20:02 Glenjamin: heh

20:02 Raynes: I'll probably do it over a weekend.

20:02 Glenjamin: you'd need the java git implementation

20:02 but aside from that it's fairly simple

20:02 Raynes: Why would you need a thing like that

20:02 Glenjamin: in theory you could generate the html in memory and write straight to the branch that way

20:02 Raynes: I'd just shell out to git.

20:02 Glenjamin: because if you shell out from lein, you might as well have just used the bash file

20:02 Raynes: The point is that it'd be a leiningen plugin, not to avoid using git.

20:03 Glenjamin: what's the gain?

20:03 Raynes: Um, not having 40 copies of the same file across repositories with minor changes.

20:03 Glenjamin: i guess portability between projects

20:03 yeah

20:03 the logic is taken from https://github.com/tschaub/grunt-gh-pages/blob/master/tasks/gh-pages.js

20:04 which is why i'm hesitant to plug it back into a task runner :)

20:05 this is a similar lein concept - http://librelist.com/browser//leiningen/2014/5/1/release-task/

20:07 technomancy: yeah, you should totally help me write the release task

20:07 Glenjamin: i am considering it

20:08 especially if rewrite-clj is considered a reasonable dependency

20:08 technomancy: erhm

20:08 is that the one that pulls in potemkin?

20:08 Glenjamin: no idea, i just same the name

20:08 and some api usage

20:08 *saw the name

20:08 technomancy: yeah, I want to use sjacket from lein

20:08 Raynes: Dependencies in general are a bad idea for leiningen, unfortunately.

20:08 They make it incredibly difficult to package the darn thing for distros.

20:09 technomancy: plus we already have a lib that does that pulled in

20:09 but for 2.4.0 we don't need full project.clj rewrite capability, just version changes

20:09 Glenjamin: ah, i see

20:10 sjacket seems sensible,

20:10 enlive for clojure, i guess

20:10 technomancy: sjacket does the job; it's just not documented

20:10 Glenjamin: doing version numbers seems pretty doable

20:11 waynr: technomancy: http://www.meetup.com/clojerks/events/182784762/

20:11 getting some folks together on thursday to take a swing at some of the lein release work

20:12 technomancy: waynr: oh very cool

20:13 Glenjamin: Raynes: the other option is a standalone tool that just runs those commands in a dir

20:14 and then you just need enough info in project.clj for it to know (a) what command to generate docs, and (b) what directory is the docs

20:14 i am unsure if that's any better

20:15 Raynes: Glenjamin: I can write a Python program to do this and have it look for 'DOC_CMD' and 'DOC_DIR' environment variables, then you can add an alias to leiningen and pretend you have an actual plugin.

20:15 I too am unclear on how this is better though :P

20:15 You don't even save startup time, since you still have to invoke lein.

20:15 :P

20:16 Glenjamin: there is a tension between being able to use this on multiple projects easily, and adding complexity to a 15 line bash script :)

20:16 Raynes: I really think you're overthinking this.

20:16 It'd probably boil down to a 15 line Clojure file, the difference is that it'd be a jar on clojars. :P

20:16 Glenjamin: i suspect my preconception of a lein plugin is it's a bunch of work

20:16 but yeah, i take your point

20:17 Raynes: That's fair.

20:17 I've written 24352436 leiningen plugins, so I basically spit out a plugin template when I slap the keyboard.

20:17 Glenjamin: it depends how portable you're tempted to make it

20:17 eg, the java interop equiv of `mktemp`, vs shelling out for that bit too

20:18 technomancy: It's Just a Function™

20:18 Glenjamin: oh neat, that's refreshing

20:18 Raynes: Glenjamin: fs has temporary directory handling implemented in Clojure :3

20:18 Glenjamin: i always assume a java api i've never used will need at least two factories

20:18 Raynes: And I have conch, which makes shelling out approximately as seamless as your bash script :D

20:19 Glenjamin: sounds like a winner then

20:19 Raynes: Glenjamin: I'll just write the darn thing and we'll consult.

20:19 Glenjamin: works for me :)

20:19 Raynes: Could have written it while I stood here arguing with you about whether or not we should write it. :P

20:19 Glenjamin: heh

20:20 as i say, i stole the workflow from a convoluted grunt plugin, so it's hardly my idea in the first place

20:20 Raynes: I'm just happy you gave me a good reason to write some Clojure again.

20:20 It has been like months, man.

20:20 MONTHS

20:20 Glenjamin: :(

20:21 i've been tinkering with a side project, might even become something actually used at work

20:21 but probably not, as no-one knows any jvm, let alone clojure - myself included really

20:21 aaelony: Raynes: are you using R now?

20:33 devn: yeesh. long day.

20:34 dbasch: ,(System/currentTimeMillis)

20:34 clojurebot: 1400027375555


21:22 waynr: wut

21:23 l1x: dbasch: you seem like a seasoned clojure guy, have you ever used any queueing system in clojure?

21:24 i am still thinking about how should i consume a queue

21:25 dbasch: l1x: what kind of queue? you’re talking about a queue data structure within clojure, or an external message queue?

21:26 l1x: the later, external message q, like Kafka

21:31 dbasch: l1x: I haven’t used Kafka (or any message queue) from clojure. That’s a pretty generic question though, do you have any specific design requirements in mind?

21:31 l1x: it is indeed, i don't have anything in mind other than i have a stream of incoming messages and i need to process them.

21:32 luckily everything is immutable and idempotent so i dont care about duplicates

21:33 dbasch: l1x: have you used core.async?

21:33 l1x: i was just thinking what is the best way to wrap the other java libraries (those obviously throw exceptions) and have a rock solid design that does not care if the server it is talking to is going down, also it would be good to have some sort of performance control over the consuming speed

21:33 i haven't used it yet

21:35 dbasch: l1x: what you ask is really what kafka does, it’s mostly about how you configure and what resources you allocate to it

21:35 l1x: yeah i guess

21:35 the only problem is that the kafka clj library has some issues

21:36 but i guess i could write a thin wrapper around the original kafka libraries

21:38 dbasch: l1x: I’d use the original client, I’m guessing the person who wrote the clojure wrapper did that and then open-sourced it because why not

21:38 l1x: yes he did, but that library is meh, lots of magic for nothing

21:39 dbasch: l1x: that’s not uncommon in clojure because it’s so easy to write libraries

21:41 Raynes: $mail aaelony Python, mostly.

21:41 lazybot: Message saved.

21:41 Raynes: lazybot: plz

21:41 lazybot: kill

21:41 lazybot: KILL IT WITH FIRE!

21:41 Raynes: Not sure who was lagging there.

21:41 dbasch: They mostly come at night. Mostly.

21:45 l1x: dbasch: good point

22:45 amalloy: i had a thought about Object/clone. the natural implementation of that for an immutable class like clojure.lang.PersistentVector is just identity; is that wrong? is there any code that could legitimately be broken by this implementation?

22:47 i see that the stuff in clojure.lang actually doesn't implement clone at all

22:50 dbasch: amalloy: why would you want to implement clone for immutable structures?

22:50 ,(.clone “cloneme”)

22:50 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: “cloneme” in this context, compiling:(NO_SOURCE_PATH:0:0)>

22:54 amalloy: dbasch: because some other bonehead api i want to use clones its inputs or whatever

22:55 dbasch: amalloy: I don’t remember encountering an api that demanded the object passed in to be Cloneable

22:56 but I suppose in that case, I’d just wrap it in a CloneableWhatever and feed it to the beast

22:57 most likely an api like that would take MyFantasticApiObject which is probably Cloneable

22:57 I hate Java

22:58 amalloy: is Cloneable the silliest interface in the jdk? i wonder

23:01 dbasch: amalloy: depending on how you define silly, my vote would go to things like BeanContextServiceRevokedListener

23:02 amalloy: i dunno, presumably that's just IFn with a long name

23:07 dbasch: this one is awesome: TransformerFactoryConfigurationError

23:08 it’s a class though

23:09 quizdr: I'm finding it a bit strange that the dependency noted at https://github.com/ninjudd/clojure-protobuf is 0.7.1 when clojars shows the latest as only 0.6.2

23:10 rhg135: hmm, someone should compile a list of api fails

23:11 dbasch: quizdr: I see a 0.8.1 https://clojars.org/org.flatland/protobuf

23:12 quizdr: dbasch oh the github page instead links to https://clojars.org/protobuf

23:12 amalloy: i like http://java.metagno.me/, dbasch

23:12 if we're gonna make fun of classnames

23:13 dbasch: amalloy: that site gets me about half the time

23:13 amalloy: more than half, for me

23:14 dbasch: AbstractAnnotationValueVisitor7 <- wtf

23:14 “A skeletal visitor for annotation values with default behavior appropriate for the RELEASE_7 source version.”

23:15 quizdr: ask amalloy to fix it :)

23:16 amalloy: i don't know much about the lein-protobuf stuff. i'm thrilled it lives under ninjudd instead of flatland now, so nobody asks me to fix it

23:18 quizdr: I've never worked with protobufs before but now I'm being asked to connect to them so am having to learn

23:19 TEttinger: oh man, protobufs are not bad... I used them in C# and the lib there is top-notch

23:19 (of course I used edn to serialize in clojure, but still)

23:19 (they can't all be lisp)

23:19 quizdr: i was given an existing proto as a spec, but its not clear to me if I can just read it straight from Clojure using the ninjudd wrapper or I am supposed to first compile (recompile?) it with lein protobuf?

23:21 dbasch: amalloy: here’s a really silly one: UnsolicitedNotificationListener

23:22 amalloy: hahaha

23:22 quizdr: you must compile the protobufs. the .proto text files are useless at runtime

23:25 TEttinger: the example in the Readme has the .proto file compiled and then... loaded, I guess, with (protodef Example$Person)

23:25 where did Example$ come from?

23:25 amalloy: from the filename, maybe? i forget

23:26 TEttinger: filename is resources/proto/person.proto

23:26 so I'm fairly confused

23:26 jacortinas: What's the current state of the art for clojure web dev? I actually just gave pedestal a try from their docs and it seems that it is in huge flux.

23:26 Is there a more stable ring + other stuff stack, that people are really happy with?

23:26 TEttinger: luminus maybe?

23:27 (sp?)

23:27 dbasch: jacortinas: client side, I’m happy with Om

23:27 quizdr: When I compile the proto I was given, lein protobuf gives me an error, stating that Expected top-level statement (e.g. "message"). This suggests the proto is malformed? However, this is a production proto already used by other parties so maybe Lein cannot compile it

23:27 jacortinas: dbasch: I want to do om on the client, but I'm just trying to figure out a good stack for a normal web app.

23:27 TEttinger: http://www.luminusweb.net/ but yeah I've heard nothing but good things about Om

23:28 dbasch: jacortinas: I use Compojure, but I don’t need to do anything particularly complex

23:28 amalloy: TEttinger: i would not be at all surprised to find that the readme is out of date

23:28 TEttinger: heh I couldn't find any docs

23:28 amalloy: if you look in test/ and resources/, you'll see that is not the state of the files

23:28 TEttinger: :-(

23:38 quizdr: Ah, got it to work. the proto had some HTML at the top of it, yikes; from an automated export script on a web page somewhere, probably.

23:38 How do protobuff-formatted data typically get sent across the web? Is it like a specific TCP port that you listen to for these protobuf packets?

23:43 zeroem: So, I'm having an issue with clojars.

23:43 When I try to `lein deploy`, everything appears "ok" except for pushing out the pom

23:43 it comes back with an `Access denied`

23:44 currently, the only version I have pushed out is a snapshot build of the actual version I'm trying to push

23:54 nvm. Looks like everything got uploaded (somehow?) but the clojars UI showing it as available

23:54 :F

23:55 amalloy: quizdr: no port. it's more like base64 or gzip than like http

23:57 quizdr: amalloy but the job of the proto is not to describe where to get the data, but rather the format of the data when you do get it, right?

23:57 amalloy: right

23:58 quizdr: this proto i was given, they said, "here is the functional proto, and it also acts as a spec." well, it does indeed have many comments scattered throughout but none that refer to where this data actually comes from.

Logging service provided by n01se.net