#clojure log - Apr 05 2012

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

0:01 dnolen: jonasen: I'm not sure if there's a good general solution for that, definitely one to ask around about.

0:04 jonasen: perhaps one way is to just handle all cases of ground not ground - https://gist.github.com/2307725

0:07 unlink: eggsby: ah. yeah, I've never had much luck with OpenJDK myself.

0:08 treehug: unlink: our prod systems are openjdk-6. no problems encountered except in an old version of c3p0 that assumed the java.version property would not have "iced tea" in it

0:18 rlb: What's currently the best way to launch and communicate with a (long-running) subprocess? i.e. I'd like to just end up with a writer I can print to when necessary.

0:20 Raynes: rlb: https://github.com/Raynes/conch

0:20 toot toot

0:21 rlb: Raynes: thx

0:29 wei_: I'm trying to write a leaky-filter function- filter unless 3 items don't match the filter, in which case return the next thing. e.g.: (leaky-filter nil? [nil 1 2 nil] ) -> [1 2] but (leaky-filter nil? [nil nil nil nil 1 2 3]) -> [nil 1 2 3]

0:30 I'm using it for a series of http calls. regular "fliter" will just hang if the server happens to be down

0:40 johnkpaul-afk: does anyone have any experience extending leinigen? I am trying to get something to run after a particular task

0:41 johnkpaul: after repl-listen, I want to preload some code into the repl

0:41 so it changes the namespace beforehand

0:41 eggsby: hmm, does lein have event hooks? that'd be a nice feature

0:42 dnolen: johnkpaul: you might want to take a look at how ClojureScript One does this

0:42 johnkpaul: oh, dnolen, I didn't think that clojurescript one did do that, but I'll look into it now

0:43 dnolen: johnkpaul: they don't use cljsbuild, but it might give you some ideas

0:46 johnkpaul: ok, thanks

0:46 eggsby: it does have event hooks, but seemingly only for a specific set of tasks

1:04 xeqi: johnkpaul: lein uses robert.hooke for extending in that way

1:05 johnkpaul: robert.hooke? that's a namespece in leinigen?

1:05 xeqi: its a library

1:05 https://github.com/clojurebook/ClojureProgramming/blob/master/ch08-lein-mixed-source/project.clj

1:06 thats an example where they want to compile java after clojure

1:06 you might be able to do something similiar, where you hook cljs.repl/repl

1:06 and call cljs.repl/add-namespace first

1:06 * cljs.repl/load-namespace

1:09 johnkpaul: oh I see

1:10 so I have to figure out how to hook this into lein-cljsbuild

1:10 in order to run this code after that task

1:10 or actually, that's just a quoted list, maybe it's really straightforward

1:13 xeqi: its a generic mechanism, but requires konwing where to hook at

1:15 johnkpaul: so that would need to go inside my project.clj file, right?

1:21 xeqi: it can, you can also add :hooks [namespace] to your project map to load it from there

1:23 or stick it in a plugin

1:24 johnkpaul: at the moment, I'm going to stick it in the plugin

1:25 what's the difference between defn and defn-?

1:27 xeqi: defn- adds private metadata

1:29 johnkpaul: oh ok

1:29 and the backtick?

1:29 I can look that up

1:30 oh, it's a quote

1:30 in the current naespace

1:32 muhoo: i'm having log4j tsuris

1:32 i'm using a java library that requires log4j. but i'm also using noir, which uses netty, which has its own log4j

1:32 so there are competing log4js

1:32 wei_: anyone know why I can't call this function? the correct arity is 2:

1:33 https://gist.github.com/2308223

1:34 muhoo: wei_: where's the source to run-threads?

1:34 xeqi: wei_: the first line calls the function, but errors on miss-calling an anonymous function inside

1:34 wei_: oh, i see

1:35 i think that's enough to debug the problem. just needed some insight on interpreting the output

1:35 thanks!

1:52 rlb: Raynes: clj-time has worked well, but how do I format the time *in* a particular timezone?

1:52 i.e. (to-time-zone (now) (default-time-zone)) always formats as UTC, but

1:52 (from-time-zone (now) (default-time-zone)) shifts

1:52 I must be overlooking something obvious -- might be time to call it a night...

3:20 wei_: in case anyone was curious about my previous question about leaky-filter: https://gist.github.com/2308710

3:23 andyfingerhut: I am missing something very basic when it comes to Leiningen and profiles. I've just downloaded and installed version 1.7.1, and have a line ":profiles {:dev {:dependencies [[org.thnetos/cd-client "0.3.4"]]}}" in my project.clj. Should I need to use "with-profiles dev" on the lein command line to activate the dev profile?

3:26 And of course I find the web page I've been needing for the past 15 minutes, but only 1 minute after asking my question to the world :)

3:26 https://github.com/technomancy/lein-profiles

3:26 Raynes: andyfingerhut: Use the 'user' profile.

3:27 andyfingerhut: Also, technomancy is saying to beware of that project. It is apparently outdated. I'd encourage you to try out lein 2 preview. It's stable enough for real projects.

3:27 andyfingerhut: Raynes: Are you recommending that so that I can avoid making the change to each project's project.clj file separately?

3:29 Raynes: andyfingerhut: Mostly because there are probably bugs in lein-profiles or outofdateness that I don't know about.

3:29 Oh, you're asking about the 'user' profile recommendation.

3:29 Yeah, I thought you said your ~/.lein/profiles.clj.

3:29 andyfingerhut: So if I were to go in front of a group of Clojure users of varying experience levels tomorrow night and recommend how they should set this up, what would you recommend? I'm thinking perhaps it might be simpler to say "If you aren't using Leiningen 2 yet, add :dev-dependencies [[org.thnetos/cd-client "0.3.4"]] to your project.clj". Would that be reasonable?

3:30 Raynes: I think that would be reasonable.

3:30 andyfingerhut: And perhaps mention on the side that :dev-dependencies is deprecated in Leiningen 2, but save that issue for later when they upgrade?

3:31 Raynes: andyfingerhut: Just tell them that when they upgrade, be sure to read the upgrading guide. It clearly explains all of that.

3:33 andyfingerhut: Raynes: Thanks. I think giving the Leiningen 1.x short answer is a good idea, with a side comment that Leiningen 2 early adopters probably have already learned they need to do it a bit differently.

3:42 franks42: You, sir, have motivated me to stay up an extra hour getting ready for a Clojure documentation presentation to a San Francisco user group that will be held Thurs evening. I'm just about to play with clj-ns-browser in hopes I can demo it and other things there.

3:47 kral: hi pals

5:04 wei_: ^ so, I just uploaded to clojars a java project built with maven. but it has other dependencies that aren't included in the jar (e.g. org.json.JSONObject). how do I specify those dependencies?

5:05 clgv: wei_: you can check whether the dependencies are already specified in the pom.xml

5:08 wei_: ok, if it is org.clojars.yayitswei/java-channels-api then there is no dependency listed

5:09 wei_: clojure dep would look like that in the pom.xml: <dependency><groupId>org.clojure</groupId><artifactId>clojure</artifactId><version>1.3.0</version></dependency>

5:09 wei_: I created that pom manually-- just added the dependencies from the original project and re-uploaded to clojars

5:12 hmm, it didn't seem to overwrite the old pom

5:16 clgv: wei_: it did. it added "-1" and "-2" postfixes. maybe you can increase the version to make sure it works

5:17 wei_: what does that mean, -1 and -2 postfixes?

5:17 clgv: wei_: have a look here http://clojars.org/repo/org/clojars/yayitswei/java-channels-api/0.1-SNAPSHOT/

5:19 wei_: I don't see any dependencies though? I added this: https://gist.github.com/2309408

5:25 oh nevermind, I see it

5:26 jpop: hello. I seem to be missing how doto works. I expected (doto 1 (+ 2) (+ 3)) to return 6. why does it return 1?

5:27 wei_: I think you're looking for ->. (-> 1 (+ 2) (+ 3))

5:29 jpop: thanks, I think I got the difference

5:29 macroexpanding helped

5:31 wei_: clgv: is it correct to increase the version number for clojars if the java project hasn't actually changed version? thanks for all the help by the way.

6:16 jpop: so the only thing doto does is it inserts the object in all the forms, and then returns that same object?

6:19 clgv: wei_: it's under your groupid. you can as well add a fourth digit for your integration changes

6:19 babilen: jpop: Sounds about right. Did you expect more?

6:20 clgv: jpop: 'doto is intended for java interop with mutable objects.

6:20 wei_: I believe it's for side effects

6:21 babilen: It is

6:21 clgv: jpop: it is very hand with swing gui.

6:21 jpop: yeah I agree it's handy

6:21 babilen: (Or with any other Java Object that you have to deal with)

6:22 stevenfx: /quit

6:22 sorry

6:28 wei_: clgv: thanks for the clojars help; that worked well

