Re: [ANN] Optimus - a Ring middleware for frontend performance optimization.

2013-11-25 Thread Jason Bennett
Magnar, could you talk a little about how your project is better 
than/different from Stefon/dieter and cornet? I feel like we have a lot of 
these projects now, all doing mostly the same thing.

I also don't totally understand why they're all done as Ring middleware 
instead of lein/maven plugins. Maybe this is my Java background talking, 
but that seems to me to be the logical place to put this sort of thing.

jason 

On Sunday, November 24, 2013 2:00:10 PM UTC-8, Magnar Sveen wrote:

 I just open sourced optimus. README and code here: 
 https://github.com/magnars/optimushttps://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fmagnars%2Foptimussa=Dsntz=1usg=AFQjCNHVew3Ey2Bh409AV3mEhpEipbxGzQ

 Optimus is a Ring middleware for frontend performance optimization.

 It serves your static assets:

- in production: as optimized bundles
- in development: as unchanged, individual files

 In other words: Develop with ease. Optimize in production.

 *Features*

 Depending on how you use it, optimus:

- concatenates your JavaScript and CSS files into bundles.
- minifies your JavaScript with UglifyJS 
 2https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fmishoo%2FUglifyJS2sa=Dsntz=1usg=AFQjCNGjUWtc9t6OLfeCSFD67Qiv1YJHuA
- minifies your CSS with 
 CSSOhttp://www.google.com/url?q=http%3A%2F%2Fbem.info%2Ftools%2Foptimizers%2Fcsso%2Fsa=Dsntz=1usg=AFQjCNHFxxUFir_vcxqI79FeEYI-2xijmQ
- adds cache-busters to your static asset URLs
- adds far future Expires 
 headershttp://www.google.com/url?q=http%3A%2F%2Fdeveloper.yahoo.com%2Fperformance%2Frules.html%23expiressa=Dsntz=1usg=AFQjCNFc3zu6wMgQIthHxVHy4AoHDyPdQw

 Also, if you're using Angular.JS:

- prepopulates the Angular template 
 cachehttp://www.google.com/url?q=http%3A%2F%2Fdocs.angularjs.org%2Fapi%2Fng.%2524templateCachesa=Dsntz=1usg=AFQjCNE8i4GlTWl0r4u9fKoAyEipcMYAlw
  with 
your HTML templates.



 https://github.com/magnars/optimushttps://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fmagnars%2Foptimussa=Dsntz=1usg=AFQjCNHVew3Ey2Bh409AV3mEhpEipbxGzQ


-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ANN] Optimus - a Ring middleware for frontend performance optimization.

2013-11-25 Thread Jason Bennett
Ok, thanks for the reply. Cornet is at https://github.com/cosmi/cornet, 
it's similar to stefon.

I believe there are some existing middlewares for ring that do similar 
things (like wrap-not-modified). Do you replace this or work with it?

jason

On Monday, November 25, 2013 11:10:54 AM UTC-8, Magnar Sveen wrote:

 Hi Jason! 

 Magnar, could you talk a little about how your project is better 
 than/different from Stefon/dieter and cornet? I feel like we have a lot of 
 these projects now, all doing mostly the same thing.


 Thanks for asking. I'll try to shed some light on the differences as I see 
 them, and hopefully the people behind Dieter/Stefon (they're very similar) 
 can add some details into their thinking. I haven't seen Comet, and google 
 didn't help much either. Can you share a link?

 As for Optimus vs Stefon: First of all it's a difference in focus. Stefon 
 focuses on being an asset pipeline modelled after Sprockets in Rails. It 
 lets you write LESS, CoffeeScript, Haml - turning it into CSS and 
 JavaScript. Optimus is not about transpiling from other languages, but 
 about frontend optimization. As such, it rewrites your urls to include 
 cache busters and serves your assets with far-future expires headers, so 
 they can be cached aggressively in production. As I add more features to 
 optimus, they too will focus around better frontend performance - and not 
 more languages to be transpiled.

 While this is the main point in my mind, there are also other differences 
 that aren't just details that everyone will agree on. :-) These two come to 
 mind:

 1. Stefon serves assets live in development, but requires a build step in 
 production to precompile the files. Optimus does not require a build step, 
 but compiles your asset when the server starts. 

 2. Stefon creates bundles by having custom .stefon files with edn-flavored 
 lists of files in your directories of static assets. Optimus also needs a 
 list of bundles, but does so using Clojure in your program. I would think 
 that Stefons' approach is better if your frontend developers are not 
 comfortable editing the Clojure code, while Optimus' approach allows more 
 programatic control.

 I hope I haven't misrepresented Stefon in any way - these are my 
 impressions. Since I'm a front-end optimization nut, these arguments were 
 enough to sway me to create a different package. It would be several major 
 breaking changes to Dieter and Stefon's architectures and APIs, and I 
 didn't think I would get anywhere fighting for these changes in github 
 issues.

  

 I also don't totally understand why they're all done as Ring middleware 
 instead of lein/maven plugins. Maybe this is my Java background talking, 
 but that seems to me to be the logical place to put this sort of thing.


 Front-end development with a compilation step is pretty horrible. There's 
 also the case that the URL to a static asset and its location on disk is 
 entirely different after optimization.

 Hope that answers your questions somewhat decently. And if it didn't, 
 maybe you'll be swayed by the argument that a little competition is a good 
 thing for the community. :)

 - Magnar


