Apologies in advance for the somewhat discursive nature of this clump of related questions; I hope the answers will be a useful resource for newcomers to Clojure.
I have just begun to learn Clojure, motivated in part by this essay. I'm not a professional developer but I have several decades of programming experience (ARexx, VB/VBScript/VBA, then Perl and daily use of R starting in 2011). My platform is Windows 7 64-bit. I'm using Emacs 24.3, cider 20131221 and Leiningen 2.3.3 on Java 1.7.0_45 Java Hotspot 64-bit server. I have bought Clojure Programming and the Clojure Data Analysis Cookbook and dipped into both. I have found them promising but I am getting lost in the detail.
Obviously the thing to do is to get stuck in and experiment with code exercises and small tasks, but the immediate problem for me has been the complexity of structuring, organising and even just plain running projects in Clojure. With R I can get away with a file of plain text containing the bulk of the code, perhaps with one or two others containing common functions for larger projects.
Clojure is very different and with no experience in Java I am struggling to put the pieces together. Clojure Programming has a whole chapter on organising and building projects, but it is so comprehensive that conversely I'm finding it difficult to tease out the information relevant to me now. I guess I'm looking for something like this answer on Swank, but the tools seem to have moved on since then. So here goes.
project.clj
file that contains the project definition and dependencies. I think I get this. Can I use this file for code not related to the definition, below the defproject
, or is it best to leave this untouched and have the code itself in different clj
file(s)?project.clj
file alone, how is the relationship between that and other files established? Is it simply that all the clj
files in the project folder are counted part of the project?project.clj
and main.clj
with some helper functions in common.clj
- how are the relations between these three files defined? I can call functions from main.clj
but how does the project know that main is the core of the project if/when I package the project into an uberjar?clj
files, what is the best way to import functions? I have read about require
and use
(and import
and refer
and...) but I don't fully understand the difference and those two keywords are difficult to search for. The examples for REPL in the Clojure Data Analysis Cookbook most often opt for use
. I found a similar question but it was a little over my head.main.clj
example given above? Currently I just open the main.clj
file in Emacs, do an M-x cider-jack-in
to establish the REPL, experiment in the REPL, then when I want to try something I select the whole buffer and select Eval region
from the CIDER menu (C-c C-R
). Is this standard operating procedure or utterly misguided?clj
files and that ns
is used to define the namespace. Should I explicitly define the namespace (at the beginning of) every file of code? Clojure Programming has some recommendations but I'm interested in input from other users.com.my-project.foo
, the source code for that namespace should be in a file located at com/my_project/foo.clj
". (EDIT as explained in this useful answer and also this one). This restriction would never have occured to me. Are there any other gotchas with regard to naming namespaces and variables? R frequently uses dots in variable names but I guess given the Java connection that dots should generally be avoided?src
in the :source-path
. -main
function in project.core
, but you can specify various different configurations in the project.clj
. require
is preferred. :use
imports all publics of a namespace unless you use it in conjunction with :only
. Require let's you use an alias for an entire namespace with :as
, but you can have the same effect from use
with :only
using :refer
. Notice that in ClojureScript :use
without :only
is not even allowed.C-c C-k
to reload the entire file of the buffer. If you find yourself entering too many forms into a REPL and would rather edit them in a separate buffer https://www.refheap.com/22235.myproject.parse
, myproject.interpret
, over myproject.parser
, myproject.interpreter
etc. But that's a question of personal style. EDIT: Yes, explicitly define the naming of the namespace by its filename and the ns
form at the beginning of the source file. It is unusual to have multiple source-file defining one namespace.I like your "worried" approach. You will (hopefully) find out that Clojure and especially Leiningen are almost nonsense-free in terms of these questions.
Regarding REPL use: I saw your comment under @Mars answer that you want to use a REPL in a fashion that you can re-use what you are entering. Two things:
C-x C-.
from within the clj file to have the form at point pasted into the nrepl and be evaluated. Installation instructions are at the link (and your .emacs file usually resides in the home directory).@Igrapenthin's answers are great. Here are a few other thoughts.
On namespaces, this tutorial is great.
Just to clarify re #2: No, don't just put the .clj files anywhere under the project. They have to be under src/, or in whatever directories are listed (as strings) in the vector after :source-paths
in project.clj, if that entry exists. Then strip off that initial path when you're making your namespace names. This drove me crazy until I figured it out. (People who know better, please correct me if something here isn't right.)
One #3, you need Igraphenthin's answer, but why not just start by evaluating expressions in the REPL? I've been working on a project on and off for weeks, and it does a lot, but my -main
function still doesn't do anything. I just run whatever parts I'm working on. Well, you're used to languages with fully operational prompts--you decide.
EDIT: Whether or not you define the -main
function to do anything, you can also put :use
or :require
keywords in the ns
statement that defines the namespace for that same file. These will automatically get invoked when you start the REPL with lein repl
, and so whatever you have made available through the ns
keywords will be available at the REPL. That way, you have your previous work available, but you can play around with it in different ways in the REPL. (Also, if you don't like the default name for the file that's automatically loaded, you can redefine it in project.clj with :main
. Igraphenthin alluded to that.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With