6:28 clgv: :)

6:28 wei_: goodnight everyone!

6:41 progo: good day

6:45 cemerick: *crazy* OT, but hopefully there's a CSS master in the channel. How can I make the image portholes on the left look decent in webkit browsers (they look great in Firefox): http://www.clojurebook.com/

6:48 Raynes: cemerick: Remove the padding.

6:50 cemerick: That looks like the simplest solution. You lose the pretty border around the images, but they look really good to me without it.

6:50 That's about as far as my CSS skills will take you.

6:51 cemerick: Raynes: Further than I got. Never thought the padding would impact the geometry of the images.

6:51 Thanks :-)

6:51 And whoa, Raynes giving CSS advice? :-O

6:51 Raynes: cemerick: FYI, figuring this out involved me removing styles until something nice happened.

6:51 Nothing clever.

6:51 cemerick: CSS is real science, huh?

6:51 Raynes: Indeed.

6:54 cemerick: actually, leaving the padding and dropping the border radius is great. Should have thought of that before.

6:56 Raynes: cemerick: Yeah, my other option was to say "Why are you being daft and using a border radius? Are you looking out of a boat or something? Srsly."

6:56 cemerick: hah

6:56 it was my poor attempt at aping the OS X Lion login screen

6:56 My general design strategy is: find something pretty, copy it.

6:57 Raynes: Haha, likewise.

6:59 bradwright: cemerick: I'm good with CSS, what exactly are you trying to achieve?

7:00 cemerick: bradwright: Nothing anymore, but thanks. :-) I've already pushed a tweak that "fixed" the problem.

7:00 bradwright: cool

7:00 Raynes: Fixed as in did it properly.

7:02 cemerick: There are CSS-only mocks of the Lion login screen, but I wasn't able to transplant them properly.

7:02 50+ properties, 3D stuff, etc.

7:03 Raynes: Frightening.

7:15 gregorius: just tepped over a nice tutorial: http://www.lisperati.com/clojure-spels/casting.html

7:15 Chiron: Hi all. how to use a clojure protocol from java?

7:18 clgv: Chiron: afaik you will have to AOT compile it and then you can just use the interface it generates

7:19 Chiron: (defprotocol ValueOriginBuilder (as-origin [any]))

7:19 defprotocol generates the ValueOriginBuilder interface, so I can implement that. But how to ask clojure for an implementation ?

7:20 clgv: Chiron: erm what? you want to define an implementation in clojure? or you want to use a java implementation of the protocol interface from clojure

7:21 Chiron: I want to have in Scala: val valueOrigin = ValueOriginBuilder.as_origin( something );

7:29 sattvik: Chiron: For that, you have to create an implementation using deftype.

7:29 Chiron: would you please explain more? thank you

7:30 clgv: Chiron: (deftype VOB ValueOriginaBuilder (as-origin [any] 42))

7:30 oops, should be (deftype VOB [] ValueOriginaBuilder (as-origin [any] 42))

7:31 Chiron: what is the value 42?

7:31 progo: the Answer, of course.

7:32 clgv: :D

7:32 Chiron: the return value of the method implementation

7:33 sattvik: Now, you have to be sure not to forget the 'this' argument in the protocol and the type.

7:34 clgv: sattvik: right

7:34 Chiron: deftype is new to me, I will check it

7:35 sattvik: And it won't create a static method. In Scala, you'd have to do something like val origin = new VOB().as_origin(something);

7:44 kahlin: hey, i'm looking for a usable logging framework... found clj-logging-config, has anyone used it?

7:47 zamaterian: kahlin, have you looked at clojure.tools.logging ?

7:50 kahlin: zamaterian: yes, a little bit. clj-logging-config seems nicer to configure which is the main reason I'm thinking of using it.

7:50 zamaterian: have you used clojure.tools.logging?

8:52 makkalot: hi, does someone have the slides and code of that talk : http://blip.tv/clojure/clojure-concurrency-819147 ?

9:09 jaley: so, it just dawned on us that we can write our mongodb queries in clojurescript... can't see anything on the google about someone doing this already. has anyone here tried it?

9:11 cemerick: jaley: And run them from the browser?

9:12 antares_: jaley: I have been experimenting with this for monger (https://github.com/michaelklishin/monger). Unfortunately, the CS compiler is still not very useful as a library. cemerick may be the only person who knows how to do it ;)

9:12 cemerick: oh, I see; so mongo allows you to write queries in javascript then?

9:12 jaley: cemerick: that's right, the second one :)

9:12 cemerick: ok, that's much more sensible then!

9:13 jaley: cemerick: so our plan is to use cljs.closure/build to get a javascript string

9:13 cemerick: There's a port of clutch to clojurescript around somewhere that allows you to connect to a couchdb instance from the browser. 'course, you need to ship your database credentials to your users, but… :-O

9:13 jaley: see https://github.com/clojure-clutch/clutch-clojurescript

9:13 antares_: ^^

9:15 jaley: cemerick: yikes! that's neat - we're nowhere near the browser though, we're just excited about writing queries in cljs instead of js. wondering if i've missed some obvious huge hurdle though

9:16 cemerick: jaley: Nope, the approach works well, at least for CouchDB. clutch-clojurescript actually has some number of users using it for real stuff, so…

9:16 jaley: cemerick: awesome

9:16 antares_: cemerick: yes, that's what I am talking about. clutch-clojurescript is the only real world example right now :(

9:16 cemerick: jaley: note the caveat in the README

9:17 antares_: and CLJS compiler has version numbers weirer than Hadoop :/

9:17 *more weird

9:17 cemerick: I suppose if the mongodb js engine is slow/persnickety/etc, it might have a rough time with ~40K of js per view. Hopefully they're using something sane.

9:18 antares_: There's cljsbuild. Same thing, I'm just gathering the code up and munging it in a couple specific ways to make it useful in couch.

9:21 jaley: cemerick, antares_ : thanks for tips guys. that's enough encouragement for us to persist with playing :)

9:21 cemerick: antares_: and yeah, the cljs versioning is something to…get used to, I guess. It's moving very quickly though; I need to get clutch-clojurescript on travis so as to keep an eye on the changes

9:22 antares_: speaking of, if travis could trigger builds when upstream maven dependencies are updated… ;-)

9:25 antares_: cemerick: they use spidermonkey with an option to build with V8

9:25 cemerick: libv8 and google closure compiler probably play well with each other ;)

9:26 cemerick: antares_: couch uses spidermonkey as well, so you should be good

9:27 antares_: cemerick: plus, you don't use JS for views with mongodb. Typically only map/reduce or arbitrary code execution.

9:27 cemerick: so code can be "installed" on app boot

9:29 cemerick: even better then w.r.t. code-loading/startup costs

9:53 oc: is there a good "rainbow"-style parenthesis completion for vim?

9:55 fdaoud: oc: yes, I use clojure.vim with g:clj_paren_rainbow

9:57 Wild_Cat: all of this reminds me I need to try out Counterclockwise.

9:58 babilen: oc: I recommend vimclojure -- https://bitbucket.org/kotarak/vimclojure best clojure integration IMHO. I do, however, prefer emacs + evil (http://emacswiki.org/emacs/Evil) for Clojure development

10:00 gfredericks: is continuing to use lein-cljsbuild after abandoning lein for maven non-trivial?

10:00 s/non-trivial/hard\/impossible

10:01 * gfredericks imagines trying `mvn lein cljsbuild`

10:02 jsabeaudry: I have a character device that behaves fine (blocking read) when I `cat` it, however if I pass the input stream to Jetty I get an "Illegal Seek" exception when the read should just block, is there a better way?

10:07 TimMc: jsabeaudry: What happens if you wrap it in a buffered stream?

10:08 fdaoud: gfredericks: why are you abandoning lein? (just curious.)

10:10 jsabeaudry: TimMc, isn't clojure.java.io/input-stream already a buffered stream?

10:10 TimMc: Integrating into an existing Maven project, perhaps?

10:10 jsabeaudry: Hum, maybe. Hey, is this that embedded device project?

10:11 jsabeaudry: TimMc, yes it is, you have good memory :)

10:12 TimMc, the fpga is working and I'm pretty much done writing the driver, time to stream that data :)

10:12 TimMc: Is there an equivalent sort of character device on a standard Linux that I could experiment with?

10:13 dgrnbrg: jsabeaudry: I notice that you're using an FPGA w/ clojure?

10:13 jsabeaudry: TimMc, /dev/random

10:14 dgrnbrg, Well let's say the two are part of the same project yes

10:14 gfredericks: fdaoud: wasn't my decision; team lead wants compatibility with other projects or something

10:14 dgrnbrg: jsabeaudry: I'm actually working on a system to program FPGAs in clojure

10:15 I have a working cycle simulator and type system that takes into account the bit-layout of structures

10:15 TimMc: jsabeaudry: The same thing happens with /dev/random in your program? Or is the data important?

