枚举名称空间并在ClojureScript中动态加载它们 [英] Enumerate namespaces and dynamically load them in ClojureScript

查看:98
本文介绍了枚举名称空间并在ClojureScript中动态加载它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这实际上可能有点 XY问题,所以我将尽力解释首要目标是什么.

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

我正在构建一个ClojureScript应用程序,该应用程序由一组 Reagent 组件组成.它提供了一个用户界面,您可以在其中动态添加或删除UI元素.这些UI元素(组件)具有某种类型.例如Markdown组件is-a文本组件.每当向用户显示添加文本的选项时,我们都会列出与类型+ 后代匹配的所有组件. (在这种情况下,Markdown可能还有其他).

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).

我将其编码的方式如下. 每个组件都在其自己的名称空间中,该名称空间包含一个生成器函数,该函数返回新组件.在命名空间的根部,它还会调用(派生 :: type :: parent)

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})

/t指的是用于定义层次结构的名称空间限定关键字.我们使用all映射来提供面向用户的菜单数据(可以添加组件,并按类型过滤).

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.

相反,我会做类似(def all (components-of (descendants ::root)))的操作,但是我不确定如何解决这个问题,因为我认为这需要按名称查找var(ClojureScript不支持).

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).

所以我的问题是:如何在ClojureScript中动态地维护映射或名称空间+变量列表?

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

推荐答案

您不能动态地执行此操作,但据我所知,您并不需要太多. ClojureScript宏可以反映回编译器中-您可以轻松地使用cljs.analyzer.api命名空间(通过var元数据或其他方法)找出所需的var,并自动发出所需的运行时信息映射.实际上,这与cljs.test/run-tests的工作原理非常相似.它使用编译器过滤掉所有带有:test元数据的命名空间中的所有变量,并生成用于测试每个变量的代码.值得详细研究cljs.test来了解如何做到这一点.

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.

这篇关于枚举名称空间并在ClojureScript中动态加载它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