-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Running Leiningen inside Jenkins CI server

2013-11-01 Thread Jason Bennett
Assuming you installed this plugin: 
https://wiki.jenkins-ci.org/display/JENKINS/leiningen+plugin you need to 
configure it.

Make sure that lein is installed in a place that Jenkins can get to. You 
should probably log into the box, su to jenkins, and run the lein install 
procedure. Then, go to the Jenkins configuration page (/configure) and 
scroll down to the Leiningen Builder section. Enter the full path to the 
lein jar (very possibly 
/var/lib/jenkins/.lein/self-installs/leiningen-2.3.3-standalone.jar). You 
should be good to go.

jason

On Friday, November 1, 2013 1:15:40 PM UTC-7, Simon Brooke wrote:

 I've installed Jenkins 1.537 on Debian 6, using Tomcat 6 as a servlet 
 container; brief note about the installation here: 
 http://blog.journeyman.cc/2013/11/getting-jenkins-ci-running-on-debian-6.html 
 Now, 
 I'm trying to get it to run Leiningen  and currently it isn't working. What 
 I'm getting is as follows:

 Started by user Simon Brooke https://www.journeyman.cc/jenkins/user/simon
 Building in workspace /var/local/jenkins/workspace/et-clj
 Cloning the remote Git repository
 Cloning repository file:///srv/git/et-clj
 git --version
 git version 1.7.2.5
 Checking out Revision 958f8466a11bef34143e43ba554b0d897942c2de (origin/master)
 First time build. Skipping changelog.
 FATAL: leiningen failed: leiningen jar path is 
 emptyjava.lang.IllegalArgumentException 
 http://stacktrace.jenkins-ci.org/search?query=java.lang.IllegalArgumentException:
  leiningen jar path is empty
   at 
 org.spootnik.LeiningenBuilder.getLeinCommand(LeiningenBuilder.java:111) 
 http://stacktrace.jenkins-ci.org/search/?query=org.spootnik.LeiningenBuilder.getLeinCommandentity=method
   at org.spootnik.LeiningenBuilder.perform(LeiningenBuilder.java:80) 
 http://stacktrace.jenkins-ci.org/search/?query=org.spootnik.LeiningenBuilder.performentity=method
   at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.tasks.BuildStepMonitor$1.performentity=method
   at 
 hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:781)
  
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.AbstractBuild$AbstractBuildExecution.performentity=method
   at hudson.model.Build$BuildExecution.build(Build.java:199) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.Build$BuildExecution.buildentity=method
   at hudson.model.Build$BuildExecution.doRun(Build.java:160) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.Build$BuildExecution.doRunentity=method
   at 
 hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:562) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.AbstractBuild$AbstractBuildExecution.runentity=method
   at hudson.model.Run.execute(Run.java:1665) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.Run.executeentity=method
   at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.FreeStyleBuild.runentity=method
   at hudson.model.ResourceController.execute(ResourceController.java:88) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.ResourceController.executeentity=method
   at hudson.model.Executor.run(Executor.java:230) 
 http://stacktrace.jenkins-ci.org/search/?query=hudson.model.Executor.runentity=method
 Build step 'Build project using leiningen' changed build result to FAILURE
 Build step 'Build project using leiningen' marked build as failure
 Finished: FAILURE


 Can anyone suggest what I need to be looking at?


 Many thanks



-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: logback.xml being picked up twice in project (how do I surpess the inheritted projects logback.xml)?

2013-08-15 Thread Jason Bennett
You shouldn't include the logback.xml in the generated jar file. 

Only the ultimately generated artifact should have a logback.xml file, best 
loaded from the file system (possibly through -D). It doesn't matter what 
settings base has for logging, derive should set all logging parameters.

jason