10:15 fdaoud: gfredericks: ah ok.

10:15 dgrnbrg: and it supports tagged unions and structures, and clojure's destructuring syntax for synthesizable types

10:15 jsabeaudry: TimMc, Ah excellent idea, let me try that right away

10:19 TimMc: jsabeaudry: When I try to .skip on a FileInputStream on /dev/random, it skips 0 but does not throw.

10:22 I guess that one won't block readily, though...

10:22 jweiss: a co-worker wants to know why he should leave groovy for clojure. I pointed out macros, but I'm struggling to find him a concise example that will show why they're so great. I thought of with-open, anyone have a better example?

10:23 zamaterian: jweiss, look at clojure-clutch the with-db*, with-db and defdbop macroes

10:23 TimMc: jweiss: core.match is made of macros.

10:24 Wild_Cat: jweiss: logging. Macros make logging 10 times more awesome

10:24 llasram: jweiss: all of core.match maybe?

10:24 * jweiss takes a look at core.match

10:25 johnkpaul: How can I set a dependency for leinigen itself, when it is interpreting project.clj?

10:25 I am trying to require leinigen.cljsbuild inside project.clj, but it can't find it

10:27 TimMc: jsabeaudry: Playing with mkfifo now. Intriguingly, the FIS constructor blocks until someone writes to the fifo.

10:28 jsabeaudry: TimMc, /dev/random seems to block too

10:28 there must be something missing in my driver

10:28 TimMc: jsabeaudry: OK, got Illegal Seek on a fifo when I tried to skip.

10:29 mkfifo foo; echo "blah" >> foo

10:29 and then (.skip fis 5) fails

10:29 jsabeaudry: but (.read blocks?

10:30 bhalbert: gfredericks: i seem to recall that lein will emit a POM for you (as a starting point perhaps)

10:31 TimMc: jsabeaudry: Hmm, no -- EOF. (returns -1)

10:32 jsabeaudry: hmm, I'll try providing a non-default implementation of llseek see if I can get somewhere with that

10:34 groovemonkey: hi guys, newb here -- I'm getting an error when I try using java's getAbsolutePath with a string in Clojure. Anyone know what i'm doing wrong?

10:34 (.getAbsolutePath "/home/path/to/test")

10:34 IllegalArgumentException No matching field found: getAbsolutePath for class java.lang.String clojure.lang.Reflector.getInstanceField (Reflector.java:289)

10:35 gfredericks: bhalbert: I'm not sure how that helps with running lein-cljsbuild? unless lein-cljsbuild has a maven interface...

10:36 zamaterian: groovemonkey, (. getAbsolutePath (File. "/home/.."))

10:37 groovemonkey: thank you! trying it now...

10:37 zamaterian: groovemonkey, the java.lang.String has no getAbsolutePath method, If your in doubt which calls an object has use type (type "/home/..")

10:38 s/calls/methods

10:40 johnkpaul: is there a different irc channel for lein help?

10:40 groovemonkey: thank you. Sorry, i took that from an old clojure peepcode tutorial.

10:41 bhalbert: gfredericks: err, sorry. was skimming and just saw "abandoning lein for maven"

10:41 zamaterian: johnkpaul, the #leiningen channel

10:42 johnkpaul: :) thank you

10:42 yoklov: anybody know of a good complex number package for clojure?

10:43 jsabeaudry: TimMc, thanks for you help it is now streaming! let's see how fast it can go now :D

10:45 TimMc: jsabeaudry: What solved it?

10:47 jsabeaudry: TimMc, providing a non-default llseek implementation in the driver of which I share the code with you: "return 0;" ;)

10:51 TimMc: heh

11:05 yoklov: that actually might be my biggest annoyance with clojure, lack of complex number support

11:16 gfredericks: also where do I look for a maven replacement for lein-ring?

11:16 lynaghk: ibdknox: In Waltz is a state's `in` function supposed to run if you set to that state while you're already in it? I'm seeing that behavior, but intuitively it seems like it should only run when first entering that state.

11:19 franks42: andyfingerhut: sorry that I kept you from a warm bed - clojure tend to do that to you ;-) - hopefully that clj-ns-browser was worth it... too bad I cannot make it tonight to the SF-meetup - good luck with presentation (love your cheatsheet!)

11:19 cemerick: gfredericks: which part of lein-ring do you need?

11:19 part(s)

11:20 konr: Can you point out some cool things that you can do with IDEs other than Emacs to Clojure?

11:25 unlink: How do I get the request URI in a ring application without the leading context path?

11:26 weavejester: unlink: If you've compiled a war using lein-ring, a :path-info and :context key will be added to the request

11:26 unlink: akin to .getPathInfo()

11:27 cemerick: konr: what are you looking for in particular?

11:30 unlink: weavejester: ok. I'm using run-jetty in development. Is it possible to make those keys accessible then?

11:31 weavejester: unlink: In development, there is no need for a :path-info key. You could write a quick function like...

11:31 RickInGA: can anyone point me to an example of using radio buttons with noir/hiccup?

11:31 weavejester: unlink: (defn path-info [req] (or (:path-info req) (:uri req)))

11:31 konr: cemerick: nothing in particular, just brainstorming things to be considered to my IDE proposal for GSoC. People often mention Textmate's useful templating system, and I bet those big IDEs must have good debugging/profiling integration

11:32 weavejester: unlink: Also, Compojure handles :path-info/:uri automatically in routing.

11:32 unlink: weavejester: I could, but what I really mean is request.getPathInfo(). (I'm not using compojure.)

11:32 weavejester: unlink: And therefore Noir does too.

11:32 cemerick: konr: well, being able to set breakpoints without altering sources is handy.

11:32 weavejester: unlink: When using an adapter, the path-info is always equal to the uri

11:33 unlink: The path-info is really only relevant when deployed as a war, or using something like the Compojure context macro

11:34 unlink: weavejester: so then it would make sense to have a middleware at the site of run-jetty that assocs in :path-info based on :uri.

11:35 weavejester: unlink: It would be easier to create a path-info function, I think

11:35 gfredericks: cemerick: lein-ring I can probably emulate well enough; it's lein-cljsbuild that I'm particularly worried about

11:35 johnkpaul: how can I add a dependency for a leiningen hook?

11:36 weavejester: johnkpaul: Add it as a :plugin

11:37 johnkpaul: oh, that will run with the right things in the classpath?

11:37 let me try that

11:37 here's the file I'm using http://pastebin.com/fwunbczK

11:38 weavejester: johnkpaul: Why did you call your namespace "leiningen.hook"?

11:38 cemerick: gfredericks: well, `ring uberwar` is baked into maven's war packaging; `ring serve` is `mvn jetty:run` (assuming proper configuration of the maven-jetty-plugin

11:38 weavejester: johnkpaul: And what does it do? Which package is it from?

11:39 johnkpaul: no good reason, just trying to get that to work

11:39 I'm trying to hook into cljsbuild's repl-listen

11:39 cemerick: gfredericks: cljs support is, as you say, a whole 'nuther can of worms

11:39 johnkpaul: I mean, eventually, right now that hook just prints "hey, it hooks"

11:39 cemerick: gfredericks: maybe you can exec out to cljsbuild somehow? :-P

11:39 weavejester: johnkpaul: Which package is the hook coming from?

11:39 gfredericks: cemerick: I was thinking a lein plugin for maven would be cool :)

11:40 wait

11:40 I mean a maven plugin for lein

11:40 weavejester: johnkpaul: And what does your hook namespace look like?

11:40 johnkpaul: ./src/leiningen/hook.clj

11:40 gfredericks: you know: `mvn lein cljsbuild once`

11:40 johnkpaul: (ns leiningen.hook (:require [robert.hooke]))

11:41 weavejester: johnkpaul: If it's in your src, you'd need a :eval-in-leiningen true in your project map

11:41 cemerick: gfredericks: you might want to look at zi as a first step: https://github.com/pallet/zi

11:41 a zi:cljsbuild goal may not be too tough

11:41 johnkpaul: oh ok, maybe I'm going about this incorrectly

11:41 gfredericks: cemerick: I'll check that out, thanks

11:41 weavejester: johnkpaul: Take a look at the installation for my environ plugin: https://github.com/weavejester/environ/blob/master/README.md

11:41 johnkpaul: should I be doing that

11:41 oh ok, thanks

11:42 cemerick: plugging lein up into maven sounds…tricky ;-)

11:42 weavejester: johnkpaul: And at the corresponding hook: https://github.com/weavejester/environ/blob/master/environ.lein/src/environ/leiningen/hooks.clj

11:43 johnkpaul: Leiningen has effectively two separate environments; one for Leiningen itself, and one for your project. Hooks need to be evaluated in Leiningen, which means they need to be a dev-dependency, or (for Lein 1.7 and above) a plugin.

11:43 johnkpaul: ooh, I didn't realize that's how it works

