Merged ns require aliases like PureScript / Potemkin

I scouted PureScript today.

They have an interesting operation when requiring namespaces (importing modules) called “Merging Modules” that allows referring to names from multiple namespaces under a common alias within the requiring ns. They encourage using by explicitly listing the names you wish included, amounting to select-keys on each of the ns maps, followed by a merge under the local alias.

Clojure’s ns macro is likely frozen (which brings me great inner peace), but it’s still fun to consider the design as a thought experiment.

I believe it’s a similar thrust to what @ztellman did with import-vars in Potemkin, allowing the organization of names for the implementor independence from organization for the library consumer. One reason I don’t use that lib more often is I don’t think it works across CLJC targets (particularly CLJS). No idea whether it could be made to work or whether there’s a deeper limitation.

Regardless, from time to time I definitely want this ability in my own projects, both for well-known “suites” of libraries (eg Ring, as Zach mentions), and for some of my own.

Anyone else relate? If supported at the language level and across CLJC targets, would you use it?

5 Likes

I also think that would be a nice feature.

Hum… I’m not sure about the PureScript merging feature. That seems to just allow you to alias to the same alias multiple requires. I am not in favour of that. The ability to easily read where exactly a var is from is something I really enjoy and would like to keep.

The Potemkin import-vars on the other hand I’m more supportive of. It lets you inline vars from other namespaces as if they’d be defined in yours. So when someone else requires your namespace they get all of the imported vars under it.

Right now I think it does so by grabbing what the imported var contains and defing it to a var of the same name in the current namespace. And then it sets a watch on the var for any change, and on change, it updates the local var accordingly.

So I don’t think this works in Cljs because Cljs doesn’t have Vars. So I’d assume it doesn’t have watches.

Though the watch feature is only useful for updates, which I don’t think is very common to do.

So in CLJC projects you could try just:

(ns com.my.lib
  (:require [come.my.wtv :as wtv]))

(def foo wtv/foo)
(def bar wtv/bar)
...

I think this would cover a lot of use cases already.