Enumerate namespaces and dynamically load them in ClojureScript

感情迁移 提交于 2019-12-21 18:02:42

问题


This may actually be a bit of an XY-problem, so I'll try to explain what the goal is first.

I'm building a ClojureScript application which is composed of a set of Reagent components. It provides a user interface where you can dynamically add or remove UI elements. These UI elements (components) have a certain type. For example a Markdown component is-a Text component. Whenever the user is presented with the option to add Text we list all the components that match the type+descendants (in this case Markdown, there could be others).

The way I've coded it up is as follows. Each component is in its own namespace, this namespace contains a builder function that returns the new component. At the root of the namespace it also calls (derive ::type ::parent)

now in some different namespace we require and enumerate all of these components in a map like:

(ns app.components
  (:require
   [app.gui.markdown :as markdown]
   [app.gui.study-list :as study-list]))

(def all
  {markdown/t markdown/builder
   study-list/t study-list/builder})

Where the /t refers to the namespace-qualified keyword which was used to define the hierarchy. We use the all map to provide the data for the menu's that face the user (which components can be added, filtered by type).

Now, as you can imagine, this isn't pretty. Since it must now maintain such a (potentially) long list of all the types in the hierarchy manually.

Rather I would do something like (def all (components-of (descendants ::root))) but I'm unsure how to tackle this, since I think it would require finding vars by name (not supported in ClojureScript).

So my question is: how do you maintain a map or list of namespaces + vars (dynamically) in ClojureScript?


回答1:


You cannot do this dynamically, but as far as I can tell for your problem there isn't much need. ClojureScript macros can reflect back into the compiler - you could easily use the cljs.analyzer.api namespace to figure out which vars you need (through var metadata or whatever) and automatically emit the runtime info map you want. This is in fact very similar to how cljs.test/run-tests works. It uses the compiler to filter out all vars in all namespaces with :test metadata attached and it generates the code to test each one. It's worth examining cljs.test in detail to see how this can be done.



来源:https://stackoverflow.com/questions/30081260/enumerate-namespaces-and-dynamically-load-them-in-clojurescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!