11:44 so if I want to be hooking _another_ plugin, I need to be evaluated inside leningen

11:44 ok, so it seems that changing the word "hook" to "plugin" in my project.clj, got everything running with no errors

11:44 weavejester: johnkpaul: The :eval-in-leiningen effectively treats your src directory as like a plugin

11:44 unlink: weavejester: Why not assoc path-info and context-path in ring.util.servlet (rather than leiningen.ring.war)? They seem like application-level concerns to me.

11:45 weavejester: johnkpaul: You need two steps: include the dependency as a plugin, and then add the namespace as a hook.

11:45 unlink: Because adapters have no concept of path-info or context

11:46 hugod: gfredericks, cemerick: I started this a while back https://github.com/pallet/zi-cljs

11:46 weavejester: unlink: Ring is all about providing the minimal possible interface, and then building on that with middleware.

11:46 unlink: weavejester: Right, and I am fully behind that philosophy.

11:46 weavejester: But don't adapters give you real HttpServletRequests?

11:47 weavejester: unlink: No. You can't rely on adapters giving you HttpServletRequest access, because adapters might not be based on top of an existing Java servlet engine.

11:47 unlink: Ring uses Jetty as it's default adapter, but that's an implementation detail.

11:48 unlink: Besides, if you're using an adapter, then the URI and the path-info are always equivalent.

11:48 unlink: weavejester: To me, path-info versus uri is an application-level concern, and should be part of the real application HTTP gateway (i.e. ring) API. If the adapter doesn't give you path-info, then the adapter is the place for the facade, not the app

11:49 johnkpaul: weavejester: so in my current project.clj, the plugin that I want to wrap is a dev dependency, is that just the old name for plugins?

11:49 weavejester: johnkpaul: dev-dependency is basically the old name for plugins, yes. It's a little more complex, but that's the gist.

11:50 johnkpaul: Pre 1.7, Ring deps were a little messy. After 1.7 they're divided into two clean parts: ones for Lein, and ones for your project.

11:50 johnkpaul: ah ok, cool, I'm continuing to work on it

11:50 paulfryzel: hey

11:51 unlink: weavejester: Is there an abstraction in Ring for prefix-based dispatchers in middleware?

11:51 weavejester: unlink: Ring is an interface to incoming HTTP requests. It isn't an application layer in the same way that Java servlets are.

11:51 unlink: Straight Ring you basically just get the raw HTTP request. Anything more than that is beyond the Ring spec.

11:52 unlink: There isn't, but I've been considering a wrap-context for Ring 1.2

11:52 unlink: weavejester: It would be very helpful to have something analagous to SCRIPT_NAME versus PATH_INFO for both of these purposes.

11:53 weavejester: unlink: Why?

11:53 unlink: i.e. uri === (str script-name path-info)

11:54 weavejester: unlink: What's your use case, exactly?

11:54 unlink: weavejester: Then I could write my application in such a way that it doesn't care whether it is (a) run directly by an adapter, (b) dispatched to by a prefix-dispatching middleware, or (c) run in its own context prefix by tomcat.

11:55 weavejester: unlink: That's really a routing problem though, and therefore a problem for your routing library.

11:57 johnkpaul: hmm, so weavejester, I somehow accidently created a new task, rather than wrapping an existing task

11:57 I keep getting this exception java.lang.Exception: Unable to resolve var: leiningen.cljsbuild/repl-listen in this context (hook.clj:7)

11:57 even after adding eval-in-leningen true

11:57 weavejester: johnkpaul: Leiningen looks for: leiningen.<task>/<task> to handle tasks

11:58 johnkpaul: where? inside project.clj?

11:58 weavejester: johnkpaul: If you run "lein foo", then Leiningen will look for leiningen.foo/foo in the project classpath.

11:59 johnkpaul: ah ok

11:59 unlink: weavejester: Why should my application care whether its router is called by run-jetty, tomcat, or dispatched to by some other middleware?

11:59 weavejester: johnkpaul: If you want a hook, you need to write an "activate" function

11:59 johnkpaul: oh, really?

11:59 I'm using this as an example...

11:59 https://github.com/clojurebook/ClojureProgramming/blob/master/ch08-lein-mixed-source/project.clj

11:59 weavejester: unlink: It shouldn't, which it why your routing library should check :path-info, and then :uri.

12:00 johnkpaul: This style is preferred: https://github.com/weavejester/environ/blob/master/environ.lein/src/environ/leiningen/hooks.clj

12:00 johnkpaul: oh, so where do you call activate?

12:01 weavejester: johnkpaul: Leiningen calls it when you add the namespace as a hook.

12:01 johnkpaul: oh, I see

12:01 unlink: weavejester: If routing libraries need to do that, that is a sign to me that :path-info belongs in some commonly agreed-upon spec for HTTP applications. Why should routing libraries know about the implementation of who deployed them?

12:01 johnkpaul: so that I understand, but in your example, you wrap #'leiningen.core.classpath/resolve-dependencies

12:01 and that is part of the core, so it's found

12:02 I am trying to wrap #'leningen.cljsbuild/repl-listen

12:02 and even though leningen.cljsbuild is in dependencies and dev dependencies and plugin, it's still not found

12:03 unlink: weavejester: without being in the Ring spec, :path-info is merely an implementation detail of libraries which offer war-based deployment. Now my routing library needs to incorporate knowledge of the implementation of those war adapters in order to give a generic interface to applications.

12:03 weavejester: And this still leaves open the issue of composable routing libraries.

12:04 weavejester: unlink: At some point we may want to formally document it. Currently it's a defacto standard, and defacto standards are not necessarily bad. It doesn't belong in the Ring SPEC, because HTTP requests have no concept of :path-info or :context.

12:05 unlink: It's also a single key designed primarily for compatibility with legacy applications, although the context macro in Compojure is kinda useful.

12:06 unlink: weavejester: Perhaps what we need then is another spec which formalizes commonly useful keys for interoperable and composable HTTP middleware, then.

12:06 weavejester: unlink: It's worth pointing out that standard keys like :params and :cookies are also not in the Ring spec.

12:07 unlink: :path-info is really only useful for internal routing and legacy compatibility.

12:07 unlink: weavejester: Except that will end up looking just like Ring, but with path-info added. The prior art here, of course, is WSGI and Rack, which both distinguish between SCRIPT_NAME and PATH_INFO.

12:10 weavejester: unlink: It's important to understand that the Ring SPEC describes an abstraction over HTTP and nothing further.

12:10 unlink: path-info ans script-name are not an intrisic part of HTTP, therefore should not be part of the SPEC

12:10 unlink: In Ring 1.2, I may add some wrap-context middleware to core

12:11 unlink: But adapters won't intrinsically add :path-info

12:11 unlink: weavejester: Right, but I contend that HTTP makes a fine spec for HTTP, and what is really needed is an abstraction for HTTP-based middleware.

12:12 weavejester: unlink: Which would just be :path-info and :context, presumably?

12:13 unlink: I'm not certain there needs to be a specific spec for :path-info and :context. There isn't one for parameters, cookies, sessions or file uploads.

12:14 unlink: The way the core middleware behaves effectively defines standard keys and behavior

12:14 unlink: weavejester: an example of SCRIPT_NAME in action: https://github.com/lukearno/selector/blob/master/selector.py#L135

12:14 weavejester: unlink: We haven't seen anyone deviate from that, yet. No-one's writing their own parameter or cookie middleware that's incompatible.

12:15 unlink: WSGI handler delegation is just another term for "routing library", at least in Ring terms.

12:15 unlink: weavejester: Well, informally specified standards for middleware is fine except that omitting path-info from the ring adapters encourages middleware developers to depend on :uri and thus author non-composable middleware

12:16 especially since application developers will also be depending on :uri.

12:16 weavejester: unlink: Hm. Most of the time middleware doesn't need to directly access the URI, however.

12:16 unlink: weavejester: Right, it's only when you're doing any redirecting when the full URI is useful.

12:17 weavejester: unlink: In the case of wrap-resource and wrap-file, but aside from static file handling...

12:17 johnkpaul: so weavejester, I'm using trampoline

12:17 so I don't think that eval-in-leiningen works

12:17 weavejester: unlink: What I could do is add a ring.util.request/path-info function to Ring 1.2...

12:18 johnkpaul: There's no point in trampolining if you're evaluating in Leiningen.

12:19 johnkpaul: yeah, I know, but I don't really care about evaluating in leiningen, I just want the end result to wrap cljsbuild's repl-listen

12:19 which, according to their docs, should be launched by using lein trampoline cljsbuild repl-listen

12:19 unlink: weavejester: Whatever you do, the goal as I see it is to encourage middleware and application developers to consume path-info, and avoid uri (except for redirecting)

12:19 johnkpaul: I didn't realize what trampoline meant until now

12:19 if it's another JVM, how do I get hooks into there

