Alias keywords without having to require the namespace


#1

@wilkerlucio just asked on #clojure slack channel

hello people, can you tell if we have any news around the issue of how to alias keywords without having to require the namespace? I really enjoy using long keywords all around with spec, but the verbosity sometimes get messy where it could be much shorter if I could have an alias. I know in Clojure land we can do a hack creating a namespace and calling (alias ... after, but in CLJS there is no such trick, for a while I have been thinking if it could go into the ns, really makes sense in my mind (I understand its already very bloated, but all the alias are there already), if we could do something like (:aliases [my.long.namespace.that.dont.exist :as using-it]). Can you tell me how you deal with this? Just keep the long ones that you require in full verbose?
I’ve been following this ticket, but it’s been a while since last update: https://dev.clojure.org/jira/browse/CLJ-2123


#2

I’m about to ask the same question as well :smile: Also, this should apply to not only keywords but also (quoted) symbols which are useful in remote server-client communication (such as om.next mutations syntax).

and the reason for not require-ing the namespace can be that the target namespace exists but it depends on current namespace hence require-ing it will result in cyclic dependency


#3

I’ve been holding of adding that to shadow-cljs because of the uncertain state of the CLJ ticket. I don’t want to add something that might end up being rejected or just different. Also would be annoying to only have this in CLJS but not CLJ.

I commonly have this problem when I have a “API” namespace and a separated .impl namespace. Since shadow.thing.impl cannot require shadow.thing (cyclic) I often end up having to use ::impl/some-kw inside the API namespace which is bad if keywords should actually be part of the API.

Having a dedicated empty namespace just for aliasing purposes sometimes works ok but feels very verbose. Although it is a good place to put specs.

This would only require a single line change in shadow-cljs however since it just abuses metadata on the ns so it is tempting to do.

(ns shadow.thing.impl
  {:reader/alias {api shadow.thing}}
  (:require ...))

::api/foo

Could even add {:reader/alias-self foo} to allow shadow.thing using the same aliases the impl would use. While ::foo is convenient it requires thinking about the current ns when reading code, having them look the same everywhere in the code might make that easier. Probably not a problem though.


#4

There’s a trick you can use in Clojure (not ClojureScript), with create-ns + alias

(create-ns 'long.namespace.name)
(alias 'x 'long.namespace.name)

::x/hello
;;=> :long.namespace.name/hello

Not saying I necessarily encourage you to do this, but might be good to know :sunglasses:


#5

Got the same problem here.
Solutions range from wacky namespace stuff to just a lot of typing.
+1 from me.


#6

This raises philosophical questions though, which is why does our code have circular structures in it? Is it possible to tree-shake the dependencies and get a clean structure?

Complecting factors are various keyword usages:

  1. Data which came out of a database (no symmetry with impl namespaces)
  2. data driven logic (questionable symmetry with impl namespaces)
  3. implementation flags or values passed as part of implementation (symmetric with impl namespaces and prone to circular refs)

… what other ways do we use keywords?