Last active
January 8, 2020 19:42
-
-
Save telekid/0f276bfa3b3f0d395a7a71158adbb35d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Spec's global ns registry makes it challenging to declare multiple instances | |
;; of the same concept in the same ns. For example, say I want to define specs | |
;; for multiple continents in (ns models.geography.continent). Different continents | |
;; have different animal populations, so they require different animal counts: | |
(ns models.geography.continent | |
(:require [models.animals :as animals])) | |
;; First, we define a spec for Antarctica: | |
(defn antarctica [{:keys [::animals/penguins]}]) | |
(s/fdef antarctica | |
:args (s/cat :animals ::animals)) | |
(s/def ::animals (s/keys :req [::animals/penguins])) | |
;; Now, if we want to do the same for Africa, we're in a bit of trouble: | |
(defn africa [{:keys [::animals/lions]}]) | |
(s/def africa | |
:args (s/cat :animals ???)) | |
;; ^^^ | |
;; ::animals has already been defined. | |
;; One way to solve this problem is to put each continent in its own ns, e.g. | |
;; ˅ | |
(ns models.geography.continent.antarctica) | |
(s/def ::animals ...) | |
;; This works, but it feels pretty heavy-handed, especially when the fn implementations | |
;; share a lot of references. | |
;; A different approach would involve a language extension: | |
(ns models.geography.continent | |
(:require [models.animals :as animals])) | |
;; This would allow you to extend ns aliases inline: | |
;; ˅ | |
(s/def ::.africa/animals ...) | |
;; the above would expand to :models.geography.continent.africa/animals | |
;; For symmetry, it could also make sense to allow aliases to be extended this way: | |
::animals.penguin/weight | |
;; expands to :models.animals.penguin/weight | |
;; One downside of this language modification is that it promotes ad-hoc creation of | |
;; namespaces, which could theoretically become hard to reason about. | |
;; (The other obvious downside is... language modification.) | |
;; I'm curious how other people approach this problem? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment