ANN: Slamhound (for reconstructing ns forms)

110 views
Skip to first unread message

Phil Hagelberg

unread,
Apr 25, 2011, 9:05:45 PM4/25/11
to clo...@googlegroups.com
So I just threw together a little tool to help with ns forms. I find
often they accumulate a bunch of cruft over time where you no longer
need a given :use or :require form. And sometimes you don't feel like
finding exactly where on the classpath a given class is. Or maybe
you're too lazy to type it; whatever. Slamhound helps with that.

(ns my.namespace
"some doc string")

(defn -main [& args]
(pprint args)
(io/copy (ByteArrayInputStream. (.getBytes "hello"))
(first args)))

Look at that; all bare, missing all kinds of necessary stuff.
Disgraceful. Release the hound!

$ lein slamhound src/my/namespace.clj

(ns my.namespace
"I have a doc string."
(:use [clojure.pprint :only [pprint]])
(:require [clojure.java.io :as io])
(:import (java.io ByteArrayInputStream)))

Tada! (also featuring Emacs integration: M-x slamhound)

Enjoy: https://github.com/technomancy/slamhound

-Phil

gaz jones

unread,
Apr 26, 2011, 9:25:57 AM4/26/11
to clo...@googlegroups.com
this looks awesome, tried it out on a project i have but sadly got the
exception below. i'll try and figure it out later when i have more
time to see if its something specific to my project, but thought i
would let you know in case it is something obvious (it failed from
both slime and lein)

Exception in thread "main" java.lang.Exception: prefix cannot be nil
(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:5440)
at clojure.lang.Compiler.eval(Compiler.java:5415)
at clojure.lang.Compiler.eval(Compiler.java:5391)
at clojure.core$eval.invoke(core.clj:2382)
at slam.hound.regrow$check_for_failure.invoke(regrow.clj:31)
at slam.hound.regrow$regrow.invoke(regrow.clj:72)
at slam.hound.regrow$regrow.invoke(regrow.clj:70)
at slam.hound$reconstruct.invoke(hound.clj:10)
at user$eval368.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:5424)
at clojure.lang.Compiler.eval(Compiler.java:5415)
at clojure.lang.Compiler.eval(Compiler.java:5415)
at clojure.lang.Compiler.eval(Compiler.java:5391)
at clojure.core$eval.invoke(core.clj:2382)
at clojure.main$eval_opt.invoke(main.clj:235)
at clojure.main$initialize.invoke(main.clj:254)
at clojure.main$null_opt.invoke(main.clj:279)
at clojure.main$main.doInvoke(main.clj:354)
at clojure.lang.RestFn.invoke(RestFn.java:422)
at clojure.lang.Var.invoke(Var.java:369)
at clojure.lang.AFn.applyToHelper(AFn.java:165)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)
Caused by: java.lang.Exception: prefix cannot be nil
at clojure.core$load_libs.doInvoke(core.clj:4802)
at clojure.lang.RestFn.applyTo(RestFn.java:138)
at clojure.core$apply.invoke(core.clj:544)
at clojure.core$use.doInvoke(core.clj:4880)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clj_lbm.core$eval386$loading__4410__auto____387.invoke(NO_SOURCE_FILE:1)
at clj_lbm.core$eval386.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:5424)
... 22 more

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Phil Hagelberg

unread,
Apr 26, 2011, 12:11:26 PM4/26/11
to Clojure
On Apr 26, 6:25 am, gaz jones <gareth.e.jo...@gmail.com> wrote:
> this looks awesome, tried it out on a project i have but sadly got the
> exception below. i'll try and figure it out later when i have more
> time to see if its something specific to my project, but thought i
> would let you know in case it is something obvious (it failed from
> both slime and lein)

It hasn't seen a lot of use yet, so there are going to be things it
doesn't handle. There are a some cases it doesn't work with by design,
and I've clarified that in the readme:

https://github.com/technomancy/slamhound/commit/c9dd2403393c086175be58c0bafc459eeff3e20b

If you run into other issues, please open a Github issue with a repro
case.

thanks,
Phil

Aaron Bedra

unread,
Apr 26, 2011, 1:01:24 PM4/26/11
to clo...@googlegroups.com
I love you Phil.


--
Cheers,

Aaron Bedra
--
Clojure/core
http://clojure.com

Phil Hagelberg

unread,
Apr 26, 2011, 2:32:42 PM4/26/11
to Clojure
On Apr 26, 6:25 am, gaz jones <gareth.e.jo...@gmail.com> wrote:
> this looks awesome, tried it out on a project i have but sadly got the
> exception below. i'll try and figure it out later when i have more
> time to see if its something specific to my project, but thought i
> would let you know in case it is something obvious (it failed from
> both slime and lein)

I just pushed 1.1.0 which should solve most issues causing this; if
not please let me know.

-Phil

James Reeves