12:19 sattvik: weavejester, unlink: I'll just mention that path-info is not servlet-specific. It's part of the CGI specification.

12:20 weavejester: sattvik: That's a different spec to Ring, however. Ring operates at a lower level. The Ring SPEC is just concerned about HTTP requests.

12:21 unlink: Hm… What sorts of middleware, beside ones serving static resources, would need the path-info or the URI?

12:22 johnkpaul: As far as I'm aware, hLein ooks are just for hooking into Lein itself, not into subprocesses.

12:22 unlink: weavejester: Application-level middleware that checks for a logged-in user and redirects to a login page would want to know the URI, for example.

12:23 johnkpaul: oh ok, so in order to wrap tasks that are trampolined, I'd have to modify the original plugin?

12:23 weavejester: unlink: So for absolute redirects. Hm, I could see that being the case.

12:23 sattvik: weavejester: Sure, I understand. I'm just saying that a lot of legacy applications/frameworks rely on these things. To someone who is starting with ring/compojure/noir, it can be confusing.

12:24 johnkpaul: I will go feature request cljsbuild, and for now just do some of this manually

12:24 weavejester: johnkpaul: If you want to hook into something outside of Lein itself, then yes. I believe lein-cljsbuild adds a cljsbuild dep and runs from that.

12:25 johnkpaul: what do you mean?

12:26 weavejester: unlink: I'll put some standard functions in to Ring 1.2, I think… if we have a practical problem after that, we can consider a guide or spec.

12:26 johnkpaul: sorry, I don't know all of the terminology

12:26 so the plugin lein-cljsbuild has it's own project.clj and adds iself as a dependency?

12:26 bobbywilson0: Is there access to an "index" in a sequence?

12:26 unlink: weavejester: The most compelling argument I see for augmenting the ring spec itself, inasmuch as it is expressly not aiming to specify a middleware API is the fact that many production environments (including newly deployed ones) only expose the context path as a deployment concern...i.e. it is out of the hands of the developer

12:26 weavejester: johnkpaul: Okay, so the project.clj file is converted into a map by Leiningen, and this map is passed to Leiningen plugins like lein-cljsbuild.

12:27 johnkpaul: If these plugins want to do anything in the classpath of the project, typically they'll assoc a new dependency into the project map, and then run "eval-in-project" with the altered map.

12:28 johnkpaul: ooh, I see, I didn't realize that's how the plugin system worked

12:29 unlink: weavejester: A slightly less compelling argument is that developers coming from other platforms (including Java) expect a somewhat higher-level API to develop their applications against, which incorporates routing concerns in the specification of the gateway API.

12:29 weavejester: johnkpaul: When you "eval-in-project", you're evaluating in the context of the project's dependencies, rather than Lein, which is why I don't think you can hook into it.

12:31 unlink: weavejester: Naturally that does come with practical benefits, namely that deploying on top of tomcat looks like like being run by an adapter, or being mounted under another Ring routing library.

12:31 johnkpaul: oh, so in order for me to do this cljsbuild would need to provide their own hooking functinoality

12:32 weavejester: unlink: The Ring SPEC won't be augmented with keys that can't be directly derived from the HTTP request map. Good Clojure practise is to keep things simple, i.e. something that does only one thing. Complecting the SPEC isn't the right solution, I don't think.

12:32 johnkpaul: thanks so much for your help weavejester, I need to work on something else for a bit, but I'll be back with more questions I'm sure

12:33 weavejester: unlink: If we need another spec that builds on Ring, okay, but for now the defacto standards don't seem to be causing any issues.

12:35 unlink: Ring is deliberately a low-level interface. Protocols and standards work best when they're layered on top of each other. Try to do too much and you get something horrible like Java servlets.

12:36 unlink: weavejester: But perhaps Ring is slated as a lower-level tool than it is actually used for. cf. lein.ring.war which must generate code to step over Ring so your application knows what path was intended for it.

12:37 weavejester: Unless there are native "ring containers" I don't know about which compete with tomcat, glassfish & kin.

12:38 weavejester: unlink: Ring containers are just handlers.

12:39 unlink: And layering additional functionality using middleware, as lein-ring war does, is good practise

12:41 unlink: weavejester: I agree that middleware should send middleware-specific information downstream in that manner. What I don't agree with is the notion that uri versus path-info is incidental to consumers of the Ring API.

12:42 weavejester: unlink: The Ring SPEC is *just* about abstracting HTTP requests. If we want anything more, then we should build something on top of that spec, not extend it.

12:43 unlink: Well, HTTP requests and responses.

12:45 unlink: weavejester: For certain, HTTP has no notion of path-info versus URI. The practical matter, however, is that Ring API consumers are not primarily useful in a pure HTTP environment. If you were starting from the ground up, it may make sense to have a separate protocol specifying best practices around routing middleware conventions. But as it stands, Ring applications live in a world of context-root-aware deployments. It just so happens to be the case th

12:47 weavejester: unlink: It depends what environment you're talking about, there is a trend toward using smaller web services with their own subdomains.

12:48 unlink: However, regardless of how useful it is in practise, it is not a good idea to take two standards that have two different purposes, and try to combine them in the same spec

12:48 unlink: That way lies madness, and Java servlets, and other horrors.

12:49 unlink: weavejester: By informally specifying the distinction between URI and consumed-unconsumed path in lein.ring.war, you are simply moving that informal specification to the absolute root of the middleware stack.

12:49 weavejester: unlink: But in practise, that hasn't been a problem so far.

12:49 unlink: If it becomes a problem, then we can create guidelines or additional standards.

12:49 unlink: weavejester: For sure, mixing of concerns is the root of all evil. My contention is merely that HTTP isn't the right concern to be concered about (but it is damn near close).

12:50 weavejester: unlink: A HTTP-application spec would be built on top of a HTTP spec, so there's no reason to join them together.

12:50 unlink: weavejester: Well, I'm not sure that is quite true. Every other language's analog to Ring I know of makes this distinction, and I have seen this issue raised about Ring a couple times in the past (and I experience it as well).

12:51 weavejester: unlink: Then let's try adding in some standard functions in Ring 1.2 to encourage people in the right direction

12:52 unlink: But aside from a few questions, I haven't seen any indication it's a significant problem.

12:52 unlink: Both Noir and Compojure support it without issue.

12:52 unlink: weavejester: Yes...at a certain point, the spec is merely an implementation detail. What truly matters is what middleware and application developers write.

12:54 weavejester: unlink: I think I agree that we at least need a path-info function in Ring 1.2, and to make wrap-resources and wrap-file context-aware.

12:56 unlink: weavejester: I admit I am not using any static-file-serving middleware... I just leave that to Tomcat (or nginx, depending)

12:59 On a completely unrelated note, how should I troubleshoot wrap-reload? I am getting it to detect changes at the module level, but not inside my handlers.

13:00 weavejester: unlink: wrap-reload looks through a directory tree (default "src") for modified files, and then reloads all the namespaces that use that file

13:00 unlink: What do you mean by "detect changes at the module level"?

13:02 unlink: weavejester: If I have a naked (println "hello") at the top level of the namespace, it will execute that the first time I make a request after updating the file. However, changes to the handlers themselves are not picked up on (within the same file).

13:02 weavejester: unlink: Oh, I see. You'll need to pass in your handlers as vars

13:02 unlink: Otherwise they're passed in as values, so Clojure won't update them if their definition changes.

13:03 (wrap-reload #'your-handler) should do it

13:03 unlink: weavejester: aha. I was missing a level of dereference.

13:04 weavejester: unlink: It's easy to miss. I accidentally factored out that behavior in lein-ring for a few versions, until someone pointed out the mistake.

13:07 unlink: weavejester: great, it's working now.

13:10 weavejester: As I understand it, lein ring server-headless should not open a browser window, correct?

13:10 It is for me, with lein-ring 0.6.2.

13:10 weavejester: unlink: Yes, but there was an issue with that, that was only fixed in 0.6.3

13:11 unlink: Well, aren't I behind the times.

13:11 weavejester: unlink: If you don't want that behavior, you can also add a :ring {:open-browser? false} to your project.clj

13:11 unlink: that's better.

13:12 weavejester: unlink: Or, if you have lein2, you can turn it off in your ~/.lein/profiles.clj for all projects

13:12 unlink: I have to admit I'm not quite ready to take the plunge O:-)

13:15 technomancy: nice hat

13:16 unlink: thanks. up here we call them halos.

13:56 oc: whats the name of the jline + colours + other extensions to the repl that comes with homebrew?

13:57 technomancy: oc: I don't know what homebrew has, but you should use reply

13:57 https://github.com/trptcolin/reply

13:59 oc: thats the one, thought i installed it with brew at work :)

13:59 thanks

14:02 acctually on second look it's not the same, but this seems good

14:05 technomancy: reply is the best

