Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use vs require #1

Open
Raynes opened this issue Oct 2, 2013 · 4 comments
Open

use vs require #1

Raynes opened this issue Oct 2, 2013 · 4 comments

Comments

@Raynes
Copy link

Raynes commented Oct 2, 2013

Howdy. Just wanted to suggest not promoting the use of :use.

As of Clojure 1.4, require serves both its original purpose and the purpose of use via the :refer modifier. For example

(ns foo.bar.baz
  (:require [plumbing.core :refer :all]))

If compatibility with pre-1.4 is not a requirement, this is generally a better way to go. It makes ns declarations far more consistent and uniform, and also means there is less code using use if it gets deprecated at some point in the future (which would not be entirely unsurprising).

My suggestion would be to replace the use uses (no pun intended) with require, but add a note about use for the unlikely event that the reader requires < 1.4 compatibility.

As a secondary thing, it isn't really great to promote these unqualified imports. In tests and such it is generally fine, but in actual code you almost always want to qualify things for readability and clarity. It seems to be trying to say this, but it doesn't feel clear enough. I'd be more aggressive in saying that it's almost always a bad idea to do unqualified imports. I don't know what plumbing.core is and whether or not it is a good example of an exception though.

Cheers!

@bitemyapp
Copy link

+1

I don't know how closely you guys follow the mailing list, but avoiding the use of use could mean better future-proofing of code as there has been rumbling about the non-orthogonality of use and this being justification for future removal.

@ianconsolata
Copy link
Contributor

Agreed. But if you take a look at the file at https://github.com/Prismatic/plumbing/blob/master/src/plumbing/core.clj, you'll see that it's full of things like map-vals, dissoc-in, and safe-get. We use many of these functions just as often as functions from clojure.core, so we (internally) advocate the use of plumbing.core. We definitely don't advocate doing that with other files.

As for use versus refer, can you explain why it's the better way to go? We value the explicitness of a header with use; it looks different, which makes it much easier to see why certain functions aren't namespace qualified. And changing it to prepare for the fact that use might eventually be deprecated seems premature to me, especially when it breaks compatibility with earlier versions of clojure that are still in use.

@Raynes
Copy link
Author

Raynes commented Oct 2, 2013

I don't think pre-1.4 is in use nearly enough at this point for it to really matter, but regardless, that's why I suggested adding a note about it if it is a concern.

Not having to fix all this code when use gets deprecated (assuming it does, but once again I'd be very surprised it if it never does) is a benefit, but the more important benefit is the the uniformity of having one thing for importing code instead of several. I think (and as far as I can tell, most people think) that what you lose in 'explicitness' is far less than what you gain by removing the overhead of several things all doing very similar things. This has been a confusing pain-point for new Clojure developers and was in fact so bad that they added :refer to require so that we could have uniformity.

In any case, these are merely polite suggestions. You guys are certainly entitled to your own engineering best practices (everybody has some!), but since this is a public thing now I just wanted to provide some counterpoints!

Cheers!

@bitemyapp
Copy link

I would also take the opportunity to mention that if you have a large number of nouns/verbs in a single namespace for some kind of DSL, :as is a good choice for making the namespacing of your operations explicit whereas :refer is better when you've got a limited bag of functions/macros you're using.

I would be quite unhappy if I was looking at code that had dissoc-in but didn't have a namespace prefix in front of it to warn me I wasn't looking at clojure.core. Code that forces you to exclude multiple things from clojure.core is not generally speaking well designed code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants