How to nest require in Clojure? - clojure

Suppose I have a namespace parent.namespace, which has two children child1.namespace and child2.namespace, i.e., both require parent.namespace. Both child1.namespace and child2.namespace require some package (:require [some.package :refer [stuff]]). Is there a way to require this package only once in the parent.namespace and then require only parent.namespace in both children without having to require some.package in each child separately?

No, there is no nesting or inheritance behavior like you are suggesting. Each child namespace must look like so:
(ns child1.namespace
(:require
[parent.namespace :as parent]
[some.package :refer [stuff]))

Related

What is the difference between core.clj and inope.clj in a clojure project?

What is the difference between core & inope?
I have a very brief idea that core is like the main equivalent in Java. And inope is like an interface between java and clojure, although I dont understand the purpose of inope entirely.
I found this in a project and this is my understanding:
inope.clj is used for writing java clojure interoperable functions.
The namespace contents imply that it functions like core.clj here.
in this inope.clj file, they have imported dependencies and defined java-clojure interoperable functions in gen-class as such :
(ns prject-avon.inope
(:require [prject-avon.ioutil :as utl]
[aero.core :as aero-core :refer (read-config)]
[clojure.java.data :as clj-data]
[malli.core :as m]
[malli.util :as mu]
[malli.instrument :as mi]
[malli.error :as me]
[malli.json-schema :as json-schema]
(:gen-class
:methods [ ^{:static true} [validateData [Object String] Boolean]
]))
<Functions are defined here>
Those are just names, there's no significance to them. In particular, I've never heard of inope myself. The only way you can reliably judge is by the namespace's contents and their usage. It's also very possible that a single namespace contains all sorts of unrelated stuff.

Why do I get IllegalAccessError when trying to import a protocol or record from another namespace

I have a file in my project where I define a few protocols and records (defprotocol and defrecord).
I'm trying to use them in a different file/namespace like this:
(ns myapp.core
(:require [myapp.protocols :refer [SomeProtocol]]))
This causes an Execution error (IllegalAccessError) at .... Does anyone know why?
btw, doing :refer :all does work but I don't want to bring in several unneeded symbols into the namespace.
thanks

How to require dependencies in Clojure?

I have two questions regarding dependencies in Clojure project.
Is there something like :dev-dependencies or :test-dependencies so that I don't have to download them all on lein run? So until I run my tests I don't need to have these extra libraries.
Can I load dependencies in one file and require this one file in an another file? I'd like to have something similar to:
; dependencies.clj
; ...
(:require [clj-http.client :as client]
[clj-http.fake :refer :all]
[clojure.test :refer :all]))
; some-file.clj
; ...
(:require [dependencies :refer :all[)
1) Yes, Leiningen offers profiles for just these purposes
2) No, referals from one namespace are not "inherited" between namespaces. You can't express "I want to refer to everything in this namespace, that some other namespace refers"
Regarding your point 2, Potemkin can help you do this. Potemkin is especially useful if you have several namespaces implementing the functionality of a library, but then want to present a single namespace to users of the library.

In Clojure 1.4 what is the use of refer within require?

What advantage does using :refer in :require have over using :only in :use? Are the following synonymous?
(ns so.example (:use [my.lib :only [function]]))
and
(ns so.example (:require [my.lib :refer [function]]))
Main idea of adding :refer to :require is to get rid completely of :use, leaving only one operator to load other packages. You can emulate existing :use with (:require [my.lib :refer :all])...
yes, they are equivalent,
:refer and :require are the basic operations required to build namespaces. :use is more convienient
:require causes classes to be loaded
:refer adds things to the name space which is really just a map (actually a couple of maps)
:use is :refer + :require
as much is it may look like it, there really is no magic to namespaces
if you make a namespace like this
(ns so.example (:use my.lib))
the equivalent with :require would be:
(ns so.example (:require [my.lib :refer [function1 function2 function3
list every function in example
here and remember to keep it
up to date ]]))
As of the 1.4.0 release, there's no longer a good reason to use use. Use require :refer instead. From the Clojure 1.4.0 changelog: "require can now take a :refer option. :refer takes a list of symbols to refer from the namespace or :all to bring in all public vars."
(from https://8thlight.com/blog/colin-jones/2010/12/05/clojure-libs-and-namespaces-require-use-import-and-ns.html)

What's idiomatic clojure for :use

I've seen several different ways for :use in clojure--what's the idiomatic/preferred method?
#1
(ns namespace.core
(:use [[something.core]
[another.core]]))
or #2 EDIT: Use this with conjunction with :only.
(ns namespace.core
(:use [something.core]
[another.core]))
or #3
(ns namespace.core
(:use [something.core
another.core]))
or #4
(ns namespace.core
(:use (something.core
another.core)))
or #5 EDIT: This is idiomatic, but one should be using :use as in #2
(ns namespace.core
(:use something.core
another.core))
Choice #5 is idiomatic, unless you are passing additional options such as :only, :exclude, etc. Colin's blog post covers the options in great detail.
The API for dealing with namespaces is unnecessarily difficult to learn. However, it is certainly capable enough for a wide variety of uses, so the pressure for a rewrite has yet to reach the boiling point for anyone.
Actually none of them are idiomatic. You should always have an :only clause in your :uses. Your best bet is adding :only to #2. If you don't want to enumerate all the vars you're taking from another namespace, consider (:require [foo.bar :as bar]).
One point of note that we should mention is that the
(:use (clojure set xml)) statement is considered a promiscuous operation
and therefore discouraged. [...] When organizing your
code along namespaces, it’s good practice to export and import only those
elements needed.
-from the Joy of Clojure, page 183.
The one exception is that a test namespace should bare-use the namespace it tests.
The cases 1, 3 and 4 are not valid and throw some Exception. I haven't seen 2 - only in combination with :only or the like.
(ns namespace.core
(:use
[something.core :only (x)]
another.core))
I usually use 5.
In Clojure 1.4+ I wouldn't use use at all. require can do all that use can do now, so forget about use. One less thing to worry about.
If you want use-like behaviour (still bad form, imo) you can do:
(ns namespace.core
(:require
[something.core :refer :all]
[another.core :refer :all]))
If you want :use .. :only behaviour, use:
(ns namespace.core
(:require
[something.core :refer [foo bar]]
[another.core :refer [quux]]))
More detail: In Clojure 1.4 what is the use of refer within require?