On Thursday, August 15, 2013 3:51:04 PM UTC-7, Stephen Cagle wrote:

 I have project 'base' that has a logback.xml file and project 'derive' 
 that also has a logback.xml file. Project 'derive' has a dependency on 
 'base'. When I lein trampoline repl on project 'derive', I get the 
 following warning.

 
 15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - 
 Could NOT find resource [logback.groovy]
 15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - 
 Could NOT find resource [logback-test.xml]
 15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - 
 Found resource [logback.xml] at 
 [file:/home/stephen/Work/com.samedhi/derive/client/config/logback.xml]
 15:34:30,067 |-WARN in ch.qos.logback.classic.LoggerContext[default] - 
 Resource [logback.xml] occurs multiple times on the classpath.
 15:34:30,067 |-WARN in ch.qos.logback.classic.LoggerContext[default] - 
 Resource [logback.xml] occurs at 
 [jar:file:/home/stephen/.m2/repository/com/samedhi/base.app/0.0.1-SNAPSHOT/base.app-0.0.1-SNAPSHOT.jar!/logback.xml]
 15:34:30,067 |-WARN in ch.qos.logback.classic.LoggerContext[default] - 
 Resource [logback.xml] occurs at 
 [file:/home/stephen/Work/com.samedhi/derive/client/config/logback.xml]
 15:34:30,129 |-INFO in 
 ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute 
 not set
 

 So, the problem appears to be that I have two logback.xml's in my 
 classpath. What am I supposed to do to surpress the logback.xml from 
 project 'base'?


-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: logback.xml being picked up twice in project (how do I surpess the inheritted projects logback.xml)?

2013-08-15 Thread Jason Bennett
The trick is, don't build the original jar with the logback config file. No
dependent of that jar wants to be told how to do logging. You should keep
your logback.xml in the /config directory, not in /resources.

As far as -D, that's to pass environment parameters to the JVM. See
http://logback.qos.ch/manual/configuration.html#configFileProperty for how
to configure the logback.xml location that way.

To recap: don't include logback.xml in any jars, anywhere (except for test
versions, which logback supports). Have it living in production on the file
system, and point to that file on startup. That way, you can have
environment-specific logging configured in that environment.

jason



