ns usage for multiple clj files

177 views
Skip to first unread message

Parth Malwankar

unread,
Sep 7, 2008, 3:03:35 AM9/7/08
to Clojure
Hello,

I am trying to use the latest ns/in-ns functionality
from HEAD. I don't seem to be getting it right.

Here is what I am tring to do.
1. test.clj - contains a function foo
2. tst-pkg.clj - contains the ns definition (so I can
get my dependencies right in a multi-file
project). I am assuming all loads for
'ns' happen sequentially.

I put these in $HOME/code/mycode.
I create a directory $HOME/.clj/user and softlink
$HOME/code/mycode into this. $HOME/.clj/user is in the
classpath.

Contents of the files below:

--- test.clj start ---
(in-ns 'bar)
(clojure/defn foo [] :foo-called)

--- test.clj end ---

--- tst-pkg.clj start ---
(ns bar
(:refer-clojure)
(:load-resources "mycode/test.clj"))
--- tst-pkg.clj end ---

If I load-resources test.clj directly it works.

user=> (load-resources "mycode/test.clj")
nil
user=> (bar/foo)
:foo-called
user=>

However, when I try to either load-file or load-resources
tst-pkg.clj I get errors.

[parth:~/code/mycode]% clj
Clojure
user=> (load-resources "mycode/tst-pkg.clj")
java.io.FileNotFoundException: Could not locate Clojure resource
on classpath: bar/mycode/test.clj
java.io.FileNotFoundException: Could not locate Clojure resource
on classpath: bar/mycode/test.clj
at clojure.lang.RT.loadResourceScript(RT.java:365)
at clojure.lang.RT.loadResourceScript(RT.java:347)
at clojure.lang.RT.loadResourceScript(RT.java:339)
at clojure.load_resources__1744.doInvoke(boot.clj:3209)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at user.eval__2286.invoke(tst-pkg.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:3850)
at clojure.lang.Compiler.load(Compiler.java:4151)
at clojure.lang.RT.loadResourceScript(RT.java:360)
at clojure.lang.RT.loadResourceScript(RT.java:347)
at clojure.lang.RT.loadResourceScript(RT.java:339)
at clojure.load_resources__1744.doInvoke(boot.clj:3209)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at user.eval__2283.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3850)
at clojure.lang.Repl.main(Repl.java:75)
user=> (load-file "/home/parth/code/mycode/tst-pkg.clj")
java.io.FileNotFoundException: Could not locate Clojure resource
on classpath: bar/mycode/test.clj
java.io.FileNotFoundException: Could not locate Clojure resource
on classpath: bar/mycode/test.clj
at clojure.lang.RT.loadResourceScript(RT.java:365)
at clojure.lang.RT.loadResourceScript(RT.java:347)
at clojure.lang.RT.loadResourceScript(RT.java:339)
at clojure.load_resources__1744.doInvoke(boot.clj:3209)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at user.eval__2292.invoke(tst-pkg.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:3850)
at clojure.lang.Compiler.load(Compiler.java:4151)
at clojure.lang.Compiler.loadFile(Compiler.java:4118)
at clojure.lang.RT$3.invoke(RT.java:289)
at user.eval__2289.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3850)
at clojure.lang.Repl.main(Repl.java:75)
user=>

What am I doing wrong here? Thanks.

Parth

Meikel Brandmeyer

unread,
Sep 7, 2008, 4:00:11 AM9/7/08
to clo...@googlegroups.com
Hi,

Disclaimer: The following is not tested. It is just from what I saw from
your description and what caught my attention.

There are special naming rules for the file in a namespace. The first
thing to do is to fix the naming. I would use the following layout.

(Note: I would drop the symlinking for the moment, take make things
easier to spot. Just put the files somewhere in the classpath.)

bar/bar.clj:
> (ns bar
> (:refer-clojure)
> (:load-resources "foo.clj"))
Note: I renamed tst-pkg.clj to bar.clj and put it in a subdirectory,
since this is the place, where use and require look for the file.

(require 'bar) -> file: bar/bar.clj.

Also note: I removed the mycode subdirectory from the load-resources,
since load-resources looks in the namespace-directory for relative
pathnames.

bar/foo.clj:
> (in-ns 'bar)
> (defn foo
> []
> :foo-called)
Just the foo function. Note: I don't use clojure/defn. bar.clj refers to
clojure and this should be the starting point, when using the lib. Later
one can reload foo.clj w/o problems, eg. for debugging or during
development. But the initial load has to be done via bar.clj, cause here
are the dependencies defined!

Now we are ready to use it:
> (require 'bar)
> (bar/foo)

I think your problems should be solved now, since in my understanding
they arise due to the non-adherence to the required file layout.


> java.io.FileNotFoundException: Could not locate Clojure resource
> on classpath: bar/mycode/test.clj

^^^
load-resources works namespace directory relative for relative
pathnames!

So, should the above work, it's time to bring in the symlinking again.
And you should check, whether it still works. If not, there is some
issue with finding files in symlinked classpaths. But to be honest I
don't think so. I also use a symlinked classpath for local projects of
mine and never had any problems.

Hope this helps.

Sincerely
Meikel

Parth Malwankar

unread,
Sep 8, 2008, 1:20:21 AM9/8/08
to Clojure


On Sep 7, 1:00 pm, Meikel Brandmeyer <m...@kotka.de> wrote:
> I think your problems should be solved now, since in my understanding
> they arise due to the non-adherence to the required file layout.> java.io.FileNotFoundException: Could not locate Clojure resource
> > on classpath: bar/mycode/test.clj
>
>                  ^^^
> load-resources works namespace directory relative for relative  
> pathnames!
>

Thanks for the pointers Meikel.
I was finally able to get it to work.
I had missed one of the points in the docs for load-resources:

"A path is interpreted as classpath-relative if it begins with
a slash or relative to the root directory for the current
namespace otherwise"

Apart from trying the bar namespace approach mentioned
I also cleaned up my 'mycode' example.
I added a symlink to mycode in ~/.clj which I added to the classpath.
And updated the code below which works.

--- test.clj start ----
(in-ns 'mycode)
(defn foo [] :foo-called)
--- test.clj end ---

--- mycode.clj start ---
(ns mycode
(:refer-clojure)
(:load-resources "test.clj"))
--- mycode.clj end ---

--- interaction start ----
user=> (load-resources "/mycode/mycode.clj")
nil
user=> (mycode/foo)
:foo-called
user=>
--- interaction end ----

Parth

>  smime.p7s
> 5KViewDownload
Reply all
Reply to author
Forward
0 new messages