4

这实际上可能是一个XY 问题,所以我将尝试首先解释目标是什么。

我正在构建一个由一组Reagent组件组成的 ClojureScript 应用程序。它提供了一个用户界面,您可以在其中动态添加或删除 UI 元素。这些 UI 元素(组件)具有一定的类型。例如 Markdown 组件is-aText 组件。每当用户看到添加 Text 的选项时,我们都会列出与 type+后代匹配的所有组件(在本例中为 Markdown,可能还有其他组件)。

我编码的方式如下。每个组件都在自己的命名空间中,这个命名空间包含一个返回新组件的构建器函数。在命名空间的根,它还调用(派生::type ::parent)

现在在一些不同的命名空间中,我们需要并在一个映射中枚举所有这些组件,例如:

(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地图为面向用户的菜单提供数据(可以添加哪些组件,按类型过滤)。

现在,您可以想象,这并不漂亮。因为它现在必须手动维护层次结构中所有类型的(可能)长列表。

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

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

4

1 回答 1

3

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

于 2015-05-11T15:34:04.430 回答