On Thu, Aug 15, 2013 at 5:06 PM, Stephen Cagle same...@gmail.com wrote:

 I don't know what -D is, other than a one eyed laughing face. :D

 Is there some sort of standard for this? Do people simply write a script
 that checks out the code and remove files that they don't want in the
 generated jar? Is there something I can put in my project.clj that
 specifies what I *don't* want included in a generated jar? How do people
 generally go about it.

 Not that it is a big deal, mind you. It just seems a bit busy to have to
 write a special script that 1) checks out my code from github 2)removes the
 files I don't want in the jar 3) builds the jar 4) does whatever else I am
 forgetting. Seems like there might be something simpler that I don't know
 about.


 On Thursday, August 15, 2013 4:38:01 PM UTC-7, Jason Bennett wrote:

 You shouldn't include the logback.xml in the generated jar file.

 Only the ultimately generated artifact should have a logback.xml file,
 best loaded from the file system (possibly through -D). It doesn't matter
 what settings base has for logging, derive should set all logging
 parameters.

 jason

 On Thursday, August 15, 2013 3:51:04 PM UTC-7, Stephen Cagle wrote:

 I have project 'base' that has a logback.xml file and project 'derive'
 that also has a logback.xml file. Project 'derive' has a dependency on
 'base'. When I lein trampoline repl on project 'derive', I get the
 following warning.

 
 15:34:30,066 |-INFO in ch.qos.logback.classic.**LoggerContext[default]
 - Could NOT find resource [logback.groovy]
 15:34:30,066 |-INFO in ch.qos.logback.classic.**LoggerContext[default]
 - Could NOT find resource [logback-test.xml]
 15:34:30,066 |-INFO in ch.qos.logback.classic.**LoggerContext[default]
 - Found resource [logback.xml] at [file:/home/stephen/Work/com.**
 samedhi/derive/client/config/**logback.xml]
 15:34:30,067 |-WARN in ch.qos.logback.classic.**LoggerContext[default]
 - Resource [logback.xml] occurs multiple times on the classpath.
 15:34:30,067 |-WARN in ch.qos.logback.classic.**LoggerContext[default]
 - Resource [logback.xml] occurs at [jar:file:/home/stephen/.m2/**
 repository/com/samedhi/base.**app/0.0.1-SNAPSHOT/base.app-0.**
 0.1-SNAPSHOT.jar!/logback.xml]
 15:34:30,067 |-WARN in ch.qos.logback.classic.**LoggerContext[default]
 - Resource [logback.xml] occurs at [file:/home/stephen/Work/com.**
 samedhi/derive/client/config/**logback.xml]
 15:34:30,129 |-INFO in 
 ch.qos.logback.classic.joran.**action.ConfigurationAction
 - debug attribute not set
 

 So, the problem appears to be that I have two logback.xml's in my
 classpath. What am I supposed to do to surpress the logback.xml from
 project 'base'?

  --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to a topic in the
 Google Groups Clojure group.
 To unsubscribe from this topic, visit
 https://groups.google.com/d/topic/clojure/jeVTo0aWWb4/unsubscribe.
 To unsubscribe from this group and all its topics, send an email to
 clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
Jason Bennett, jaso...@acm.org
E pur si muove!
Get Firefox! - http://getfirefox.com

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: How to log a precondition in clojure 1.3

2012-12-06 Thread Jason Bennett
I hate to resurrect a dead thread, but I've been dealing with the same 
problem.

Pre/postconditions throw an Error, not an exception, meaning you have to 
catch Throwable instead. This would violate most all good practice in 
Java/JVM programming. Are pre/postconditions just not designed for basic 
validation like nil handling, or should we consider Throwable to be the 
root of Clojure exceptions?

jason

On Wednesday, March 21, 2012 4:06:11 PM UTC-7, Sean Corfield wrote:

 On Wed, Mar 21, 2012 at 9:34 AM, ron peterson 
 peterso...@gmail.comjavascript: 
 wrote:
  So I'd like to log the AssertionError using clojure.tools.logging
  library. For example if my function throws the following:
  #AssertionError java.lang.AssertionError: Assert failed: (=
  resource s)
 
  How do I redirect it to be printed in the console using the
  clojure.tools.logging library?

 Wrap the call in try/catch and log the exception in the catch.

 Exceptions are meant to bubble up to whatever can handle them.
 -- 
 Sean A Corfield -- (904) 302-SEAN
 An Architect's View -- http://corfield.org/
 World Singles, LLC. -- http://worldsingles.com/

 Perfection is the enemy of the good.
 -- Gustave Flaubert, French realist novelist (1821-1880)



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Documenting clojure data structures

2012-10-31 Thread Jason Bennett
Over the last month, I've been learning clojure for my new job, and taking 
Odersky's scala course on coursera. I've been enjoying my time with clojure 
much more, but the one thing I miss from scala is the ability to document a 
data structure. It's really nice in Java/Scala to type in an object and get 
a list of methods/members that are available, instead of having to trace 
the code and/or guess.

I've seen things in clojure like defrecord, but have not seen good examples 
of if this is a good way to give some structure to my data. I don't want to 
turn clojure into an OO language, but there are times when I'm passing 
around a large map that it would be nice to be able to know what to expect.

jason

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: let in the middle of thread-first

2012-10-26 Thread Jason Bennett
Appreciate everyone's responses! I'll certainly check out the let- option.

jason

On Friday, October 26, 2012 6:16:28 AM UTC-7, Jonathan Fischer Friberg 
wrote:

 You could also let every function take a map as input/output.
 Then, b could return a map with key :result-b or similar.
 This result would then pass through the rest of the functions and be 
 accessible in e.

 Like this:
 a ; = {:result-a ...}
 b ; = {:result-b ... :result-a ...}
 ...
 d ; = {... :result-a ...}
 e ; use :result-a

 This technique is brought up in:
 http://www.infoq.com/presentations/Thinking-in-Data

 Jonathan

 On Fri, Oct 26, 2012 at 4:43 AM, Ben Mabey b...@benmabey.comjavascript:
  wrote:

 On 10/25/12 6:24 PM, Jason Bennett wrote:


 Let's say I have a set of thread-first calls:

 (- url
  a
  b
  c
  d
  e)

 And let's say that I need to process and save the result of function b 
 as a second parameter to function e (function b returns a file, and 
 function e needs the extention of that file). How would I drop a let into 
 the middle of the thread calls without making a large mess? The only 
 suggestion I've gotten so far is to move calls A and B into a let before 
 the thread-first so I can process their return values.

 jason


 Pallet's thread-exp library has a let- macro that would do the trick:

 https://github.com/pallet/**thread-expr/blob/develop/src/**
 pallet/thread_expr.clj#L100-**106https://github.com/pallet/thread-expr/blob/develop/src/pallet/thread_expr.clj#L100-106

 I love the thread-expr library but when I spoke with Hugo Duncan at 
 Clojure West he said that pallet's use of it was largely being replaced by 
 monads.

 -Ben


 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@googlegroups.comjavascript:
 Note that posts from new members are moderated - please be patient with 
 your first post.
 To unsubscribe from this group, send email to
 clojure+u...@**googlegroups.com javascript:
 For more options, visit this group at
 http://groups.google.com/**group/clojure?hl=enhttp://groups.google.com/group/clojure?hl=en




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

let in the middle of thread-first

2012-10-25 Thread Jason Bennett

Let's say I have a set of thread-first calls:

(- url
 a
 b
 c
 d
 e)

And let's say that I need to process and save the result of function b as a 
second parameter to function e (function b returns a file, and function e 
needs the extention of that file). How would I drop a let into the middle 
of the thread calls without making a large mess? The only suggestion I've 
gotten so far is to move calls A and B into a let before the thread-first 
so I can process their return values.

jason

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en