Fork me on GitHub
#leiningen
<
2020-06-08
>
jimka.issy15:06:51

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?

jimka.issy16:06:26

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.

mikerod16:06:56

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

mikerod16:06:59

as in compile them?

mikerod16:06:08

like via :aot option?

jimka.issy18:06:34

@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.

jimka.issy18:06:44

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

jimka.issy18:06:58

how am I supposed to force them to be loaded?

jimka.issy18:06:36

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?

jimka.issy18:06:31

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

jimka.issy18:06:31

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

andy.fingerhut18:06:52

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

andy.fingerhut19:06:24

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")

jimka.issy19:06:20

what's the path name relative to?

jimka.issy19:06:16

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

jimka.issy19:06:57

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)

jimka.issy19:06:18

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.

andy.fingerhut21:06:25

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).

andy.fingerhut21:06:46

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

andy.fingerhut21:06:27

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

andy.fingerhut22:06:01

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.

jimka.issy15:06:13

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.

jimka.issy16:06:07

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

andy.fingerhut19:06:43

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.

andy.fingerhut19:06:23

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

andy.fingerhut19:06:24

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.

andy.fingerhut19:06:34

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

andy.fingerhut19:06:29

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.

jimka.issy18:06:59

Can someone help me find the documentation for defproject ?

jimka.issy18:06:18

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

andy.fingerhut18:06:40

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