#clojure log - May 06 2013

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

0:03 muhoo: is there some way to throw a 404 or other exception from deep inside an app and have it show up as a ring 404 error?

0:03 it seems like any exception shows up as a 500 in the ring response

0:04 which is kind of not ideal.

0:05 tomoj: catch it and return a 404

0:06 perhaps (ex-info "not found" {:your.ns/error-code 404}) or something

0:06 and maybe use https://github.com/fredericksgary/catch-data

0:06 or just return a 404 response :)

0:16 muhoo: yeah the right way to do this is to make it purely functional, and return a ring response {:status 404 :body ..}

0:17 also, is it a code smell to have (if cond (do some stuff here) (do more other here)) ?

0:18 the explicit do's look ugly to me

0:19 the probelm with returning ring responses is i do not want the entire app to have to understand ring

0:19 all the way deep down. that seems wrong. maybe i'll write somethign that catches custom exceptions and turns them into ring error responses.

0:19 i'm surprised nobody has done that already tho

0:19 nightfly__: sounds like the right way to go

0:20 tomoj: I've considered using exceptions for that

0:20 but I suspect it's.. not good

0:21 muhoo: slingshot looks pretty cool

0:21 tomoj: catch-data is better :P

0:22 muhoo: really? why?

0:26 tomoj: it does one simple thing

0:27 I don't understand your argument for throwing

0:29 brainproxy: gah, what's the right way to use github markdown so that you can highlight html including script tags

0:29 tomoj: either you throw a ring error response, in which case the thrower has to know ring. or you throw something which signifies an error but isn't coupled to ring, and translate it into a ring response elsewhere, in which case couldn't you just return that thing?

0:30 I guess I can sort of vaguely see why throwing would be useful, which is why I considered it, but I don't understand the tradeoffs..

0:34 ex-info and catch-data seem to maybe encourage using exceptions as part of normal control flow

0:43 tieTYT: clojure.repl has a pst. If I want to print the stack trace in my own program, what should I use?

0:44 tomoj: I use pst

0:46 lpvb: anyone tried using clojure on avian's AOT compilation and compared performance with any other VMs?

0:47 tieTYT: ok thanks

2:08 tomoj: &(seque (lazy-seq (/ 0 0)))

2:08 lazybot: java.lang.ArithmeticException: Divide by zero

2:08 tomoj: hmm

2:08 broken in 1.5.1?

2:10 I get ()

2:14 amalloy: hmm, did you break it? :)

2:16 ucb: tomoj: nice (the async blocks)

2:29 amalloy: i might've done, tomoj

2:30 tomoj: not like it would really help me to get the exception

2:31 totimkopf: what is a good high performance web server for clojure?

2:33 muhoo: i built this artifact, installed it in my ~/.m2/repository via "mvn install", but lein check can't find it https://github.com/tobie/ua-parser

2:34 also uploaded it to a private repo, added the repo to :repositories, and it still can't find it, but it's right there.

2:34 is it the underscores/dashes in the name? mvn installed it in two different places, on with ua_parser, another with ua-parser

2:36 auugh, nevermind i got it [ua_parser/ua-parser "1.2.1-SNAPSHOT"] does it. damn dashes

2:46 interestingly alembic and the repl hates those dashes, but in project.clj :dependencies it works fine

2:51 alistair: so I got asked to build a bog-standard CMS for a client today, and I told them I'd do it if I could do it in Clojure

2:51 is this an awful idea?

2:51 zRecursive: alistair: not auful if you know Clojure well

2:52 alistair: wouldn't it be a lot slower to implement than just using something off-the-shelf?

2:53 zRecursive: I gather there aren't a lot of pre-existing Clojure CMSs

2:53 tomoj: why build a new one if something off-the-shelf would satisfy?

2:53 zRecursive: seems Python has

2:54 something off-the-shelf will cause maintenance problem

2:54 alistair: because I want an excuse to be paid to write Clojure =)

2:55 I'm just wondering if there's anyway I can make it good for the client, and not just me.

2:56 zRecursive: Many Java Library make it good, doesnot it ?

3:08 chemistdeep: anyone alive?

3:08 HolyJak: not really ;-)

3:08 chemistdeep: aware of any cool clojure libraries that have come out recently?

3:18 Foxboron: alindeman: go to univ. Find a research group that needs something done, where you get paid. Code it in Clojure

3:18 best excuse ever.

3:19 totimkopf: I'm trying out http://www.luminusweb.net/ but when I type 'lein ring server' inside the project folder I get : That's not a task. Use "lein help" to list all tasks.

3:19 seems like a typo of some kind?

3:19 wink: totimkopf: what exactly did you do before?

3:20 HolyJak: totimkopf: not sure how it works but meybe you need to install ring plugin (or how is it now called) for lein?

3:20 totimkopf: wink: simply : lein new luminus myapp

3:21 wink: totimkopf: hm, tried "lein deps"?

3:21 totimkopf: wink, tried that just now, still no go

3:22 wink: totimkopf: if you're using lein2, that should be enough though.. hmm :)

3:22 totimkopf: i'm using lein 1.7.1

3:22 ut oh

3:22 wink: that could be it.

3:22 ring in this case (afaik) works as a leiningen plugin

3:23 the CLI part, that is

3:23 lein help should show ring

3:35 totimkopf: wink, fantastic, lein2 solved this issue

3:36 wink: totimkopf: nice, have fun then :) I'm doing my first luminus app as well right now

3:36 totimkopf: thanks, you too :)

3:41 Foxboron: Now srsly. Spent a little time with Midje last night. Best Testing framework i have encountered.

3:41 Was atually fun writing tests

3:41 mthvedt: even though lisp is the poster child for macros and code generation, i still have a hard time believing it when it actually works

3:41 djcoin: Where did the defadt moved to (the link in http://clojuredocs.org/clojure_contrib/clojure.contrib.types/defadt is broken - the clojure.contrib has been split in several lib - but can't find the good one) ? Thanks!

3:42 mthvedt: as though after enough coding the machine just takes pity on me, and pretends my code generators are doing the right thing

3:50 ucb: ,(source ->)

3:50 clojurebot: Source not found\n

3:50 Guest15182: q

3:51 totimkopf: mthvedt: I think that's one of the benfits of Lisp, more power to express something as intended

3:54 mthvedt: totimkopf: yeah, but it gets more unbelievable as you pile the abstractions and eval/macros higher

3:55 totimkopf: or maybe you're just that good at expressing yourself in Lisp that you just can't believe it;p

3:56 mthvedt: oh yeah, i did forget to account for my greatness

3:56 thanks for reminding me!

3:57 wink: lol

4:01 amalloy: tomoj: aha! i'm not the one who broke seque

4:02 apparently in 1.5 if you deref an agent that's failed, you get nil instead of an exception

4:07 tomoj: I see

4:07 amalloy: so seque is broken, and i'm the only one who touched it, but i'm not the one who broke it

4:07 tomoj: I apologize for the accusation :)

4:07 hiredman: amalloy: well, you get back whatever value was in the agent before the failure

4:07 amalloy: are you kidding? being accused of breaking clojure.core is great! it's nice to have some code that has the possibility to do that

4:08 oh, okay. hiredman is right, i'm sure

4:08 was that an intentional change, do you know?

4:08 hiredman: I don't

4:09 mthvedt: not re-throwing exceptions seems like a better behavior

4:09 hiredman: I don't seen any mention of it in changes.md of course

4:10 amalloy: i expect it was unintentional fallout from the change to let you specify what executor to use for agents

4:12 hiredman: I am looking at that now

4:13 the diff for that doesn't have anything immediately obvious

4:15 mthvedt: wait, does the deref never throw at all? or just not throw subsequent derefs?

4:19 amalloy: mthvedt: it never throws

4:20 mthvedt: oh, that's obviously wrong

4:20 amalloy: the only exception happens on the thread performing/computing the sent action. so if you don't catch it, you never see it

4:21 hiredman: very weird, you can see why it doesn't, but all those lines are at least a year old

4:24 amalloy: hiredman: 1.4 is more than a year old, isn't it? so a year-old change would be between 1.4 and 1.5

4:29 hiredman: I don't think agents ever threw on deref

4:29 (and this build of 1.2 agrees)

4:30 you get exceptions if you send an action to a failed agent

4:38 amalloy: hiredman: weird. i wonder why seque "touches agent just to propagate errors", then, with (do @agt nil)

5:38 pepijndevos: wow my repl doesn't start 0_o

5:40 tomoj: b

5:42 pepijndevos: ok it does. a bit. whatever

6:04 cmdrdats: hey guys, is there a built in clojure equivalent to rember? ie - remove an item from a list once - (rember 1 [1 1 1]) -> [1 1]?

6:11 noidi: cmdrdats, I don't think so

6:15 clgv: cmdrdats: it is pretty easy to build though. I think we had a task like this in our lisp course exercises ;)

6:30 cmdrdats: clgv, noidi: cool, thanks - I found an implementation here : http://juliangamble.com/blog/2012/08/03/the-little-schemer-in-clojure-chapter-3/ - cleaned it up a little, but I had hoped there was way to just use core functions directly

6:31 clgv: cmdrdats: do you want it to be lazy?

6:31 cmdrdats: cljgv: probably better if it were lazy, but I'm not too fussed

6:31 clgv* :P

6:32 clgv: clgv: you could take it as example to learn how to build your own lazy function

6:32 lol oops

6:33 cmdrdats: ^^ keyword: lazy-seq

6:34 cmdrdats: clgv: hehe, thanks :) I'm busy converting a php function across to clojure and they have a removeonce function - reminded me of the Little Schemer's rember function :P

6:37 tomoj: if we have core-async check for clojure.core/binding before macroexpansion, it could maybe compile bindings inside async in cljs to clojure.core-async/{push,pop}-binding ?

6:37 but still the problem of bindings established outside core-async

6:38 but shit, that's easy

6:38 light at the end of the tunnel :)

6:40 clgv: what type hast the "writer" in "print-method"? I got working examples and exceptions for both StringWriter and PrintWriter

6:41 hm ok they share the Writer ancestor...

7:56 tomoj: why can't you let qualified names?

7:57 echo-are`: Because let only introduce symbols to locations?

7:57 *introduces

7:59 And they are compiled out

8:07 tomoj: compiled out?

8:09 echo-are`: I mean there are no indications about the symbols in let's binding form in the assemble code

8:10 I.e. they are like function arguments, only references to a location

8:13 tomoj: so what?

8:14 I just want to be able to say (let [{:keys [foo/bar]} baz] foo/bar)