unread,
Apr 26, 2011, 3:58:31 PM4/26/11
to clo...@googlegroups.com
1.1.0 seems to have regressed. I've added slamhound as a dependency:

(defproject foobar "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.2.1"]]
  :dev-dependencies [[slamhound "1.1.0"]])

Then added a function to "src/foobar/core.clj":

(ns foobar.core)
(str/trim " hello ")

When I start a REPL and try to slamhound it, it instead throws an exception:

user=> (require 'slam.hound)
nil
user=> (slam.hound/reconstruct "src/foobar/core.clj")
java.lang.Exception: No such namespace: str (core.clj:2)

And the same occurs with the Leiningen plugin:

$ lein slamhound src/foobar/core.clj 
Exception in thread "main" java.lang.Exception: No such namespace: str (core.clj:2)
...

- James


-Phil

.Bill Smith

unread,
Apr 26, 2011, 4:03:11 PM4/26/11
to clo...@googlegroups.com
That's a great idea, Phil.  Thanks for contributing!

Phil Hagelberg

unread,
Apr 26, 2011, 5:16:11 PM4/26/11
to Clojure
On Apr 26, 12:58 pm, James Reeves <jree...@weavejester.com> wrote:
> When I start a REPL and try to slamhound it, it instead throws an exception:
>
> user=> (require 'slam.hound)
> nil
> user=> (slam.hound/reconstruct "src/foobar/core.clj")
> java.lang.Exception: No such namespace: str (core.clj:2)

That's by design; it only works when the :as alias is the same as the
last segment of the namespace name.

However, there was an unrelated bug causing issues when uncompilable
namespaces were on the classpath. I'll have a 1.1.1 fix pushed in a
few minutes.

-Phil

James Reeves

unread,
Apr 26, 2011, 5:56:21 PM4/26/11
to clo...@googlegroups.com
On 26 April 2011 22:16, Phil Hagelberg <ph...@hagelb.org> wrote:
>
> On Apr 26, 12:58 pm, James Reeves <jree...@weavejester.com> wrote:
> > When I start a REPL and try to slamhound it, it instead throws an exception:
> >
> > user=> (require 'slam.hound)
> > nil
> > user=> (slam.hound/reconstruct "src/foobar/core.clj")
> > java.lang.Exception: No such namespace: str (core.clj:2)
>
> That's by design; it only works when the :as alias is the same as the
> last segment of the namespace name.

Ah, well even if I use "string/trim" it throws the same error:

user=> (require 'slam.hound)
nil
user=> (slam.hound/reconstruct "src/foobar/core.clj")

java.lang.Exception: No such namespace: string (core.clj:2)

> However, there was an unrelated bug causing issues when uncompilable
> namespaces were on the classpath. I'll have a 1.1.1 fix pushed in a
> few minutes.

Is clojure.string an uncompilable namespace, then?

- James

Phil Hagelberg

unread,
Apr 26, 2011, 6:49:07 PM4/26/11
to Clojure
On Apr 26, 2:56 pm, James Reeves <jree...@weavejester.com> wrote:
> On 26 April 2011 22:16, Phil Hagelberg <p...@hagelb.org> wrote:
> > That's by design; it only works when the :as alias is the same as the
> > last segment of the namespace name.
>
> Ah, well even if I use "string/trim" it throws the same error:

Right; this should be fixed in 1.1.1.

> user=> (require 'slam.hound)
> nil
> user=> (slam.hound/reconstruct "src/foobar/core.clj")
> java.lang.Exception: No such namespace: string (core.clj:2)
>
> > However, there was an unrelated bug causing issues when uncompilable
> > namespaces were on the classpath. I'll have a 1.1.1 fix pushed in a
> > few minutes.
>
> Is clojure.string an uncompilable namespace, then?

No, it was that foo.bar was uncompilable, and it was looking there for
candidates. But no longer!

There are still a issues with running it in a few places in our
codebase, but they mostly revolve around needing a smarter
disambiguator. I don't have any clear plan for this; it needs hammock
time. Part of it is to allow composable disambiguators and look for
them in project.clj, but that's probably not the whole solution.

-Phil

James Reeves

unread,
Apr 26, 2011, 8:06:00 PM4/26/11
to clo...@googlegroups.com
On 26 April 2011 23:49, Phil Hagelberg <ph...@hagelb.org> wrote:
> On Apr 26, 2:56 pm, James Reeves <jree...@weavejester.com> wrote:
>> On 26 April 2011 22:16, Phil Hagelberg <p...@hagelb.org> wrote:
>> > However, there was an unrelated bug causing issues when uncompilable
>> > namespaces were on the classpath. I'll have a 1.1.1 fix pushed in a
>> > few minutes.
>>
>> Is clojure.string an uncompilable namespace, then?
>
> No, it was that foo.bar was uncompilable, and it was looking there for
> candidates. But no longer!

Ohh! I see what you were saying now.

Thanks for the fix!

- James

Reply all
Reply to author
Forward
0 new messages