clojure-style-guide icon indicating copy to clipboard operation
clojure-style-guide copied to clipboard

Suggest ok to seemingly mask/shadow built-ins

Open MicahElliott opened this issue 5 years ago • 3 comments

Follow Idiomatic require aliases

The most common way to require string is: [clojure.string :as str]. This may appear to mask clojure.core.str, but it doesn't. It's expected that clojure.core/str and clojure.string/* to be used in a namespace as str and str/whatever without conflict.

;; good
(ns ... (:require [clojure.string :as str] ...)
(str ...
  (str/join ...

;; not as good - just be idiomatic and use as `str/`
(ns ... (:require [clojure.string :as string] ...)
(str ...
  (string/join ...

The same applies to clojure.set :as set and the built-in set.

Across a project, it's good to be consistent with namespace aliases; e.g., don't require string as str in one NS but string in another.

MicahElliott avatar Feb 06 '20 01:02 MicahElliott

Hej,

I don't think that this is a common way how to do it. I see usage of string, str and s in projects. Also it violates

As a general first rule, make the alias the same as the namespace name with the leading parts removed.

from https://stuartsierra.com/2015/05/10/clojure-namespace-aliases

LukasRychtecky avatar Feb 06 '20 08:02 LukasRychtecky

It might be worth some analysis across several code bases. The bigger point I guess I want to make (beyond in-project consistency) is that it'd be nice to standardize the community on some as much as possible.

E.g., in my Emacs config for clj-refactor, I've enjoyed the consistency and auto-requiring of this:

 '(cljr-magic-require-namespaces
   (quote
    (("io" . "clojure.java.io")
     ("set" . "clojure.set")
     ("str" . "clojure.string")
     ("walk" . "clojure.walk")
     ("zip" . "clojure.zip")
     ("json" . "cheshire.core")
     ("xml" . "clojure.data.xml")
     ("as" . "clojure.core.async")
     ("mat" . "clojure.core.matrix")
     ("edn" . "clojure.edn")
     ("pp" . "clojure.pprint")
     ("spec" . "clojure.spec.alpha")
     ("csv" . "clojure.data.csv")
     ("time" . "java-time")
     ("spr" . "com.rpl.specter")
     ("http" . "clj-http.client")
     ("log" . "clojure.tools.logging")
     ("s3" . "amazonica.aws.s3")
     ("sql" . "hugsql.core")
     ("yaml" . "clj-yaml.core")
     ("sh" . "clojure.java.shell")
     ("w" . "clojure.walk")
     ("fs" . "me.raynes.fs")
     ("r" . "reagent.core")
     ("rf" . "re-frame.core"))))

Those are personal and probably too broad for adoption, but the idea is sound for the most common ones.

I don't care a lot whether the alias convention for clojure.string becomes string or str or s (though single chars are usually not great), just that could be one.

Here are aliases that get used a lot (includes str), given that everyone who uses clj-refactor likely ends up with them: https://github.com/clojure-emacs/clj-refactor.el/wiki#magic-requires

MicahElliott avatar Feb 06 '20 21:02 MicahElliott

E.g., in my Emacs config for clj-refactor, I've enjoyed the consistency and auto-requiring of this:

     ("walk" . "clojure.walk")
...
     ("w" . "clojure.walk")

Hmm.... ;)

I think the general rule (of the short name being the last component) is fine, but don't mind exceptions for a few commonly used namespaces (especially something like str for clojure.string -- though I work primarily in Joker, so it's for joker.string).

Thanks for the list and link though!

jcburley avatar Feb 06 '20 23:02 jcburley