8:14 echo-are`: What do you need from "foo/bar" there?

8:15 tomoj: oh, hmm

8:15 I was thinking it should mean the same as (let [{bar :foo/bar} baz] bar)

8:17 but maybe ::foo/bar

8:17 which would be weird

8:17 so, OK :)

8:40 dnolen: stuartsierra: any chance for another CLJS release?

8:41 stuartsierra: dnolen: I did it last week.

8:41 Do we need another one?

8:42 dnolen: stuartsierra: we do, I introduced a regression, master is fixed.

8:42 stuartsierra: ok

8:43 dnolen: stuartsierra: thx!

8:50 stuartsierra: dnolen: Just released 0.0-1803 to Sonatype.

8:51 dch: noob question, I'm using `lein repl :connect nrepl:host.name:port` a lot the last few months and after a project upgrade, this seems not to work anymore, but `lein repl :connect host.name:port` does. Is this leiningen that changed, or the project I'm using?

8:55 dnolen: stuartsierra: sweet, thanks!

9:16 djcoin: Are their macro composability problem in clojure ? I have no clue about that but I heard someone on an other chan talking about "fortified macro" in racket for example. Any thought on this subject ?

9:18 nDuff: djcoin: Macros can't be composed in the same way functions can, correct. That's not a problem in any way specific to Clojure, and if Racket has a solution to it, I'm very curious to see it.

9:20 djcoin: nDuff: Well i don't have any links to give you :) I went directly asking there about this as one of the goal of clojure is composability whatever the subject

9:23 nDuff: djcoin: Macros can certainly be composed from other macros. Composing macros and functions together is something of a mess by-definition, and I don't see how one could possibly "fix" it.

9:24 jxx: djcoin: Clojure's macros excel at /that/ kind of composability. (You're conflating function-composition, a mathematical concept, with composabilty, the ease of building things out of smaller components).

9:24 nDuff: djcoin: ...now, if one had both function and macro implementations of a thing, and used the appropriate one in the given circumstances, that would be a workaround applicable in some cases, and is also something Clojure supports (see definline).

9:25 jxx: (e.g. in Clojure I can easily build macros on top of macros and more macros, to a degree that I wouldn't dare, say, in Common Lisp...)

9:26 djcoin: jxx: what make it more composable ?

9:27 nDuff: djcoin: ...to be clear, my answer was predicated on an assumption that we were talking about function composition.

9:27 jxx: djcoin, in the sense that you can build big Xs out of smaller Xs...

9:29 nDuff: djcoin: That is, you can certainly use macros and functions together; you can't use function composition to combine a function and a macro into a new function.

9:29 dnolen: djcoin: Racket's macro system is considerably more sophisticated/complex then Clojure's.

9:30 djcoin: nDuff: right :)

9:30 dnolen: djcoin: I think you could convincingly argue Racket's system is more composable at some cost to simplicity and ease of use.

9:33 jxx: Well, if ease-of-use is no object, then *anything's* composable... >:D

9:34 djcoin: dnolen: unfortunately, apart from toy examples, i ahve no experience of racket. But I guess they aimed for composability/simplicity too

9:35 dnolen: are you familiar with their (fortified) macro system ?

9:36 jxx: djcoin: really? http://docs.racket-lang.org/guide/macros.html

9:37 djcoin: jxx: maybe this http://lambda-the-ultimate.org/node/4071

9:37 jxx: Racket comes from Scheme, which is simple in nearly every way *except* macros...

9:39 djcoin, that might be simple by L:tU standards, but that way lies madness...

9:39 silasdavis: any contraindications for using isa? as a defmulti dispatch function?

9:41 I have a page rendering function that I was considering accepting a hashmap {:content "blah" :footer "bleh"} or otherwise assume whatever is passed belongs as the :content

9:41 is it wise to overload the same function for this

9:41 ?

9:42 stuartsierra: silasdavis: multimethods already use `isa?` to compare dispatch values.

9:42 jxx: (my bias has always been for Lispy macros and against Schemey syntax-blarg (while recognizing the usefulness of a modicum of hygiene), so I'm enjoying Clojure immensely...)

9:44 dnolen: djcoin: only passing familiarity having the seen the paper on fortified macros.

9:44 silasdavis: stuartsierra, so I wouldn't write: (defmulti foo isa?) ?

9:45 stuartsierra: silasdavis: `isa?` returns true or false, so I don't see how that's going to be very useful.

9:45 dnolen: djcoin: Racket is very cool, though I would say overall it has a bit more of an academic / research focus than Clojure does. It's considerably older as well, 1995?

9:46 jxx: dnolen, close. Racket was PLT-Scheme; 1994.

10:02 silasdavis: can I convert a keyword to a symbol?

10:03 I was hoping something like (symbol (type {})) would work

10:03 AimHere: ,(symbol :foo)

10:03 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String>

10:03 stuartsierra: ,(symbol (name :foo))

10:03 clojurebot: foo

10:05 silasdavis: sorry I'm using the wrong word, I think I mean a symbol

10:05 what does (type {}) return?

10:05 mikerod: ,(type {})

10:05 clojurebot: clojure.lang.PersistentArrayMap

10:06 stuartsierra: That's a Java class.

10:06 silasdavis: a reference to itself I suppose, but how could I get that as keyword

10:08 mikerod: ,(keyword (.getName (type {})))

10:08 clojurebot: :clojure.lang.PersistentArrayMap

10:10 silasdavis: ,(symbol (name (keyword (.getName (type {})))))

10:10 clojurebot: clojure.lang.PersistentArrayMap

10:10 silasdavis: mikerod, ah thanks, I think that straigtens me out

10:12 AimHere: ,(symbol (.getName (type {})))

10:12 clojurebot: clojure.lang.PersistentArrayMap

10:12 mikerod: silasdavis: I'm not sure what you are wanting to accomplish there, but no problem.

10:12 ,(type (type {}))

10:12 clojurebot: java.lang.Class

10:12 silasdavis: getting symbols and keywords the right way round is a start

10:13 mikerod: silasdavis: `type` is just returning a java.lang.Class.

10:20 silasdavis: how is the following multimethod meant to work:

10:20 (defmulti foo class)

10:20 (defmethod foo ::collection [c] :a-collection)

10:21 from the clojure docs

10:21 then apparently:

10:21 (foo [])

10:21 :a-collection

10:21 ,(class [])

10:21 clojurebot: clojure.lang.PersistentVector

10:24 silasdavis: ,(isa? (class []) ::collection)

10:24 clojurebot: false

10:25 trptcolin: silasdavis: are you referring to http://clojure.org/multimethods ?

10:25 silasdavis: trptcolin, yes

10:25 trptcolin: there's a bit on `derive` above the code you're looking at that sets up the hierarchy involving ::collection

10:26 [that is, ::collection means nothing by itself, you have to write code to make it mean something]

10:27 gfredericks: has anybody used the multimethod inheritance stuff for realsies?

10:27 trptcolin: gfredericks: no.

10:27 ;)

10:28 Pupnik--: has anyone use macros for realsies? (for something you couldnt just use a function for anyway)

10:28 gfredericks: um

10:28 TimMc: Pupnik: No such thing.

10:28 gfredericks: that question totally hinges on "just use"

10:28 Pupnik: i leave it up to the reading to make that judgement

10:29 if you used a macro, do you believe it offered a substantial advantage over a function alternative

10:29 reader

10:29 not reading

10:33 nDuff: Pupnik: You use macros all the time. "and" is a macro. "or" is a macro.

10:33 Pupnik: thats not what i mean, as i am sure you are away

10:33 nDuff: Pupnik: In those cases, the advantage offered is short-circuiting behavior.

10:33 Pupnik: wow my typing is awful tonight

10:33 That is not what I mean, as I am sure you are aware.

10:34 nDuff: Pupnik: ...It's exactly the point I'm making, though. Macros are most useful for language extensions.

10:35 gfredericks: Pupnik: macros can reduce syntactic ceremony in a way that functions can't

10:35 Pupnik: that is true gfredericks

10:35 i wasn't asking what they do, just if anyone has used them

10:35 gfredericks: people use them all the time

10:35 nDuff: Pupnik: ...now, have I sometimes seen fit to write custom language extensions? Certainly.

10:36 gfredericks: every significant project I've participated defines a few macros for one thing or another

10:36 Pupnik: ok

10:36 nDuff: Pupnik: ...for instance, I have one which builds accessors for JIRA service components.

10:36 Pupnik: tahts good :)

10:36 gfredericks: macros take the pressure off the language designer to include every conceivable useful feature

10:37 nDuff: Pupnik: ...makes what would have been a huge chunk of code down to two words per service.

10:37 Pupnik: ...and it's a very domain-specific thing; wouldn't be justified elsewhere.

10:37 gfredericks: Pupnik: https://github.com/fredericksgary/catch-data

10:37 that library consists of a single macro

10:40 silasdavis: If I want to dispatch based on whether something is a map, a keyword, or something else, what's the best way to do it?

10:42 trptcolin: maybe start w/ multimethods using clojure.lang.IPersistentMap, clojure.lang.Keyword, :default as dispatch values?

10:43 silasdavis: trptcolin, am I right to think I need a (defmulti foo class) for that..?

10:43 or can I just right the (defmethod ..)s

10:43 trptcolin: class or type; type is slightly more flexible

10:43 silasdavis: why is that?

10:44 trptcolin: ,(doc type)

10:44 clojurebot: "([x]); Returns the :type metadata of x, or its Class if none"

10:44 silasdavis: ah thanks

10:46 gfredericks: ,(-> [] (with-meta {:type :foo}) type)

10:46 clojurebot: :foo

10:46 gfredericks: ,(-> [] (with-meta {:type nil}) type)

10:46 clojurebot: clojure.lang.PersistentVector

10:52 silasdavis: why would you want to use :type metdata over defrecord?

10:54 trptcolin: mostly to prevent technomancy's hair catching on fire

11:01 silasdavis: anyone got a clue what might cause "No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil

11:01 "

11:01 using lein ring server...

11:02 weavejester: silasdavis: You're trying to make an io/reader out of nil

11:02 silasdavis: This can happen if you're using io/resource

11:03 silasdavis: Which returns nil if the resource is not found.

11:04 silasdavis: weavejester, thank you!

11:26 ppppaul: nil is the best reader

11:45 gfredericks: silven: I'm actually considering using it for vectors, which defrecord would not be an equivalent drop-in for

11:45 also if you want to use the inheritance facilities in multimethods I think :type metadata is the way to go

11:46 dnolen: lynaghk: new release of CLJS out w/ fix for your issue the other day

12:11 ticking: loooooool

12:13 silasdavis: does anyone know how to insert a node with laser?

12:13 ticking: die telekomiker geben jetzt geld aus um ihre kupferkabel mit kuenstlicher dna zu sichern

12:13 hyPiRion: ticking: I think you accidentally the channel.

12:14 ticking: damn wrong channel sorry -.-

12:14 silasdavis: I've tried (l/id= "login-form") (l/insert :left (l/parse-fragment "<p>hello</p>"))

12:15 but it complains that it's not a valid node

12:15 ticking: hyPiRion yeah I accidentally all the things ^^

12:15 silasdavis: Raynes, don't suppose you're about...

12:15 Raynes: silasdavis: Yep.

12:16 silasdavis: It's your lucky day because I'm having such a bad day. I wouldn't be awake right now on any other day.

12:16 silasdavis: ah great, I was just wondering how I can insert something with laser

12:16 ucb: cemerick: are you parsing regexes like (\w) is (\w) for @imho?

12:16 Raynes: Just a sec

12:16 silasdavis: oh dear

12:17 cemerick: ucb: no regexes; it's clojure-opennlp + some core.match stuffs

12:17 ucb: cemerick: cool :)

12:17 cemerick: heh, we'll see

12:17 Raynes: silasdavis: Are you creating the node that you're trying to insert? Does it come from an HTML file somewhere?

12:18 ucb: well, I recall doing something along those lines some time ago; matching regexes like the one above and then creating a graph of "is" relationships; once you have some stable nodes you can start matching for other types of relationships for those nodes

12:18 cemerick: I was curious whether you were going down the same route

12:18 silasdavis: Raynes, in this case it comes from an html file

12:19 what I really want to do is match a node and append as the last child

12:19 Raynes: Yeah, we can do that. I'm trying to remember how. ;)

12:23 silasdavis: (document (parse "<div><p>foo</p></div>") (element= :div) #(update-in % [:content] into (nodes "<p>hello</p>")))

12:24 silasdavis: This could be a sign that an 'append' transformer is in order.

12:25 silasdavis: thanks... might be useful

12:25 also insert is listed in the api

12:25 but I can't find the source...

12:25 Raynes: silasdavis: insert puts the node either to the left or right of the matched node. If your example had worked, it would have resulted in "<p>hello</p>…login-form stuff"

12:26 silasdavis: ah it's because the api docs link to an old commit

12:26 Raynes: (document (parse "<div><p>foo</p></div>") (element= :div) #(update-in % [:content] into (nodes "<p>hello</p>")))

12:26 Bah

12:26 https://github.com/Raynes/laser/blob/master/src/me/raynes/laser.clj#L228

12:26 Yeah, I need to update the API docs.

12:26 silasdavis: Raynes, my example didn't work, can you see what's wrong wiht it?

12:27 Raynes: Yes. parse-fragment returns a seq of nodes and insert expects a single node.

12:27 (first (parse-fragment ..)) might have made it work./

12:28 silasdavis: ah insert docstring says "Inserts node(s) in direction which can be..."

12:28 Raynes: Hrm

12:28 silasdavis: also looks like it has stuff to handle sequence

12:28 (if (sequential? nodes) ...)

12:31 Raynes: silasdavis: I'm looking into it. Good catch.

12:32 Oh, I see.

12:32 silasdavis: It's because parse-fragment returns a seq of zippers, not just nodes. You'd want to call the 'nodes' function on it instead.

12:32 (document (parse "<div><p>foo</p></div>") (element= :div) (insert :left (nodes "<p>hello</p>")))

12:32 silasdavis: ^ This works.

12:33 Doesn't do what you want, of course, but it does work like it is supposed to.

12:33 silasdavis: Raynes, thanks, yeah I didn't think it would do what I wanted, but I thought if I could understand how it worked I could do what I wanted

12:34 and thanks for the library

12:34 Raynes: silasdavis: If you need anymore help with anything let me know. :)

12:35 silasdavis: actually one other thing, I was wanting to conditionally perform one select-transform or another depending on whether the user was logged in

12:36 I tried doing this in the defdocument macro which unsurprisingly didn't work

12:37 I think the way to go is to move the conditionality into the transformation function, and make the selector 'static' (i.e. not conditional)

12:37 I guess I could drop the use of the defdocument, but I think I want the parse caching

12:37 is this the right approach?

12:38 Raynes: You can do things like (defdocument … (if logged-in [(element= :something) (transform)]))

12:38 Will that help?

12:39 silasdavis: oh yes

12:39 I tried (when logged-in (selector) (transformer))

12:39 Raynes: silasdavis: https://github.com/Raynes/refheap/blob/master/src/refheap/views/paste.clj#L79

12:39 Here is an example

12:39 silasdavis: but I guess that will return (transformer)

12:39 Raynes: Yup.

12:39 * silasdavis is still learning clojure

12:39 Raynes: No worries!

12:39 That's what this channel is for. :)

12:41 trptcolin: i've got a domina event listener fn in which i'd like to swap! a closed-over atom. but i'm getting "No protocol method IWatchable.-notify-watches defined for type"

12:42 dnolen: trptcolin: what version of CLJS?

12:42 trptcolin: and can you recreate the issue w/ a minimal setup?

12:42 trptcolin: looks like 0.0-1586

12:42 dnolen: trptcolin: i.e. no domina or anything

12:43 trptcolin: try 0.0-1803

12:43 trptcolin: cool, will try that first

12:44 ambrosebs: tools.cli and core.typed work nicely together https://gist.github.com/frenchy64/5526264

12:45 dnolen: ambrosebs: neat

12:45 ambrosebs: dnolen: :)

12:47 silasdavis: Raynes, I tried (l/id= "login-form") (l/insert :left (l/nodes (l/parse-fragment "<p>hello</p>"))) as you suggested (just to try and get insert working)

12:47 but I get the same error:

12:48 Exception in thread "main" clojure.lang.ExceptionInfo: Not a valid node: [{:type :element, :attrs nil, :tag :p, :content ["hello"]} nil] {:dom [{:type :element, :attrs nil, :tag :p, :content ["hello"]} nil]}

12:50 Raynes: silasdavis: Don't call parse-fragment at all.

12:50 Just l/nodes

12:56 silasdavis: Raynes, so that works for that example, but actually my notes are coming from a file. Line 27: https://www.refheap.com/paste/14219

12:56 trptcolin: dnolen: looks like the same error after updating, and seeing a couple wacky bits, one in clojurescript.test (can look there for update), and (js->clj (clj->js {})) ;=> {"" nil}

12:57 i'll open a jira ticket for that last one if you agree it's a problem, and will eventually work up a repro case for the watcher error i'm seeing

12:57 silasdavis: where partial-template calls l/parse-fragment

12:58 Raynes: silasdavis: You have to call l/nodes there instead. You should be able to call it on the resource just the same. You might need to add another function for it like partial-template but that calls l/node instead of l/parse-fragment.

12:58 dnolen: trptcolin: yeah open a ticket for the data conversion bug

12:58 trptcolin: http://dev.clojure.org/jira/browse/CLJS-504

12:59 dnolen: trptcolin: and another for the atom bug with a minimal example

12:59 silasdavis: Raynes, when should partial-fragment actually be used?

12:59 dnolen: trptcolin: you might want to ping cemerick about clojurescript.test, I moved things around so we could have easily introduced other small regressions - would be great to get test cases for all these since they weren't picked up by the ones we have.

13:00 Raynes: silasdavis: When you need something to give to fragment

13:04 trptcolin: dnolen: yep, that's my plan. the clojurescript.test thing that was immediately showing up was just about how each deftest name is printed [Object object]; maybe something around Symbol stringifying, but i'd have to look closer to find out for sure. gonna roll back and look for a workaround in the shorter term

13:05 redline6561: Hey folks. I'm having issues porting a common lisp lib to clojurescript. Could anyone help me see what I'm doing wrong? I'm having real trouble with my defaddress macro. https://github.com/redline6561/cljs-6502/blob/master/src/cljs/cljs_6502/addressing.cljs

13:06 dnolen: trptcolin: the persistent data structures no longer implement toString

13:07 technomancy: redline6561: is that ... named after the chip?

13:07 O_O

13:07 redline6561: Yes it is.

13:07 trptcolin: dnolen: this should just be a Symbol. or are you including that in the persistent data structures"

13:07 technomancy: 6502 is on my list of languages to learn

13:07 (not anywhere near the head, mind you)

13:08 trptcolin: dnolen: nm, i can just REPL it :)

13:08 redline6561: technomancy: The cl lib may interest you then! I thought it would be a fun port but clojurescript macros are... a bit different. ;) http://github.com/redline6561/cl-6502

13:08 dnolen: trptcolin: oh probably an oversight

13:08 trptcolin: ok, must be something strange under the hood, because (.toString 'foo) works just fine

13:09 dnolen: trptcolin: what about (pr-str 'foo) ?

13:09 trptcolin: good also

13:11 dnolen: yeah, ok, it's a list under the hood

13:11 probably because of nested (testing) forms

13:13 dnolen: redline6561: what's the problem?

13:14 mikerod: Is it a bad idea/inefficient to repeatedly call reify? Such as to fill a list of objects that all implement some protocol/s or some interface/s the same way. e.g. (map #(reify MyProto (foo [_] %)) some-list)

13:15 dnolen: mikerod: reify creates a class, so you just paying for creating an object

13:16 redline6561: dnolen: lein cljsbuild once works but trying to use nrepl.el and load the file (w/ C-c C-l) blows up saying: "clojure.lang.ExceptionInfo: Assert failed: set! target must be a field of symbol naming a var targetexpr at line 13"

13:16 Which is pretty confusing as neither my defaddress macro nor any of the calling code uses set!

13:16 dnolen: redline6561: lots of moving parts. does lein cljsbuild auto work?

13:17 redline6561: Haven't tried. One sec...

13:17 technomancy: why are there three separate lein invocations on https://github.com/magomimmo/modern-cljs/ ?

13:17 mikerod: dnolen: So if in my example (map #(reify MyProto (foo [_] %)) some-list), if (count some-list) ;= 100 , does that mean that there would be 100 different classes created as well as the 100 different objects?

13:18 dnolen: mikerod: 1 class

13:18 redline6561: technomancy: i wondered the same thing reading through it recently.

13:18 dnolen: 100 objects

13:18 * redline6561 is not certain the one true cljs tutorial exists yet

13:18 technomancy: I'm trying to help someone out who is using cljs and that page looks really complicated and confusing

13:18 and it uses lein-ring =(

13:19 mikerod: dnolen: repeated calls to reify for the same protocols/interfaces and function implementations knows to create only a single class?

13:19 dnolen: mikerod: yes

13:19 gfredericks: man java.jdbc's insert! has a weird API

13:19 technomancy: what happened to emezeske anyway; I haven't seen him in ages

13:19 mikerod: dnolen: Oh, that is interesting.

13:20 dnolen: technomancy: haven't seem him on channel but I see deals w/ issues & pull request on GitHub for lein-cljsbuild

13:22 redline6561: dnolen: ... lein cljsbuild auto doesn't want to halt.

13:23 cpu usage has stopped however. just sitting there eating memory.

13:23 technomancy: man; I don't want to write a jeremiad against lein-ring but I feel like if people keep getting confused by it I will have no choice

13:23 dnolen: redline6561: you have to edit the file to trigger a re-compile - i.e. modify some whitespace.

13:23 technomancy: attn: run-jetty is *not* special. it's just a function. call it like one. the end.

13:24 redline6561: ah, i see. neat. It encounters the same error btw.

13:24 dnolen: redline6561: auto avoids JVM startup time and allows the JVM to warmup so subsequent compiles are much faster.

13:24 redline6561: dnolen: Very cool. Thanks for the tip.

13:24 TimMc: $seen emezeske

13:24 lazybot: emezeske was last seen quitting 15 weeks ago.

13:24 redline6561: Still have no idea why this macro blows up when I use it in cljs though: https://github.com/redline6561/cljs-6502/blob/master/src/clj/cljs_6502/macros.clj#L3

13:25 This seemed the most natural way to port the cl code.

13:29 dnolen: redline6561: hmm can't look at it more closely, looks like fairly portable Clojure code did you try it in Clojure?

13:29 `fogus: redline6561: What's the explosion?

