leiningen

N.B. The maintainers are on #leiningen on Libera chat IRC. Go there for direct support/bug reports.
Jim Newton 2020-06-08T15:43:51.217700Z

Hi everyone, is there a way to tell lein which order to load the files in? especially in the case that the load order cannot be determined by name space requirements?

Jim Newton 2020-06-08T16:01:26.218900Z

The only way I can think of doing it is to create empty name spaces, one per file which needs to be loaded. And then :require those name spaces in the order which I know they need to be loaded. This seems to work, but sounds like a hack.

2020-06-08T16:47:56.219700Z

@jimka.issy what do you mean by “load files in”?

2020-06-08T16:47:59.219900Z

as in compile them?

2020-06-08T16:48:08.220300Z

like via :aot option?

Jim Newton 2020-06-08T18:45:34.222300Z

@mikerod, if you have several files in the directory, it seems the project.clj file indicates in the defproject which is the first file to load via the :main keyword. And thereafter if any file defines a ns which requires other packages to be loaded, they seem to be loaded by assuming the name of the file matches the ns name.

Jim Newton 2020-06-08T18:45:44.222600Z

what about other files which don't match the ns name?

Jim Newton 2020-06-08T18:45:58.223Z

how am I supposed to force them to be loaded?

Jim Newton 2020-06-08T18:46:36.223600Z

as per the compilation, as I understand it load semantics and are the same whether loading from source and compiling on the fly, or loading from pre-compiled files. right?

Jim Newton 2020-06-08T18:47:31.224200Z

an example would be a file which does not begin with (ns ...) but rather begins with (in-ns ...)

Jim Newton 2020-06-09T15:41:13.233500Z

The problem is that lein assumes ns name is derivable from file name. This is an unfortunate assumption which was not intended by clojure's design, otherwise in-ns would not exist. In my opinion this is a bug in lein, in that it is requiring the user to provide redunant information.

Jim Newton 2020-06-09T16:14:07.233700Z

bug is a strong work. I understand the heritage comes from java, so we're not starting from a perfect world by any means.

2020-06-09T19:34:43.234500Z

I don't think there is actually a requirement in Leiningen for every source file to start with an ns form with a name that corresponds to the file name. Clojure require given a namespace name will always look for it in a file with a corresponding file name, but I doubt Leiningen imposes any more requirements than that.

2020-06-09T19:50:23.234700Z

Here is a tiny demo Leiningen project demonstrating that one can have files that contain no ns form at the beginning, that can be loaded via a call to load from a different source file in the same project: https://github.com/jafingerhut/loaddemo

2020-06-09T19:52:24.235Z

I have heard Stuart Halloway make a comment noting that while require has this namespace<->filename correspondence built into it, you can concatenate the contents of most (all?) multi-file Clojure projects in a valid order where things are defined before they are used, and just concatenate those all into one big file, or copy and paste that all into a REPL session, and the issue of file names, and even of files in the file system, never arises, and things can work that way.

2020-06-09T19:52:34.235200Z

Most people don't create Clojure code bases that way, of course.

2020-06-09T19:53:29.235400Z

I suspect that the creation of in-ns was motivated more by live REPL development, and the desire to switch from one namespace to another in a live REPL session, more than anything else.

Jim Newton 2020-06-08T18:52:59.224600Z

Can someone help me find the documentation for defproject ?

Jim Newton 2020-06-08T18:53:18.224900Z

i.e., what are all the possible options and their meanings?

2020-06-08T18:58:40.225900Z

One source is a huge sample project.clj file included with Leiningen that has many comments. Not necessarily full documentation, but at least mentions most possible things: https://gitlab.com/technomancy/leiningen/blob/master/sample.project.clj

1✔️
2020-06-08T18:59:52.226700Z

As in, the file beginning with (in-ns ...) is code that belongs in a namespace whose (ns ..) form is in another file?

2020-06-08T19:01:24.226900Z

If yes, then I have seen such files loaded from the file containing the (ns ...) form in clojure.core's namespace, like this:

(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")

Jim Newton 2020-06-08T19:34:20.227200Z

what's the path name relative to?

Jim Newton 2020-06-08T19:35:16.227400Z

re your question above. yes. several files which contribute to the same ns.

Jim Newton 2020-06-08T19:36:57.227600Z

The way I've figured out how to do it is just define a bunch of empty name spaces, one per file, And the top of the files look like the following

(ns clojure-rte.type-extend
  "This is an empty namespace to fool lein to load this file as part of
  the clojure-rte.core ns.")

(in-ns 'clojure-rte.core)

Jim Newton 2020-06-08T19:38:18.227800Z

I wonder whether it is better to call load directly. My guess is that calling load directly will confuse lein when trying to print error messages if a problem happens at load time. Just my but feel though.

alexmiller 2020-06-08T20:48:39.228200Z

lein sample

11✔️
2020-06-08T21:22:25.228300Z

If you want to avoid the question, you can simply put all code that you want to belong in one namespace in one file, with a name corresponding to the namespace name. The upper limit on the size of one is quite large (not sure what exactly determines it).

2020-06-08T21:22:46.228500Z

Using load like used in the clojure.core namespace you can split the contents of a single namespace across multiple files.

2020-06-08T21:23:27.228700Z

The load calls in any namespace foo.bar should execute whenever ns foo.bar is require'd, or loaded in any way, I believe.

2020-06-08T22:27:01.228900Z

I would expect it would be confusing to many readers of code to have an ns form at the beginning of a file, which corresponded to the file name, but then soon afterwards have (in-ns ..)` with a different namespace name, and none of the code was actually in the namespace named in the ns form. Obviously Clojure allows you to do this -- just saying it would look odd to me.