14:10 jtoy: can anyone recommend a clojure library that will get me the domain from a url like twitter.com from twitter.com/asdas/dasd/sadsadsad and google.com from google.com/asdasdas/asdasd/sadsa/d?123123=12321 ?

14:11 technomancy: (.getHost (java.net.URL. "http://twitter.com/asdas/dasd/sadsadsad"))

14:11 ,(.getHost (java.net.URL. "http://twitter.com/asdas/dasd/sadsadsad"))



14:11 oops

14:11 antares_: jtoy: urly

14:11 jtoy: but yes, for simple cases java.net.URI is sufficient. Just in case: https://github.com/michaelklishin/urly

14:12 jtoy: ok, i was thinking in clojure because i've never even programmed in java, and i don't plan to really even though clojure is on top of java

14:14 antares_: jtoy: then just use urly

14:14 llasram: Honestly, I'm not sure how feasible that is general, at least in the sense you seem to mean it. Clojure is designed as a hosted language, and depends on the hosting platform for a variety of features

14:15 antares_: jtoy: (host-of "https://google.com") should do what you want. It can also work with java.net.URI, java.net.URL and some more inputs

14:15 llasram: You can't even do most string operations without calling methods on java.lang.String instances

14:15 jtoy: llasram: yeah, I'm avoiding it as much as a can, yeah I've had to use a couple of simple string methods from java unfortunately

14:15 technomancy: jtoy: calling java methods is not programming in java

14:15 there's nothing unfortunate about that

14:16 antares_: llasram: I think the point is that some people are not familiar enough with JDK APIs. urly wasn't created to hide JDK classes from you, but it also may be a bit nicer for someone who never used java.net.URI.

14:17 jtoy: I am the creator of urly, so if you run into issues, let me know

14:17 llasram: antares_: Right. That's why I added "in general" :-) Urly looks to add some useful extra features, but using it just to avoid directly using URL/URI is probably not beneficial

14:17 jtoy: antares_: cool, thanks

14:17 antares_: llasram: I agree. urly covers areas JDK classes do not. I absolutely did not intend to discourage java.net.URI usage, etc.

14:18 jtoy: its unfortunate that if you don't program java, and as someone who wants to leaner a cool new language like java, they must essentially learn 2 languages

14:18 like clojure

14:19 technomancy: you don't need to learn Java

14:19 you need to learn some Java libraries

14:19 hiredman: *shrug* java is not very hard to pick up

14:20 emacsen: hiredman, yeah, it kinda is :)

14:20 technomancy: emacsen: to write, maybe

14:20 emacsen: there are still some concepts I'm fuzzy on, like "Interfaces"

14:20 jtoy: hiredman: it doesn't matter if its hard or not, the goal is to learn and program clojure, adding more things to learn and do slows you down no matter how easy it is

14:20 llasram: And it's not even really "Java libraries" -- it's more "JVM libraries." You can completely ignore anything about e.g. generics. Although maybe that makes it harder for someone completely new to the environment?

14:20 hiredman: emacsen: compared to what?

14:20 antares_: jtoy: that's another side of having all the Java ecosystem tools and libraries at your disposal. I think over time there will be more and more tools and libraries that require 0 Java knowledge. But learning JDK APIs is still very very helpful.

14:20 emacsen: hiredman, Python, Ruby, even Clojure

14:20 technomancy: llasram: right; if you didn't have that, then Clojure itself would be a much larger language

14:21 or a much less useful language

14:21 antares_: llasram: not having to worry about generics or checked exceptions is definitely a good thing for newcomers :)

14:21 hiredman: emacsen: in what way is java harder to pick up then either of those?

14:22 llasram: antares_: Oh man. I like to forget checked exceptions even exist.

14:22 emacsen: hiredman, I just find it harder. harder to read, harder to grok. More concepts, more verbose. harder to debug

14:22 technomancy: certain Java codebases are difficult to read if they go nuts with patterns and crazy abstractions

14:22 hiredman: emacsen: that is hardly objective

14:22 technomancy: as are ruby codebases that go nuts with method_missing and metaprogramming

14:23 even though I would find it very tiresome to write, having classes specified everywhere actually helps a lot in reading code

14:23 hiredman: you can write clojure to generate your java source!

14:55 devn: i wrote clojure to generate my ruby source

14:55 * devn is clearly an evil bastard

15:03 oc: oh. the joy of having 1200 reminders dumped into your mailbox.

15:04 any of you put in a suggestion for a talk @ JavaZone 2012?

15:06 mega: no :(

15:08 oc: only see Stuart Sierra; need more! Go submit talks at www.javazone.no :)

15:09 It's the same week as CUFP and ICFP... 1 hour flight! Do a tour!

15:16 technomancy: can't promise anything, but if it happens to be another debate on build tools, I'd like to see leiningen represented :)

15:31 rlb: Is there some idomatic way to run something every N minutes, or would java executors be a reasonable choice?

15:31 amalloy: executors

15:32 antares_: rlb: if you need more power, Quartz (and quartzite) is a good option. Here's my Clojure DSL on top of Quartz: https://github.com/michaelklishin/quartzite

15:32 rlb: but scheduled executors is very often all you need

15:34 rlb: ok, thanks

15:47 chouser: does anyone have an opinion about redefining ->Foo to take different args and/or do non-default things to construct and instance of record type Foo?

15:47 s/construct and/construct an/

15:48 konr: Hi! I've submitted my proposal for GSoC. Can you check if there's something missing, or in case you have a specific request? http://www.google-melange.com/gsoc/proposal/review/google/gsoc2012/konr/29002

15:49 amalloy: chouser: my opinion is that you should just add a different function to do that, like make-Foo-the-easy-way

15:50 Raynes: chouser: My opinion is that amalloy's opinion is sound and that I'd be likely to throttle you if you did what you were thinking of doing.

15:51 llasram: chouser: I'd worry it could be confusing, but how often do people actually use the ->Foo constructor functions?

15:51 (the ones defined by `deftype`, that is)

15:51 Er, defrecord even

15:51 chouser: all good points

15:52 llasram: If people don't use them often, I think it could make sense to replace it. Make a new Clojure convention that ->Foo is your default factor function for Foos

15:53 What do people see as the normal convention right now?

15:53 chouser: I don't think there is one

15:53 make-Foo, new-Foo, and create-Foo are all relatively common, afaik

15:54 llasram: Yeah, and `mk-foo`. I've been doing just `foo` (lowercase) myself, but maybe there are pitfalls there?

15:55 chouser: llasram: that's actually common in clojure itself. nouns used as a verb create the thing

15:55 atom, agent, hash-map, vector, etc.

15:55 llasram: Ah yeah! I must have picked up on that subconsciously :-)

15:55 chouser: But you can't do that with a class name. Foo is the class, not a function that creates one.

15:57 llasram: But if you want to treat the class as an implementation detail, then I think having a function `foo` which creates a Foo makes sense

15:58 Or maybe it makes things impossible to read on large code-bases. None of my Clojure projects are very large yet

16:13 sjl: I thought I remembered someone in here saying they were working on a Django-like templating library a while ago... am I going crazy or does that exist?

16:16 devn: can cl-format convert back from roman numerals to digits?

16:17 (cl-format nil "~something-magical" "III") => 3

16:21 * dnolen is thinking about optimizing away CLJS truth tests when possible

16:32 mrb_bk: dnolen: whattup buddy

16:35 dnolen: wondering if you have resources re: zippers that we were talking about with undo/redo

16:41 oskarth: Using clojure with mongodb and I want to store dates. MongoDB suggests ISODate (standard 1970 second time) but the only clojure date function I found is java.util.Date. Is there any harm done in using the java one?

16:41 technomancy: clojurebot: java.util.Date?

16:41 clojurebot: excusez-moi

16:42 technomancy: oskarth: yes, java.util.Date is the worst class in the JDK. look at clj-time

16:42 oskarth: it speaks french but not java

16:42 technomancy: thanks for the heads up

16:42 technomancy: clojurebot: java.util.Date is the worst class in the entire JDK.

16:42 clojurebot: Roger.

16:42 oskarth: :D

16:43 antares_: oskarth: no

16:43 unlink: How would you say this more concisely? (fn [m] (assoc m :x (or (:x m) y)))

16:43 assoc-if-missing