13:29 cemerick: trptcolin: Looks like those PR's are breaking the build?

13:30 trptcolin: womp womp

13:30 `fogus: redline6561: Those `mode` params look suspicious

13:30 redline6561: dnolen: Just requiring and

13:30 cemerick: whoa, travis' lein isn't seeing the 'all' alias o.O

13:30 redline6561: * macroexpanding it in the clojure repl "worked" fine.

13:30 `fogus: How so?

13:31 dnolen: redline6561: they'll get namespace resolved, you probably want mode#

13:31 redline6561: Ah, I'm dumb. Good call.

13:31 `fogus: redline6561: Do you refer to mode in your bodies?

13:31 redline6561: Sorry for dumb questions. Still getting used to things.

13:31 `fogus: No.

13:31 `fogus: redline6561: No apologies needed.

13:32 redline6561: So what dnolen said should be a start

13:33 redline6561: Likewise, the `cpu` and `val` params. Are they referenced in the `body`?

13:34 redline6561: `fogus: Those will be, yes.

13:34 The working CL this is a port of is here: https://github.com/redline6561/cl-6502/blob/master/src/addressing.lisp

13:35 Basically, I have a simple protocol in cljs and want to extend it with a macro.

13:35 `fogus: redline6561: Clojure will ns resolve those bare symbols. You'll need the magic anaphora sauce to refer to those

13:36 redline6561: Aha.

13:36 austinh: Is there an easy way to copy resource files to an output dir using `lein cljsbuild`?

13:40 trptcolin: cemerick: hrm, i'm seeing these tests as passing locally, fwiw

13:40 there's some weirdness around fixtures (the name munging doesn't seem to match up w/ how the fixtures are looked up), but i don't see that exposed in the tests until this new one i have locally

13:41 [not new weirdness afaict]

13:43 gfredericks: I just walked up and read (out of context) fogus's line "Do you refer to mode in your bodies?" as if it were some weird mystical thing

13:44 technomancy: are the docs for lein-cljsbuild pretty comprehensive/trustworthy?

13:45 gfredericks: I don't recall feeling hostile toward the docs at any point

13:46 technomancy: seems like a pretty big pile of moving parts but I guess a lot of that is to work around JVM boot time

13:47 dnolen: technomancy: I think they are

13:48 trptcolin: dnolen: this feels like the underlying issue of that js->clj thing: (for [k (js-keys (js-obj))] k) ;=> (nil)

13:48 but maybe there's a solid js/cljs reason for it that i don't see yet?

13:49 dnolen: trptcolin: looks like a bug

13:49 trptcolin: k cool, i'll pursue that direction

13:49 dnolen: trptcolin: (js-keys (js-obj)) => #<Array [nil]>

13:49 that's the bug

13:50 trptcolin: ticket welcome

13:50 trptcolin: even lower down: (for [x (array)] x) ;=> (nil)

13:51 i'm assuming i'll attach this detail to the one i created earlier, cljs-504

13:52 dnolen: trptcolin: I think these are seperate issues

13:52 tieTYT2: i just got an email from my project manager that I'm not allowed to write any more clojure code (We're a java shop)

13:52 trptcolin: ok, but one will fix the other

13:52 dnolen: (array) prints as #<Array [nil]> but count return 0

13:52 so that's a printing problem

13:52 trptcolin: right

13:53 tieTYT2: what do I do?

13:53 dnolen: (for [x (array)] x) returns a seq count 1

13:54 gfredericks: that sounds like an issue from like 6 months ago o_O

13:54 around the PrimSeq type or something like that

13:55 trptcolin: dnolen: so seems like the ICounted implementation is correct, but whatever allows traversal is not

13:56 dnolen: gfredericks: maybe but I doubt it

13:56 gfredericks: sure I doubt it's a regression; just eerily similar

13:57 dnolen: quite a few things changed at the same time - array & strings are handle directly and not via protocols in core fns. for/doseq got chunked seq support, printing details changed.

13:57 so could be any of those.

13:57 kaw: Is there any way I can get better error messages in emacs / nrepl? Right now I'm getting an IllegalArgumentException when trying to C-c C-k a file, and the only line number reference I'm seeing is to the compiler code, "clojure.lang.RT.seqFrom (RT.java:505)"

13:58 I'm sure the actual error is something silly and easy to resolve, but it's hard to spot when I have to look through a whole file to find it

14:00 dnolen: kaw: you probably have a malformed ns expression, or a malformed def

14:01 kaw: Yeah, probably, I've seen a similar error before in Clojure

14:01 But I really want to know how to get a line number, not how to fix this particular error

14:01 Or to print the problematic form or whatnot

14:01 dnolen: kaw: there no way to improve that error w/o patching the compiler

14:02 kaw: Huh, okay

14:03 Well, I guess I can tolerate a little bit of terribleness for a lot of fairly-nice-ness

14:05 technomancy: you build up an immunity after a while

14:05 well

14:05 more like a numbness

14:05 aaelony: lacij is awesome… just sayin'

14:05 technomancy: stub your toe often enough and eventually you stop feeling it

14:06 kaw: Heh, yeah, I've been there with other languages

14:06 dnolen: kaw: or send a patch that gives line numbers. I've made a few fixes to ClojureScript to provide more line number and file information where possible - it really helps.

14:06 Raynes: technomancy: I don't think that's true.

14:06 technomancy: Raynes: ymmv =)

14:06 dnolen: kaw: ClojureScript can probably do even more when we switch readers

14:06 Raynes: technomancy: Maybe if you somehow bash the nerves dead in your toe.

14:06 kaw: dnolen: I'll try to remember it when I feel comfortable enough to start patching the compiler :)

14:06 trptcolin: dnolen: i tracked it down to (seq (array)) ;=> (nil) - and also (seq "") ;=> (nil)

14:07 technomancy: I was amazed that racket's various beginner languages actually provide customized error messages tuned to beginners.

14:08 trptcolin: i know how a patch to cljs.core/seq would work, so i can attach that to the ticket. if you feel like the patch belongs in IndexedSeq instead maybe we can work that out in jira (gotta take off here)

14:09 dnolen: trptcolin: oops right, I see the issue.

14:09 trptcolin: no patch to IndexedSeq, just check that alength != 0

14:10 trptcolin: do strings have a fast length fn as well? i was assuming i'd use (count) for both, but yeah, can skip that extra fn call, that's fine

14:10 ah, .-length

14:11 dnolen: trptcolin: or alength

14:11 hiredman: was the ability to comment on the clojure confluence wiki disabled?

14:11 dnolen: hiredman: don't think so

14:11 hiredman: I can see comments, and see my old comments, but I can't seem to make new comments

14:12 trptcolin: dnolen: alength is no good for strings afaict, but yeah, will use that for the array side

14:13 oh, derp, the cljs fn

14:13 got it

14:13 hiredman: dnolen: can you try and comment and see if it works? (or even if you can find the input box to do it?)

14:14 technomancy: note that you don't seem to be able to delete comments last I checked

14:14 so make it count =)

14:14 dnolen: trptcolin: it works for strings

14:15 trptcolin: yep, for some reason i had .alength in my head

14:15 dnolen: trptcolin: alength just compiles down the .-length anyway

14:15 hiredman: technomancy: could you check?

14:15 dnolen: down to

14:15 hiredman: technomancy: if you can find a text input for leaving comments

14:16 dnolen: hiredman: I've been commenting on the specify CLJS has worked fine me all weekend

14:16 technomancy: hiredman: yeah, I can't comment either

14:17 nor edit pages, it appears

14:17 hiredman: :/

14:17 technomancy: shame since the emacs page still recommends inf-lisp and slime

14:18 should probably replace the whole thing with a clojure-doc.org link

14:18 dnolen: just tried editing, seems to work

14:18 hiredman: dnolen: you must have a magic set of permissions the plebes don't

14:22 austinh: Here's my latest ClojureScript work: http://pettomato.com/games/restaurant/drawing_demo_1/

14:22 (Not actually a lot of cljs, but I'm really enjoying it.)

14:24 redinger: Fixing up your permissions hiredman and technomancy. Anybody else while I'm at it? :)

14:25 technomancy: doesn't seem to have changed?

14:25 oh, there we go

14:25 redinger: it's sloooooow.

14:26 hiredman: redinger: thanks

14:26 pretty little "add comment" button :)

14:27 technomancy: still no "delete spam comments" button

14:27 redinger: Hmm, I'm not sure where the comments permissions even are

14:27 technomancy: but I guess it doesn't matter if it's just forwarding to clojure-doc

14:27 don't worry about it

14:29 silasdavis: how can splice a list into another list at the nth position like (splice 2 [:u :v] [1 2 3 4 5]) -> [1 2 :u :v 3 4 5]

14:29 ?

14:30 gfredericks: silasdavis: with careful use of split-at and concat

14:31 assuming you don't care if you get a vector back

14:32 pl6306: I am running windows. I would like to start the clojure repl from the command prompt with a directory added to the classpath. How do I do that?

14:33 redinger: Found it!

14:33 Glenjamin: weavejester: cheers for the merge, sorry about the commit length - I was lazy and typed it onto the command line without checking :)

14:34 weavejester: Glenjamin: No problem. I'm just really picky about pull requests :)

14:34 Well, I guess less picky than big projects

14:36 Glenjamin: is there a reason ring-mock isn't part of the ring-clojure org?

14:37 weavejester: Glenjamin: No, I'm been meaning to do it.

14:37 Glenjamin: Oh, since you're here...

14:37 Glenjamin: i've got a branch going that has the tests passing on 1.5 and adds the lein profile if you'd like me to tidy up and push - there were some issues with order of hash maps

14:38 weavejester: Would it be a big problem just to slim down the commit message with a git --amend and then git push -f?

14:38 Glenjamin: not at all

14:38 silasdavis: gfredericks, i'd like the same type back like with inio

14:38 into

14:39 weavejester: Glenjamin: I'd also be happy to accept a 1.5 test pull request

14:39 Glenjamin: cool, i've re-pushed that commit now

14:39 is it worth me adding a travis yml as well, or is that best left to you?

14:40 gfredericks: silasdavis: that would take more manual effort I think

14:51 dnolen: austinh: neato!

14:51 austinh: re: game

14:52 gfredericks: austinh: I get script-running-forever errors in FF

14:53 trying to avoid passing DB connections around with the new java.jdbc API kind of precludes using transactions

14:55 austinh: dnolen: Thanks.

14:55 avishai: hi

14:55 noob question about style

14:55 austinh: gfredericks: I believe I just fixed that.

14:55 hiredman: win 15

14:55 avishai: any takers?

14:55 gfredericks: ~anyone

14:56 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 ..."

14:56 dnolen: austinh: I'm impressed your giving a go w/ ClojureScript for this instead of JS

14:56 Glenjamin: avishai: just ask, and see if you get an answer, tis the IRC way

14:57 avishai: suppose i have a variable that starts with one value

14:57 austinh: dnolen: I've gone back and forth, but this time around cljs was a lot easier than my last JS experiments, and I'm going to try to use pedestal, too.

14:57 avishai: then alter initialized to another value

14:57 e.g. starts as nil

14:58 austinh: dnolen: I also wasn't sure if it would be a single page app at first, but now that seems certain.

14:58 avishai: in a sense you can say it's "state"

14:58 seangrove: austinh: looks very cool, what's the cljs script output size?

14:58 avishai: i can't use def

14:58 seangrove: Our app is ~400k, which is pretty considerable

14:58 avishai: so do i need an atom?

14:58 Glenjamin: avishai: can you give a concrete example of why you init to nil?

14:58 gfredericks: avishai: s/alter/later/?

14:58 seangrove: avishai: Sure, why not def an atom?

14:58 dnolen: austinh: neat

14:59 TimMc: avishai: Atom/ref, or possibly use binding if the change can be thread-local.

14:59 avishai: that's what i did

14:59 can i rebind?

14:59 i thought binding was for inner scope

14:59 austinh: seangrove: 1009b right now, but this is only a tiny piece of the app.

14:59 gfredericks: you swap! the atom to update is value

14:59 austinh: seangrove: Sorry, 109kb

14:59 Glenjamin: ,(doc binding)

14:59 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

15:00 seangrove: austinh: Hah, ok, I was going wide-eyed at how you got a cljs build down to 1k :)

15:00 avishai: don't think i can use binding

15:00 Glenjamin: but if it only ever has nil, or the new value - there might be a way to avoid having it be nil

15:00 gfredericks: avishai: you use swap! to change an atom

15:00 avishai: yes, that's what i did

15:00 the scenario is i use sns

15:00 dnolen: seangrove: I'm assuming you're gzipping?

15:00 seangrove: dnolen: Yeah, definitely

15:01 avishai: so i need to register an sns

15:01 seangrove: Just the initial output is large

15:01 avishai: topic

15:01 dnolen: seangrove: how many LOC is the original CLJS?

15:01 avishai: which is later used in other functions

15:01 seangrove: dnolen: ~4k

15:01 avishai: can't pass the variable via function call since sns uses http callbacks

15:01 seangrove: But it makes use of a lot of the google closure libs, especially the ui libs

15:01 avishai: need to keep this internal

15:02 Glenjamin: avishai: i see, that's a common scenario - you can either use an atom - but then you only get one "instance" per application

15:03 or you can use a ^:dynamic var, and provide a (with-sns {:config :values} ~@body) macro that uses (binding)

15:03 or you can have require the config var to be passed into your functions which need it

15:04 or you can have a factory-like function which returns a function that closes over the config and can then be called

15:05 dnolen: seangrove: well 400K sounds pretty good for 4KLOC of CLJS, that's a pretty big CLJS app!

15:05 avishai: Glenjamin, how do i initialize the var from a function?

15:05 seangrove: dnolen: I suppose. We just started the SF Clojurescript meetup, probably have the first meetup next month

15:05 Feel like coming out to give a talk sometime?

15:06 There's a pretty big group of people using it out here at this point

15:06 avishai: i call def from the function?

15:06 Glenjamin: avishai: in which scenario?

15:06 gfredericks: (def my-var (some function to call))

15:06 dnolen: seangrove: oh wait, 400K after advanced compilation?

15:07 seangrove: Yeah

15:07 tomoj: suppose you implement a slow with-bindings* for cljs, which uses maps of var name symbols to vals as binding maps, but leave binding as is. is it impossible to get correct semantics with mixed usage of with-bindings* and binding?

15:07 avishai: (defn init-sns [] (def sns-topic (sns/create-topic topic-nae)))

15:07 and later defn with-init to use this in the binding?

15:08 dnolen: seangrove: w/ prettying printing turned off?

15:09 seangrove: dnolen: No debug, no pretty printing, advanced optimizations => 470k

15:10 gzipping cuts it down, of course

15:10 dnolen: seangrove: that's cool about the SF group!

15:10 seangrove: I'm assuming you're pulling together a lot of external CLJS libs as well?

15:10 Glenjamin: avishai: something like this https://www.refheap.com/paste/14222

15:11 if you're building a web-app, then middleware is usually a good place to use the with- macro

15:12 seangrove: dnolen: Not a huge number of other libs, but a big chunk of the google closure library

15:12 A lot of the network, UI, event, etc. stuff

15:12 dnolen: seangrove: oh, yeah OK, that does sound about right.

15:12 avishai: Glenjamin, wouldn't that macro re-evaluate create-topic every time?

15:12 seangrove: I would really love a report at some point to figure out what require statements are responsible for final output size

15:13 dnolen: the tests in CLJS which touch just about every fn and data structure generates a 630K advanced compiled file

15:13 seangrove: Not sure how you'd track it at this point

15:13 Glenjamin: yeah, does create-topic do expensive work?

15:13 dnolen: that gzips to 96K

15:13 avishai: suppose it does, for argument sake. i'm trying to learn the style

15:14 dnolen: seangrove: having lots of requires doesn't really matter, Closure will dead code eliminate anything you don't use.

15:14 seangrove: dnolen: Sounds similar to us, gzip takes it to ~130kb

15:14 Glenjamin: avishai: if you look at the examples in https://github.com/jgrocho/clj-gntp

15:14 seangrove: dnolen: That's what I mean - I want to know what code I'm using is causing the largest impact on file size

15:14 Maybe I'm only using a few functions from a google closure require, but that adds another ~20kb, for example

15:15 Hard to tell at this point... cutting down on the app size (if we have to) is going to take a lot of trial and error

15:15 Glenjamin: that's a different style, but i think it works well for letting apps do init work via a library

15:15 muhoo: i vaguely remember a way in destructuring to get all the args as args. something like (defn wrapper [& :as args] (wrap (apply stuff args))) ?

15:16 seangrove: It's not the biggest deal, but cringing a bit at the thought of having to do it under pressure

15:16 muhoo: without using a macro

15:16 dnolen: seangrove: at 4KLOC of CLJS you're probably using a lot of CLJS, most of the weight really comes from the data structures.

15:16 seangrove: Ah, I see

15:17 Well then, compiled-code growth should be fairly slow from here on out then :)

15:17 Glenjamin: muhoo: that will work without :as

15:17 dnolen: and many of data structures are kind of tangled together necessarily

15:17 Glenjamin: ,((fn [& args] args) 1 2 3 4)

15:17 clojurebot: (1 2 3 4)

15:17 dnolen: ObjMap required PersistentHashMap requires TransientHashMap etc

15:18 so just writing {}, pulls in a lot of code

15:18 muhoo: Glenjamin: Unable to resolve symbol: args in this context

15:18 seangrove: Well, ~150kb deliverable is acceptable, and if we've already incurred most of the cost at this point, it should be fine

15:18 muhoo: Glenjamin: try actualy using the args inside the fn. they're optional, so they can't be used

15:18 seangrove: Is it documented somewhere though? Would have been nice to know so I wasn't wringing my hands so much. There's talk about eliminating dead code, but it isn't obvious how much it's helped

15:19 svedubois: ;; Is this JavaScript to ClojureScript conversion correct?

15:19 ;;; JavaScript:

15:19 var collection = [];

15:19 collection.pusj ({foo: "a", bar: 1});

15:19 collection.pusj ({foo: "d", bar: 4});

15:19 ;;; ClojureScript:

15:19 Glenjamin: i'm not sure i follow...

15:19 svedubois: (def collection {:foo "a" :bar 1})

15:19 (def collection {:foo "d" :bar 4})

15:19 typo "collection.push"

15:19 SegFaultAX: muhoo: ##((fn [& args] (reduce + args)) 1 2 3 4)

15:19 lazybot: ⇒ 10

15:19 Glenjamin: ,((fn [& args] (apply str args)) 1 2 3 4)

15:19 clojurebot: "1234"

15:20 seangrove: svedubois: No, not really, you're modifying the object in place in js

15:20 You usually wouldn't do that in cljs

15:20 dnolen: seangrove: it's not documented, but Closure just follows the call graph. I've teased things apart a bit in the latest release since I understand better what was causing issues for *trivial* programs

15:20 muhoo: SegFaultAX: Glenjamin huh. ok, great, thanks, that does work. the space between & and args is significant, it seems

15:20 dnolen: Hello World in CLJS now generates ~100 LOC

15:20 gfredericks: I'm deeply confused about how connection pooling could ever possibly work with java.jdbc

15:21 at least the old API

15:21 dnolen: but optimizing real programs like yours - not much more I think we can do, since usage of the standard library really means needed a lot of stuff.

15:21 seangrove: dnolen: Sure, just saying, letting people know that a reasonable cljs app is going to use datastructures, which are a bit heavy, so you're going to end up with ~100kb gzipped pretty quickly, but growth should slow from there

15:21 gfredericks: dnolen: given apparently most things aren't necessary for hello world, I'm terribly curious what _is_

15:22 seangrove: More of the "growth should slow from there" part which is important for allaying fears

15:22 dnolen: gfredericks: the fact that we don't have real keywords, if we get those it'll probably be 1 line of code or close to that.

15:23 Glenjamin: if i'm only going to write a few hundred lines of JS, it's worth knowing how much CLJS i'd get if i went that route instead

15:23 gfredericks: a whole lot

15:23 Glenjamin: I was considering looking at CLJS, but after seeing this discussion i suspect it's not well suited to what i'll be building

15:24 gfredericks: I wonder how useful cljs would be for using the js semantics, but making use of macros and such to get syntactic benefits

15:24 Glenjamin: which is a mostly non-JS app with a few UI niceities

15:24 dnolen: seangrove: well, it's better to hear that from you and other users :) People should blog about their experience with larger codebases.

15:24 gfredericks: Glenjamin: yeah cljs has a significant fixed startup cost in a lot of aspects

15:25 dnolen: Glenjamin: yeah, no win over plain JS - unless you want macros

15:25 Glenjamin: right, it's better suited for large JS applications?

15:25 dnolen: Glenjamin: if you're only writing a hundred lines of JS

15:25 Glenjamin: and if i understood the introduction slides correctly it's good for CLI tools via node?

15:25 gfredericks: dnolen: it's a curious use case for high-perf JS -- using macros to make a whole lot of low-level twiddling manageable

15:26 dnolen: Glenjamin: medium to large. If you're considering using jQuery, Underscore.js, BackBone.js, Ember.js or anything like that - I think CLJS offers a better story in many wyas.

15:26 gfredericks: I haven't really done high-perf JS so I'm just rambling

15:26 Glenjamin: managed to avoid jQuery so far, but might cave in and use zepto

15:26 dnolen: gfredericks: yes, I think low level CLJS wins over low level JS because of macros.

15:27 you can pull some Jim Blinn C++ template meta programming tricks

15:27 * gfredericks knows none of those tricks

15:28 dnolen: http://www.flipcode.com/archives/Faster_Vector_Math_Using_Templates.shtml

15:28 SegFaultAX: Ugh, I came to clojure to get away from template black magic.

15:29 Glenjamin: is that basically advanced loop unrolling?

15:29 svedubois: Could be something like this:

15:29 dnolen: SegFaultAX: macro-hell is real.

15:29 svedubois: (let [{:keys [foo bar]} collection] "a" 1 "d" 4)

15:30 SegFaultAX: dnolen: Yes, yes it is.

15:30 seangrove: Glenjamin: cljs is excellently suited for large, and especially long-running apps

15:32 That link is terrifying

15:34 dnolen: related http://github.com/clojure-numerics/expresso

15:46 huh wow

15:46 mori got really fast

15:46 svedubois: Any suggestion how to convert this?

15:46 var collection = [];

15:46 collection.push ({foo: "a", bar: 1});

15:46 collection.push ({foo: "d", bar: 4});

15:47 to CLJs

15:47 bbloom: dnolen: what's "really fast"?

15:47 dnolen: reducers are better than sequencing JavaScript array ops

15:47 gfredericks: svedubois: doto

15:47 svedubois: unless you want to use cljs data structures

15:47 dnolen: you can of course do that in JS but it's nice they're already there.

15:48 bbloom: 55ms under Node.js to reduce 1-100000 in array, 86ms to do it with PersistentVector

15:48 bbloom: nice!

15:48 is that using a transient under the hood?

15:50 dnolen: bbloom: yeah I started mori before all the data structures and optimizations got in

15:58 SegFaultAX: Will CLJS leverage ECMA 6 when it becomes more widely available? Are people already working on that?

15:59 dnolen: SegFaultAX: what do you see us leveraging?

15:59 SegFaultAX: I don't know I guess. Are there any new features that benefit CLJS?

15:59 Even if only to simplify the implementation.

16:00 bbloom: SegFaultAX: not without complicating the platform support story...

16:00 SegFaultAX: bbloom: Sure, that's always the case with new major versions.

16:02 A better question might be: what features, if any, from ECMAScript 6 will benefit CLJS?

16:02 avishai: Glenjamin, back again

16:03 dnolen: SegFaultAX: I've seen little in ES6 that we could leverage

16:03 avishai: (def ^:dynamic *global-var* ...) is per thread, right?

16:03 dnolen: SegFaultAX: I mostly interested in seeing JS get fast, not get new features

16:04 bbloom: dnolen: i'm with you. i'd be even more interested in JS going away :-P

16:06 callen: dnolen: could you use asm.js?

16:06 dnolen: since you spoke of speed. :)

16:06 dnolen: callen: no GC story

16:07 yet

16:07 SegFaultAX: Would that be a welcomed feature?

16:07 callen: I figured.

16:07 dnolen: SegFaultAX: it could be in the future

16:07 SegFaultAX: but right now, of little use

16:07 bbloom: asm.js is really (at this point) just for numerical code, AFAICT

16:07 but i may be wrong

16:07 SegFaultAX: dnolen: What are the slowest parts of js, out of curiosity?

16:08 dnolen: SegFaultAX: GC, closures, no enough inlining

16:08 at a low enough level, the variance in perf profiles between the different browser is obnoxious

16:09 weird crap like null == x vs. null === x

16:09 SegFaultAX: dnolen: Is V8 categorically better in all cases?

16:09 dnolen: makes a diff on V8 but none on SpiderMonkey, and JavaScriptCore

16:09 bbloom: the bigger issue isn't what particular things are slow, it's that you can kill your perf with no indication of why

16:10 dnolen: SegFaultAX: V8 deals with CLJS better, which is allocation heavy

16:10 SegFaultAX: bbloom: That's mostly a tooling problem though isn't it?

16:10 dnolen: SegFaultAX: no because you don't know, implementations vary

16:11 SegFaultAX: dnolen: Does the standard specify memory managment? Is it just simple reference counting?

16:11 bbloom: SegFaultAX: it's a little harder than that… there is a fundamental attribution problem…. there is no way to match slowness to perf bugs without an absurd level of noise

16:11 dnolen: SegFaultAX: however the arms race has made some kind of operations uniformly fast. object/array access, array iteration, function call overhead

16:12 SegFaultAX: Are there low level profiling tools for V8 or spider monkey?

16:13 dnolen: SegFaultAX: probably, but I just use the browser + command line benchmarks

16:13 trinary: this came out recently: https://trace.gl/

16:13 looks fun.

16:13 dnolen: SegFaultAX: I mean for V8, I don't know of anything for SM or JavaScriptCore

16:13 SegFaultAX: Lame.

16:14 dnolen: Does CLJS make any browser specific optimizations?

16:14 dnolen: SegFaultAX: nope

16:17 brainproxy: dnolen: have you experimented with cljs on nashorn yet?

16:17 dnolen: brainproxy: have not

16:17 brainproxy: but Bodil did

16:17 brainproxy: yeah, saw her repl port thing

16:18 Bodil: WHAT DID I DO?!

16:18 brainproxy: but hadn't taken time to get setup to experiment with it myself

16:18 Bodil: Oh. Yes I did. :)

16:18 dnolen: brainproxy: you're Michael Bradley right?

16:18 brainproxy: dnolen: yes

16:19 dnolen: brainproxy: thanks for the Mori push

16:19 brainproxy: I was kind of shocked to see how much faster Mori is now

16:19 brainproxy: dnolen: you're welcome; I'm excited to have a good use for it :)

16:19 dnolen: couple of quick things; I can open issues if you like

16:20 dnolen: brainproxy: please do, it might be nice to get another release out after a few more changes.

16:20 brainproxy: dnolen: if you point Travis at your github account and mori, the travis badge at the top of the readme will work

16:20 dnolen: brainproxy: do I need to setup an account?

16:20 brainproxy: no, it uses passthrough to github

16:21 oauth i guess

16:23 dnolen: cool; next time you push to master, it should trigger a build/test

16:23 dnolen: brainproxy: cool thanks

16:23 brainproxy: I'll open issues for the other things

16:24 beffbernard: Does anybody know if you can generate primitive type instance variables with deftype? I AOT'ed a deftype that was type hinted and it was an Object instead of the type I wanted

16:25 dnolen: beffbernard: it should work

16:32 beffbernard: dnolen: it works for primitive types but not primitive arrays

16:32 dnolen: which is unfortunate what I need

16:32 :(

16:32 dnolen: beffbernard: yeah that doesn't work

16:33 beffbernard: local type hints work though if you're trying to avoid reflection.

16:33 beffbernard: dnolen: I'm trying to avoid boxing

16:34 dnolen: beffbernard: local type hints for the array not the things in it

16:34 beffbernard: dnolen: I have some performance sensitive code in a hot loop

16:35 dnolen: beffbernard: hint the array outside the loop

16:35 (let [^doubles xs xs] (loop ...))

16:39 svedubois: In CLJS is it possible to load external libraries with any command?

16:40 beffbernard: dolen: I can't really do that. I'm using the disruptor pattern and I have to get the primitive array every time.

16:42 seangrove: svedubois: What do you mean?

16:43 dnolen: beffbernard: you should take a look at gvec.clj

16:44 beffbernard: http://github.com/clojure/clojure/blob/master/src/clj/clojure/gvec.clj

16:45 svedubois: seangrove: For example if raphael.js is inside the folder /resources/public/js, How I call it?

16:46 I suppose js/Raphael

16:46 dnolen: beffbernard: rhickey works around this issue with an ArrayManager I think?

16:46 beffbernard: dnolen: reading...

16:47 dnolen: beffbernard: I believe the issue is primitive array type hints are an open set, so he creates a wrapper that implements an interface and I think this stuff inlines well

16:47 seangrove: svedubois: https://www.refheap.com/paste/e536371dfc6dd339b532f962e is an example of how I wrap the Firebase api

16:47 n_b: Am I correct in the understanding that Clojure-CLR isn't missing anything major that Clojure-JVM has?

16:47 seangrove: It's not perfect, and you may need to use externs instead of this, but it's certainly possible

16:48 The loading-handle is there because firebase is loaded async, and may not be present to get a ref when we first load up

16:49 tomoj: bbloom: dnolen: bound-fn! this test passes https://www.refheap.com/paste/da7a5901836377211615ed5c2

16:50 bbloom: tomoj: link to impl?

16:52 tomoj: https://www.refheap.com/paste/f906600e0042363bbfa767310

16:53 WIP..

16:54 bbloom: heh, ok, interesting approach :-P

16:54 tomoj: indeed :(

16:54 I can't figure out any way to touch binding that won't get shot down for making existing uses much slower

16:55 so here you get the slow stuff only when you actually use with-bindings*

16:56 there's a get-thread-bindings macro commented out there that was the beginning of my previous attempt, using the analyzer to find all dynamic vars, but that didn't seem likely to work out because you'd have to go recompile everything every time you define a new dynamic var

16:56 bbloom: yeah, i was just looking at that

16:57 personally, i think it's totally OK to reify Var objects for the :dynamic case

16:57 but that also has impact on the repl

16:57 b/c dynamic vars need to be automatically deref-ed

16:58 tomoj: so maybe we just need to convince the benevolent dictator that there's actually a use case for that dynamic-only reification?

16:59 much rather have a solution something like that if we can get it in, obviously :(

16:59 bbloom: well so i had a fork that used bound-fn and a bunch of dynamic var stuff….. and it was extremely useful for me while i was exploring

16:59 tomoj: yeah I remember, but last status I remember is that the use case is not appreciated

17:00 and/or the performance issues are too serious even for dynamic-only reification?

17:00 bbloom: yeah, well what happened was i got to a point where i only needed bound-fn in one very specific, very important place

17:00 and it turned out that i could do static analysis there w/o any problem

17:00 tomoj: my sights are on core-async which requires just get-thread-bindings and with-bindings

17:00 bbloom: so i refactored my code & replaced that with a macro generated call to bindings w/ some values pulled out of a map

17:01 yeah, those are basically what i need, but instead i had get-desired-thread-bindings and with-bindings-where-keys-are-known-statically-and-here-are-the-desired-bindings

17:01 & that turned out to be good enough

17:01 lazybot: java.lang.RuntimeException: Unable to resolve symbol: that in this context

17:01 tomoj: heh

17:01 bbloom: but i would have never arrived there without my fork to explore with

17:03 so if you reify only dynamic vars, the biggest issue is what happens when you redefine a var from dynamic -> static or static -> dynamic

17:03 b/c you need to rewrite call sites to have the .deref indirection or not

17:03 that's the tricky bit w/ that approach

17:05 tomoj: anyway, cool stuff.

17:06 tomoj: that does seem.. tricky

17:06 bbloom: tomoj: if you're going to continue to explore the approach here, you may want to combine getters & pushers into a single deftype

17:09 tomoj: with mutable fields pointing to maps?

17:10 I went with just atoms and maps for now because thinking about trying to make it fast left me wondering what to do about the symbol keys

17:12 avishai: suppose i have some blocking operation, say ring's run-jetty

17:12 and i want to do something after jetty started

17:12 do i need to use and agent?

17:13 in general, how do i wait for other thread? java's thread.join? latch?

17:13 tomoj: hmm, I think due to the trickiness in the reification approach, the accesses will still have to be like they are now, right? so a var access would always emit what it does now, just the binding-related functions would use the Vars?

17:13 n_b: should just be able to do (future (do (run-jetty) (your-thing))

17:13 tcrayford: you can use :join? false for that in ring

17:13 ring-jetty even

17:13 avishai: nice

17:13 arrdem: is there an idiomatic way to reduce with several pieces of state, or is the solution to reduce using a destructure and a return sequence?

17:13 tcrayford: that'll stop the current thread joining the jetty thread, but now you need a way to make sure the program doesn't exit immediately ;)

17:13 avishai: but the real question for me is how to wait later on

17:13 tomoj: sort of hybrid but far less ugly than my hybrid

17:13 tcrayford: a future is good for that

17:14 avishai: how do i wait for it?

17:14 hiredman: @(promise) is a very simply way to block the current thread

17:14 avishai: deref?

17:14 tcrayford: yeah, deref

17:14 n_b: A future will block on deref until it's fulfilled

17:14 avishai: and how do i handle exit signals? say ctrl c

17:14 tcrayford: try and catch like java, iirc

17:15 avishai: try and catch on what? do all threads get the exception?

17:15 tcrayford: no

17:15 I'm wrong

17:15 :)

17:15 google can answer that

17:15 gfredericks: does slamhound output require entries in a random order?

17:15 avishai: it's a jvm question, not clojure?

17:16 tcrayford: avishai: yep. Clojure doesn't do anything specific there to my knowledge

17:16 technomancy: gfredericks: should be alphabetical order?

17:16 gfredericks: technomancy: also it splits up [foo :as :refer] into [foo :as] [foo :refer]

17:17 technomancy: gfredericks: =(

17:17 wait

17:17 avishai: oddly enough ctrl+c does stop my programs

17:17 * gfredericks waits

17:17 technomancy: oh, I see what you mean

17:17 avishai: so something does handle it

17:17 i'll google and get back

17:17 technomancy: gfredericks: yeah, that's kind of weird

17:17 gfredericks: phew

17:17 technomancy: would be great if you could fix it

17:17 gfredericks: what? your full time job isn't fixing slamhound??

17:17 lazybot: gfredericks: Uh, no. Why would you even ask?

17:19 tomoj: arrdem: you got it

17:19 gfredericks: if for some reason I had a big company with lots of money I would hire A) somebody with the title "double-clicker" and B) technomancy to work full-time on slamhound

17:19 tomoj: I'd like to see another option

17:19 gfredericks: maybe A) and B) could be the same thing

17:19 arrdem: lol

17:19 tomoj: figured as much

17:20 hiredman: except technomancy hates mice

17:20 tcrayford: gfredericks: I thought you ran groupon?

17:20 NeedMoreDesu: I wish to generate keyboard sequences when some keys are down. Those thinks are usually done in autohotkey or autoit, but my ahk script is just too big to understand. I found java.awt.Robot class, so I can press needed keys. How can I listen to keypresses?

17:20 gfredericks: hiredman: oh man what a choice to present him with: you can work full-time on slamhound, but you can't use a keyboard

17:21 tcrayford: on screen keyboard only

17:21 no voice input either


17:21 tomoj: arrdem: are they independent?

17:21 gfredericks: tcrayford: a double-clicking based on-screen keyboard

17:21 tomoj: I mean are you basically trying to do two reduces in parallel, or do the states affect eachother?

17:21 technomancy: computer mice give actual rodents a bad name

17:21 gfredericks: tcrayford: the idea that I run groupon is a grave exageration

17:22 technomancy: I had a pair of fancy rats a while ago that were very agreeable

17:22 gfredericks: technomancy: how were they as I/O devices?

17:22 tcrayford: I: food O: poop

17:22 arrdem: gfredericks: they work out OK if you don't mind that they nip back when you click

17:22 technomancy: I: also the sofa

17:23 gfredericks: subset of food?

17:30 avishai: ah

17:30 java SignalHandler

17:30 works like charm

17:30 used reify for the first time too! yippi!

17:31 i have to say, clojure make jvm fun for me!

17:32 gfredericks: (inc clojure)

17:32 lazybot: ⇒ 12

17:32 hiredman: ~clojure

17:32 clojurebot: clojure is like life: you make trade-offs

17:33 gfredericks: ~clojure

17:33 clojurebot: clojure is not scheme

17:33 gfredericks: ~scheme

17:33 clojurebot: scheme is Scheme is like a ball of snow. You can add any amount of snow to it and it still looks like snow. Moreover, snow is cleaner than mud.

17:33 hiredman: clojurebot: that is not the universally positive message I am looking for

17:33 clojurebot: Roger.

17:33 hiredman: clojurebot: idiot

17:33 clojurebot: Excuse me?

17:33 gfredericks: ~idiot

17:33 clojurebot: Gabh mo leithscéal?

17:33 hiredman: ~clojure

17:33 clojurebot: clojure is the best

17:34 nightfly__: ~common-lisp

17:34 clojurebot: Pardon?

17:34 nightfly__: ~common lisp

17:34 clojurebot: common lisp is howl's moving castle

17:34 seancorfield: a great movie!

18:15 tacoman: I've got a library I'm trying to use that only exists on GitHub, no Clojars push or anything. I tried making a checkout dependency locally, but it just gives me a "could not find artifact oin Clojars" error

18:16 justin_smith: tacoman: did you try running lein install in the project's directory?

18:16 hiredman: ~checkout

18:16 clojurebot: Leiningen's "checkout dependencies" feature (see the README) allows you to override a declared dependency with a local copy symlinked inside the ./checkouts dir.

18:16 __zero: hello, I'm a little lost regarding the use of external jars and clojure. I already set up leiningen to include it in my classpath but from the repl I cannot seem to import it. Keep getting a FileNotFoundException. Any clues?

18:17 tacoman: justin_smith: my directory, or the other lib?

18:17 justin_smith: the other lib - lein install in the repo is an alternative to checkout, and I prefer it (as long as it is a lein project so installable)

18:18 tacoman: justin_smith: got it. yeah, that makes it work. thanks!

18:19 __zero: btw, I have used a local maven repo to set it up

18:19 justin_smith: just remember that in order to run your app on another machine, you will need to lein install the same lib there

18:19 which is why clojars is preferable

18:19 tacoman: right. I'm not the lib author, though. is it considered rude to push a snapshot on someone else's behalf?

18:20 justin_smith: you would basically fork it but not modify

18:20 then it would show up under your project umbrella

18:20 it would be polite probably to ask them to consider hosting on clojars first

18:20 tacoman: I did that a week or two ago, actually. No reply yet

18:21 so do you mean GitHub fork and then push to Clojars? the lib might be abandoned anyway, so I might have to pick up maintenance if my own work gets anywhere

18:21 justin_smith: so you could just make your own clojar of it, then other people are spared the hassle

18:22 nothing stops you from saying "I am not maintaining this code, I only forked it in order to put it on clojars" correct?

18:23 technomancy: justin_smith: yeah, putting that in :description of project.clj is not a bad idea

18:23 though putting it under an org.clojars.$USERNAME group-id kind of implies that too

18:23 tacoman: True. Just trying to make sure I understand community etiquette; I've never actually participated in the open source community in any capacity before

18:24 technomancy: what's the lib?

18:24 tacoman: clj-libtcod. I used libtcod for my senior project, and am looking into doing a rewrite in Clojure

18:25 clj-libtcod is really just a set of bindings with the lib packaged alongside it, I think

18:25 technomancy: only one commit =(

18:25 tacoman: yeah. well, it's autogenerated I think

18:26 there's a clj-native library which apparently automatically goes through some JNA stuff for you

18:26 it has been used a bit in one of his other projects, although I don't know how stress-tested it is

18:40 shoot. looks like the library itself no longer supports OS X these days. :\

18:48 Glenjamin: is there a way to specify that one defmethod of a multimethod should match more than one dispatch value?

18:51 aha, i can use parent

18:52 derive, even - is it totally horrible to do this on a non-namespaced keyword?

18:52 SegFaultAX: Glenjamin: I think they must be namespaced, yea?

18:53 Glenjamin: ah, i think i can do (derive :checkbox ::checkable) (derive :radio ::checkable) and get what i'm after

18:53 SegFaultAX: Hmm, I thought both the parent and child had to be namespaced.

18:53 Glenjamin: oh, you're write

18:54 right even

18:54 i get cryptic assertions failures otherwise

18:54 how do i turn a normal keyword into a namespaced one?

18:54 SegFaultAX: Glenjamin: In any case, you're on the right track I think. You should probably resolve this at the dispatch fn.

18:55 Glenjamin: the dispatch function just returns the <input>'s type

18:55 SegFaultAX: Glenjamin: ::foo is just shorthand for :user/foo

18:55 Glenjamin: Keywords follow the same namespacing convention as symbols (since they use symbols under the hood)

18:55 Glenjamin: but given :foo at runtime, via (-> elem :attrs :type), how do i translate to :user/foo ?

18:56 there has to be something better than (keyword (str *ns* "/" (name k)))

18:57 SegFaultAX: Shouldn't the dispatch fn coalesce the input types?

18:58 Glenjamin: hrm, maybe

18:58 i've been trying to keep it generic so it's extensible - but perhaps that's a poor goal

18:59 SegFaultAX: Glenjamin: I mean if you have types foo bar baz but you want bar and baz to result in the same invocation, have the dispatcher yield barbaz or something. Ultimately the function can still inspect the proper type.

19:00 Glenjamin: Or just factor out the shared code and have both multimethods call it.

19:01 Glenjamin: mm, i've just got it working with (derive ::checkbox ::box) and (derive ::radio ::box)

19:01 but both those approaches would work too

19:01 oh, keyword takes two arguments

19:01 ,(keyword :user :a)

19:01 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String>

19:01 Glenjamin: ,(keyword "user" :a)

19:01 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String>

19:02 Glenjamin: ,(keyword "user" "a")

19:02 clojurebot: :user/a

19:31 devn: Raynes: Dude, I just took down 4clojure. We're having a meetup here. /cc amalloy

19:31 Showing the list of all users *kaboom*

19:31 amalloy: yeah, that's a feature we really should disable since we can't cope with it

19:32 it'll be back in a minute

19:32 devn: amalloy: ill make sure no one hits that page again.

19:32 thanks amalloy!

19:32 jsmonkey: Hi, I am thinking about learning clojure. I am lookg for a good book. I saw there is a joy of clojure 2ed coming out in aug but I can't wait that long. the first edition covers 1.2 I think and the stable version is 1.5 now. Are the difference that big, should I go with the first edition or any other recommendations? I rather read a book then documentation since I am not that experiencd in functional programming so I w

19:33 Glenjamin: jsmonkey: i think you can still get the MEAP edition of the second edition

19:33 you get the first edition, and chapters of the 2nd as they are written

19:34 jsmonkey: Glenjamin: there was only like 2 avaible chapters for the 2ed edition. but I will of course read the 2ed if I like the first one.

19:34 but what I meant is. have the languge changed much since 1.2?

19:34 Glenjamin: or do you recommend another book or learning resource?

19:34 Glenjamin: i think the core language hasn't changed, but the module layout has - i'm not certain, I only learnt recently

19:35 I just read a few syntax tutorials and got stuck in, but I've done a fair bit of FP before

19:35 i suspect joy of clojure will still be useful if you're new to FP - but you might have read up on the docs afterwards to catch up with new language features

19:36 jsmonkey: Glenjamin: ok cool I think I will go with it. I have done some haskell and my main language is js where I try to do as much FP as possible.

19:37 Glenjamin: ah, then you might be ok with just reading up on the syntax and trying to build something

19:37 that's pretty much where I started from

19:37 jsmonkey: Glenjamin: lets hope that is the case.

19:37 do you like it so far? how long have you been hacking clojure?

19:57 muhoo: anyone using migratus?

19:58 i'm curious how it "knows" whether a migration has been run or not

19:59 SegFaultAX: I've never looked at it, but most migration systems use a migration table.

20:01 muhoo: a table in the database? makes sense.

20:01 trinary: that's how rails migrations work, and I'd expect that it's a common way to implement them.

20:01 SegFaultAX: muhoo: Yea, if you look at the database.clj you can see the top few functions are for querying to see if a migration record exists.

20:02 muhoo: ah, i wasn't clear on what that was. table-name is kind of unspecific

20:02 yep, thanks. (log/info "creating migration table" (str "'" table-name "'"))

20:06 jjttjj: OI want to just catch all exceptions and log them somewhere

20:07 wrapping the -main function in a try-catch to catch all exceptions doesn't seem to be working

20:08 It's a GUI app that uses swing and does most the work in a future. Am I missing something obvious or is this not enough info

20:08 axle_512: jjttjj: are you catching the exceptions somewhere so that they aren't thrown all the way to main?

20:09 jjttjj: I'm not explicitly, is this something other libraries might do?

20:09 hiredman: guis in java are multithreaded

20:10 in the sense that the gui toolkit almost always has a special thread different from the main thread that it uses

20:10 axle_512: jjttjj: if you are doing all the work in a future, then the exceptions will be propogated up to the run method of that thread. (Not you rmain thread).

20:10 SegFaultAX: hiredman: Um, what?

20:11 axle_512: jjttjj: and what hiredman said. Swing GUIs will involve the swing event dispatch thread

20:11 SegFaultAX: hiredman: Swing is not threadsafe.

20:11 Like, at all.

20:11 And most GUI toolkits are not.

20:11 hiredman: SegFaultAX: yes, but by using swing you now have at least 2 threads

20:11 axle_512: jjttjj: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html

20:11 hiredman: SegFaultAX: I am well aware of swings threading model

20:11 jjttjj: axle_512: cool thanks!

20:12 SegFaultAX: hiredman: It's probably more correct to say that swing /event handling/ runs separately.

20:12 hiredman: if you use swing you have at least the main thread and swing's thread (and the finalizer thread and the gc thread)

20:12 SegFaultAX: the swing thread is a real thread and the novice can unknowingly run real work on it

20:13 axle_512: jjttjj: working with the event dispatching thread takes some practice

20:13 SegFaultAX: hiredman: Yes, and?

20:13 axle_512: jjttjj: that 2nd to last paragraph that starts with "It's useful…"

20:14 hiredman: SegFaultAX: so if you use swing your program is multithreaded

20:14 SegFaultAX: Saying "guis in java are multithreaded" is, in my humble opinion, misleading at a minimum. Swing may manage internally multiple threads but swing itself is not thread safe.

20:14 axle_512: jjttjj: any event that is called from Swing is running on the event dispatching thread.

20:14 hiredman: SegFaultAX: I said nothing about safety

20:14 SegFaultAX: hiredman: Ok, if you use java your program is multithreaded. That's a really misleading argument.

20:14 axle_512: jjttjj: If that event triggers some long-running task, you want to move that work to another thread.

20:14 hiredman: multithreaded = more than one thread

20:15 axle_512: jjttjj: when your long-running task is finished, don't update the UI from that thread. Instead, make the event dispatch thread do it by using invokeLater() or invokeAndWait().

20:15 SegFaultAX: Oh, pendantic arguments. Nevermind, I withdraw.

20:15 hiredman: SegFaultAX: which means for example, if you put a try/catch around your main code and their are exceptions in the event loop, you won't catch them

20:15 SegFaultAX: hiredman: Okay.

20:16 jjttjj: yeah that's what was throwing me off :)

20:17 axle_512: jjttjj: also, take a look at this: http://stackoverflow.com/questions/4448523/how-can-i-catch-event-dispatch-thread-edt-exceptions

20:17 hiredman: "Even though the GUI frameworks themselves are singlethreaded subsystems, your application may not be, and you still need to consider threading issues carefully when writing GUI code." to quote jcip

20:17 axle_512: jjttjj: It looks like you can register a callback for any exceptions that are thrown in the event-dispatch-thread

20:17 jjttjj: Never tried it though :-)

20:18 jjttjj: axle_512: cool, I think I was basically doing most of that stuff by default due to seesaw nudging me in that direction

20:18 axle_512: awesine yeah I just found that 2 minutes ago

20:18 SegFaultAX: hiredman: Yes of course you need to consider threading issues. Because you're probably using threads to do a lot of heavy lifting away from the main thread, but that work still needs to be updated on the main thread.

20:29 alexyk: is there a separate pedestal channel or is it all in here for now?

20:30 tomoj: alexyk: /msg alis list *pedestal*

20:30 or, hell, /join #pedestal ...

20:31 alexyk: tomoj: thx!

21:03 mmitchell: technomancy: hey, i'd like to hook into a lein task (lein midje), specific for a project. What's the recommended approach for this?

21:54 uvtc: In the cheatsheet, http://clojure.org/cheatsheet , under the "Strings" section, what does "See also IO/to string" refer to?

21:55 amalloy: uvtc: probably something really really old

21:56 uvtc: amalloy: thanks. Also, thanks for the help a few days ago (after I'd gone offline) re. .indexOf, removing an item from a sequential coll, and using recursion.

21:56 amalloy: oh good, i'm glad you got that after all

21:56 uvtc: I used it to update my notes at http://www.unexpected-vortices.com/misc-notes/clojure/examples/data-structures.html .

21:57 amalloy: i still think it's a lot better if it takes a pred rather than a specific entire item

21:57 uvtc: Right. To make it more generic.

21:57 amalloy: eg, (remove-once even? coll). and the args should definitely be x coll (or pred coll), not coll x

21:58 * uvtc not sure what you mean ... looking for that gist you wrote ...

21:59 amalloy: the args are in the wrong order. it should take coll last, not first

22:00 uvtc: found it: https://gist.github.com/amalloy/5500495

22:01 Hm... I'm suppose I'm not experienced enough with Clojure yet to see why the coll should come last...

22:01 amalloy: functions which operate primarily on sequences should take them last, just like map, filter, remove, reduce...

22:02 gfredericks: works great with ->>

22:02 uvtc: amalloy: thanks. Now I want to make a table to see just which functions take coll first and which take it last.

22:03 jxx: everything works great with as->

22:03 gfredericks: conj takes a coll first

22:03 amalloy: well, it takes a *coll*, not a *sequence*. i was careful to say sequence

22:04 gfredericks: drat! fooled by care again!

22:09 uvtc: amalloy: do you specifically mean "sequences", or "sequential collections"?

22:10 amalloy: things which you will treat only as sequences

22:11 uvtc: Thanks. Updated my notes.

22:13 brehaut: yup

22:13 whoops

22:24 uvtc: Seems like `(keep some-fn some-coll)` should be the same thing as `(filter (complement nil?) (map some-fn some-coll))`, and it seems to act that way. But looking at the source, `keep` does not appear to be implemented using `map` in that way.

22:25 Is it maybe for performance that `keep` isn't implemented that way? Or am I misunderstanding `keep`?

22:25 `keep` save typing in some circumstances, anyway.

22:26 saves*

23:17 mmitchell: OK, I'm having trouble creating a leiningen plugin hook. I'd like to hook into a task, copy a file on the resource/class-path and call the original task. The problem is that the classpath is not available to my hook. Any ideas on how to fix this?

Logging service provided by n01se.net