16:43 antares_: oskarth: if you go with Monger (https://github.com/michaelklishin/monger), it has a way to store JodaTime dates, too

16:43 unlink: maybe-assoc

16:44 technomancy: unlink: (merge {:x y} m)

16:44 unlink: ah, much better. thanks.

16:45 oskarth: antares_: using congomongo at the moment, but will check it out too, thanks

16:50 oc: Could anyone suggest a couple good and inspiring Clojure speakers to me? (besides Rich ;)

16:52 dnolen: mrb_bk: probably best to looks a libs that use zippers for undo/redo, http://fhcrc.github.com/taxtastic/refpkg.html, here's a Python one.

16:53 mrb_bk: and, also yo! JSConf was good times.

16:53 justin`: I think I'm missing something stupid. I'm trying to change an atom in cljs. Anyone know why (def a (atom nil))(swap! a identity "hello")(js/alert @a) isn't working for me?

16:55 hiredman: identity takes a single argument

16:56 dnolen: justin`: you probably just want reset!

16:56 justin`: dnolen: doh! exactly, thanks!

17:07 mrb_bk: dnolen: thanks!

17:07 dnolen: yeah, was a balst

17:51 antares_: oskarth: if you don't need clojure.data.json or joda time integration, congomongo is probably

17:51 oskarth: monger is much better in my opinion but I am biased because it's my project :)

17:51 oskarth: oops, congomongo is fine is what I was saying :)

17:52 oskarth: antares_: how hard is it to switch? thinking about heroku/mongolab integration

17:52 I used to use karras, but ran into problem when trying to remote connect, so I followed some example with congomongo. Would've given monger a shot otherwise

17:52 antares_: oskarth: should be pretty easy, both are pretty small libraries

17:53 oskarth: antares_: roger, will check it out

17:53 antares_: oskarth: monger should work fine on heroku. If there are ways to be more heroku friendly (like using some env variables for connection), I will happily add it

17:54 oskarth: we do this to support neo4j on heroku with neocons, another my project: http://github.com/michaelklishin/neocons, and langohr, my AMQP 0.9.1 client (http://github.com/michaelklishin/langohr) uses heroku's RABBITMQ_URL

17:54 so, adding stuff for heroku is very welcome

17:54 I am just not sure what else heroku users may need

17:54 oskarth: antares_: cool, currently I use a MONGOLAB_URI env which gets splitted into db, host, port etc

17:55 antares_: oskarth: ok, I think if you give me an example, I can add it over the weekend.

17:55 technomancy: on the library level it's best to just support configuring the connection as a string

17:55 antares_: oskarth: we can iterate over env variables present, like MONGOLAB_URI or MONGOHQ_URI

17:55 technomancy: and have the application pass in the value of (System/getenv "whatever")

17:55 * antares_ nods

17:55 technomancy: the key is to support a URL as well as a map

17:56 antares_: that's trivial

17:56 technomancy: with mongo it is a bit more tricky, though

17:56 technomancy: https://github.com/clojure/java.jdbc/commit/690296ba858c2d0e0f04bcd981addd48fa39c03f

17:56 antares_: technomancy: mongodb has mongo options most complex apps have, a way to configure client thread pool and such

17:56 it cannot be passed in as a string

17:56 but everything else can and I will make sure monger supports it

17:56 technomancy: oh, sure

17:56 oskarth: antares_: I use something very similiar to http://blog.markwatson.com/2011/10/experimenting-with-clojure-13-and-noir.html

17:56 technomancy: but that's different from connection parameters

17:57 antares_: oskarth: ok, well, technomancy is suggesting making it a bit easier on app authors and I agree

17:57 oskarth: I don't think that approach is anything mongodb-driver specific though

17:57 antares_: monger should accept URIs for connection

17:57 oskarth: it's not

17:57 oskarth: that would be great

17:57 antares_: but it's not the easiest thing possible

17:57 oskarth: indeed :)

17:58 added monger to watch list

18:05 sivajag: hi

18:05 as anyone used compojure with clojure 1.3?

18:08 seancorf`: who is going to the Bay Area Clojure meetup tonight?

18:09 technomancy: ~anyone

18:09 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 ..."

18:09 seancorfield: LOL

18:09 well, i know you are _not_ going to seajure tonight :)

18:09 technomancy: seancorfield: hah; no that was for sivajag

18:10 sivajag: :)

18:11 weavejester: sivajag: You might want to post the error you're getting

18:11 sivajag: I don't believe it's Compojure-specific.

18:12 sivajag: when I use compojure with clojure 1.3

18:12 i am getting this error

18:12 (use 'compojure.core)

18:12 NoSuchMethodError clojure.lang.KeywordLookupSite.<init>(ILclojure/lang/Keyword;)V clout.core/request-url (core.clj:53)

18:12 with 1.2.1 it works fine

18:12 hiredman: abi compat issue

18:12 code compiled with a different version of clojure than what you are using

18:12 antares_: sivajag: something loaded Clojure 1.2

18:13 Raynes: rm -rf classes/

18:14 sivajag: Raynes: tried doing … same error

18:14 antares_: let me check my dependencies …

18:15 antares_: sivajag: it may be something like tools.cli or data.json, you need to exclude clojure dependency for them like so: [org.clojure/tools.cli "0.2.1" :exclude [org.clojure/clojure]]

18:16 weavejester: Wouldn't a dependency have to be something like "[1.2.1]" to force an earlier version of Clojure?

18:17 seancorfield: antares_: all the new contrib libs are source only so those should not cause ABI issues?

18:17 antares_: seancorfield: my experience shows that they do

18:17 seancorfield: it may be an interplay between how leiningen loads things but something used to drag 1.2 onto the classpath, it hit several of my OSS projects

18:18 I think one of org.clojure/* artifacts was republished to retroactively add 1.2.1 compatibility

18:18 and because all my projects are 1.3.0+, I had exactly this issue several times

18:19 I have seen this on travis-ci.org multiple times, too

18:19 and helped a few projects pin point problematic dependencies

18:20 sivajag: can you share your dependencies list via gist or refheap?

18:20 sivajag: antares_: ok

18:21 antares_: http://pastebin.com/wweTw6B7

18:22 * Raynes chuckles.

18:23 antares_: sivajag: try adding :exclude like I pasted above for compojure and ring

18:23 sivajag: I see compojure has 1.2.1 dependency

18:23 sivajag: ok let me try

18:24 weavejester: antares_: In theory that shouldn't matter unless the dependency is "[1.2.1]"

18:24 Raynes: sivajag: Can you confirm what Clojure version is in lib/

18:24 weavejester: You're right, it doesn't.

18:24 sivajag: ok

18:24 antares_: sivajag: also, I suggest that you try clj-http 0.3.6, it is definitely 1.3.0-ready while 0.2.3 may not be

18:24 *may be not

18:25 sivajag: clojure-1.4.0-beta3.jar

18:25 Raynes: Is that the only clojure jar?

18:25 sivajag: yah

18:25 dakrone: clj-http 0.2.3 is compatible with clojure 1.3, but you should use 0.3.6 regardless since there have been bugfixes

18:25 Raynes: If so, the excludes aren't going to help and one of your dependencies has AOT'd code that was compiled against Clojure 1.2.

18:26 sivajag: Raynes: how do i find them?

18:26 dakrone: updating clj-http and let me try

18:27 dakrone: same error

18:28 dakrone: from the original exception, it looks like an issue with clout

18:28 Raynes: Pretty sure it is clj-oauth2.

18:28 clj-oauth2 is AOT compiled for some reason and uses an ancient version of most everything.

18:29 There is a newer version of it though.

18:29 0.2.0

18:29 I'd try that and see what happens.

18:30 sivajag: ok first let me try removing it

18:30 and then I will try updating it

18:33 user=> (use 'compojure.core)

18:33 NoSuchMethodError clojure.lang.KeywordLookupSite.<init>(ILclojure/lang/Keyword;)V clout.core/request-url (core.clj:53)

18:33 now I have dependencies only to [org.clojure/clojure "1.4.0-beta3"]

18:33 [compojure "1.0.1" :exclude [org.clojure/clojure]]

18:33 [com.datomic/datomic "0.1.2753"]

18:38 Found the issue

18:38 I had storm in my dev dependencies

18:38 once I removed it works fine

18:40 aaelony: what is the best way to repeat the first element of a vector 5 times, then the 2nd element 5 times, ..., nth element of the vector 5 times ?

18:41 sivajag: thanks guys

18:42 Raynes: &(mapcat (partial repeat 5) [1 2 3])

18:42 lazybot: ⇒ (1 1 1 1 1 2 2 2 2 2 3 3 3 3 3)

18:42 Raynes: Damn him.

18:42 aaelony: wow... sweet

18:42 thanks, raynes!

18:42 Raynes: Oh, you're still here.

18:42 :)

18:42 aaelony: haha yah

18:42 Raynes: I saw your ghost leave.

18:42 :p

18:43 aaelony: i realized i had another box on

18:47 mk: how can I rewrite (bin3 v (fn [x] (bin3 (fa x) fb))) so that it doesn't have the fn, or is otherwise pretty?

18:52 S11001001: mk: (bin3 v #(-> % fa (bin3 fb)))

18:54 mk: S11001001: can that be done without the anonymous function?

18:56 S11001001: mk: I couldn't possibly tell you, not knowing what bin3 is. A function allowed to treat any function arguments as having indefinite extent (see the reader and state monads for exceptionally good examples of the power this gives you)

18:56 but the result is that in general the translation from a program that uses closures to one that doesn't is not trivial, and requires deep knowledge of the underlying functions

18:56 mk: S11001001: indefinite extent?

18:58 S11001001: mk: may continue to live effectively forever (in reality, until GCed), as opposed to dynamic extent, such as you get with references to stack-allocated objects in C++

18:59 mk: S11001001: do you just mean that clojure has closures?

19:00 S11001001: mk: it's more than that; a closure may have dynamic extent and still be a closure

19:01 it is just not as interesting

19:01 mk: S11001001: I'm not sure how a closure that expires very quickly (if I'm understanding you right) counts as a closure

19:02 S11001001: because it still refers to the lexical bindings in effect when it was created

19:02 so, the thing is, bin3 can call the function you give it any number of times, or it could even return a result that includes it wrapped in some other bits

19:03 mk: yes - I see no problem so far

19:03 S11001001: you can write combinators like comp, partial, and flip that take functions and produce functions

19:03 but the result probably won't be prettier

19:04 (bin3 v (comp (partial (flip bin3) fb) fa))

19:04 mk: S11001001: the function there is just a test of the 3rd monadic law

19:04 S11001001: at this point I would say the version with lambda is clearer

19:05 mk: (= (bin3 (bin3 v fa) fb) (bin3 v (fn [x] (bin3 (fa x) fb))))

19:05 S11001001: oh, ok

19:05 in that case, you might want to restate your laws in terms of fmap and join

19:06 mk: I'm trying to get my head around it, and I'm bogged down in the clojure syntax

19:06 S11001001: how might I do that?

19:09 dnolen: ibdknox: btw, playing with optimization stuff a lot more recently.

19:10 ibdknox: removing truth tests will help, but I'm realizing that one of the biggest things burning us now are related to how we handle complex expressions to if.

19:11 S11001001: mk: restate fmap as lift, and prove that (= ((lift (comp f g)) v) ((comp (lift f) (lift g)) v)) for functors, and so on

19:11 the laws for join are different from the ones for bind

19:12 but the result is the same

19:14 mk: is (= ((lift (comp f g)) v) ((comp (lift f) (lift g)) v)) the third monad law in its totality?

19:14 S11001001: it's associativity for functors; there are further laws related to join

19:14 not having curried functions means that lambda expressions are much more useful in clojure than they otherwise would be

19:16 if you prefer let, consider (letf [(name [args] result)] expr)

19:16 ta ta

19:16 mk: thanks

20:27 jtoy: how would you guys recommend to do url unrolling in clojure or in java?

20:28 the-kenny: Is there a fix/workaround for `lein swank' when Emacs locking tokens (.#foo.clj -> user@host...) are in the src-tree? It always throws a java.io.FileNotFoundException when I have unsaved files in emacs.

20:28 dnolen: jtoy: why would you need to do that in Java?

20:28 jtoy: well unless there a library you want to use or something.

20:28 jtoy: dnolen: because clojure is built on java? I'm new to both so not sure how people do it in either language

20:30 dnolen: jtoy: there's little need these days to write anything Java if you're using Clojure.

20:30 jtoy: dnolen: string splitting!

20:31 dnolen: but yeah, i agree, i was asking how to do something earlier today and people were telling me to use java

20:31 dnolen: jtoy: huh. What was that?

20:31 jtoy: finding the root url from a url

20:31 technomancy: jtoy: I don't think you understood what was being said earlier.

20:31 jtoy: (.getHost (java.net.URL. domain)

20:32 technomancy: calling java methods is not "writing java"

20:32 dnolen: jtoy: do you mean they meant you should call into Java libs? that's normal.

20:32 jtoy: technomancy: yeah, i get that

20:32 dnolen: yes, thats what i meant by in java

20:32 my bad wording

20:32 dnolen: jtoy: ok, sorry I was confused then. Yes, you can often save yourself some time by calling into a Java lib.

20:33 jtoy: so what is used for finding an unrolled url in clojure or called java?

20:34 amalloy: (.getHost (java.net.Url. domain)) sounds pretty good so far

20:34 you have some reason it's awful?

20:35 dnolen: jtoy: and if you like, you could write a simple wrapper over to get a more idiomatic interface.

20:35 (:host (url domain))

20:35 jtoy: amalloy: that is different, unrolling is finding the real url, following all the redirects

20:35 amalloy: so far you haven't told anyone that's what you want to do

20:36 jtoy: amalloy: that is what url unrolling is

20:37 technomancy: ,(.getPort (java.net.URL. "http://clojure.org"))

20:37 clojurebot: -1

20:37 * technomancy stares wistfully

20:38 jtoy: seems like to do unrolling i do need to call a bunch of java :( http://stackoverflow.com/questions/2659000/java-how-to-find-the-redirected-url-of-a-url

20:39 dnolen: jtoy: the solutions look simple and easy to do.

20:39 technomancy: if you only need to "unroll" HTTP URLs, you can use clj-http

20:40 jtoy: yeah probably is, i have never written any java though

20:40 technomancy: cool, i will use that

20:42 technomancy: btw, not sure if that link is the best way to do it with regular java, but that fits into my definition of needing to write/know java

20:43 technomancy: it's a bunch of objects and the methods to call on them

21:12 muhoo: anyone seen random crashes with noir on heroku? i'm getting this: https://refheap.com/paste/1826

21:27 jtoy: technomancy: what version of clj-http are you using?

21:33 muhoo: wh, nevermind, found it: https://devcenter.heroku.com/articles/dyno-idling

21:36 a clj app that takes 60+ seconds to compile and start up doesn't seem very compatible with heroku free 1-dyno tier, unf. my bad.

21:38 i am impressed though that so much of the heroku docs seem to use clojure as an example. i suspect i see the handiwork of technomancy in this :-)

21:39 dsantiago: dnolen: What is truth inlining in cljs?

21:47 hiredman: clojurescript currently has to emit code to emulate clojureish behaviour for truthy tests in if, I imagine inlining is trying to get rid of that extra code

22:01 technomancy: muhoo: you can shift compilation to the build phase by doing "heroku config:add LEIN_BUILD_PHASE="compile :all" and enabling user_env_compile: https://devcenter.heroku.com/articles/labs-user-env-compile

22:01 that should make dyno boot much quicker

22:08 muhoo: thanks!

22:10 so it'll kind of aot compile, basically?

22:12 nm, i'll try it and find out.

22:17 senthil: how do I install a plugin?

22:18 use 1.2.1, want to install https://github.com/clojure/tools.trace

22:22 muhoo: senthil: in lein 1.7, i've been doing: lein plugin install pluginname "version"

22:22 i dunno about lein2

22:27 senthil: muhoo: does it usually install without any output?

22:29 muhoo: i don't remember. but you can check your ~/.lein/plugins directory to be sure

22:30 senthil: muhoo: it seems to be installed, but i'm not able to load it in "clj" repl

22:31 muhoo: if you type "lein classpath", what do you get?

22:31 senthil: Couldn't find project.clj, which is needed for classpath

22:32 muhoo: you're not in the project's directory

22:33 senthil: muhoo: err, what project is that? .lein ?

22:33 muhoo: oh, you haven't started a project yet, ok.

22:33 i dunno, for fun, just do "lein new someprojectname", cd into it, type "lein classpath", see if your plugins are showing up in there

22:34 senthil: muhoo: yea they're

22:34 muhoo: then try "lein repl", and try to (use it.

22:35 jay: Hi

22:36 senthil: muhoo: lein repl works, but "FileNotFoundException Could not locate clojure/tools/trace__init.class or clojure/tools/trace.clj on classpath: clojure.lang.RT.load (RT.java:430)"

22:36 muhoo: wat?

22:37 i dunno then. i'm pretty new to clojure myself, haven't seen that one.

22:37 jayunit100: So - im noticing that the if-let and when-let macros have [] rather than a function as the first form.

22:37 senthil: muhoo: https://gist.github.com/2316211

22:37 jayunit100: seems like strange syntax... Why do these macros couple the "let" to the "if" ?

22:38 muhoo: senthil: ah, are you sure that's a plugin?

22:38 it doesn't look like one

22:39 senthil: i'd try this: remove the plugin from your ~/.lein/plugins dir

22:39 then instead, do as the git page says, add [org.clojure/tools.trace "0.7.3"] to the :dependencies of your project.clj file

22:41 senthil: like this: https://refheap.com/paste/1828

22:41 xeqi: jayunit100: to avoid writing something like (let [x ..] (when x ..))

22:41 senthil: muhoo: got it, I assume I've to install it somehow

22:42 muhoo: well, if you type "lein deps", it will do that

22:42 or if you type "lein repl", it'll do that automatically AFAICT

22:43 senthil: muhoo: awesome, thx!

22:44 muhoo: senthil: np, glad to be able to help

Logging service provided by n01se.net