我使用re-frame和spec来验证app-db
,就像在todomvc示例中一样。
当用户进行无效输入时,我使用s/explain-data
(在重帧拦截器中)返回problems
地图,命名导致验证的:pred
icate失败。此谓词是project.db/validation-function
等符号。
我的验证功能具有元数据,可以使用以下命令从repl访问:
(meta #'project.db/validation-function)
函数定义(在project.db
命名空间中)如下所示:
(defn validation-function
"docstring..."
{:error-message "error message"}
[param]
(function-body...)
问题是我无法解决如何动态检索元数据(在project.events
命名空间中工作),例如:
(let [explain-data (s/explain-data spec db)
pred (->> (:cljs.spec.alpha/problems explain-data) first :pred)
msg (what-goes-here? pred)]
msg)
我已经尝试了以下代替what-goes-here?
:
symbol?
提供true
str
提供"project.db/validation-function"
meta
提供nil
var
给出编译时错误"无法在此上下文中解析var:p1__46744#" 我认为问题在于我获得了一个符号,但我需要它引用的var,这是元数据所在的位置。
我尝试过使用微博,但我真的不知道自己在做什么。 This是我能找到的最接近的讨论,但我无法解决。
帮助!
答案 0 :(得分:2)
一般情况下,你不能这样做,因为vars不是在ClojureScript中实现的。
来自https://clojurescript.org/about/differences#_special_forms:
- var notes
- Vars未在运行时生效。当编译器遇到var特殊形式时,它会发出反映编译时元数据的Var实例。 (这满足了许多常见的静态用例。)
在REPL,评估时
(meta #'project.db/validation-function)
这与
相同(meta (var project.db/validation-function))
并且在编译(var project.db/validation-function)
时,会发出JavaScript代码以创建cljs.core/Var
实例,其中包含您可以使用meta
获取的数据。如果您感到好奇,相关的analyzer和compiler代码是有益的。
因此,如果(var project.db/validation-function)
(或读者等效#'project.db/validation-function
)并不存在于源代码中的任何位置(或通过使用类似ns-publics
的内容间接存在)此数据在运行时无法使用。
在优化代码大小时,省略var varification是一件好事。如果启用:repl-verbose REPL选项,您将看到表达式(var project.db/validation-function)
会发出大量JavaScript代码。
在REPL中使用def
时,编译器会携带足够的分析元数据,并且完成的事情就像评估def
表单一样,返回var而不是值 - 在名称中构建一种幻觉,你正在使用具体的Clojure变种。但是,在为生产交付生成代码时,这种错觉会故意消失,只保留基本的运行时行为。
答案 1 :(得分:0)
编辑:抱歉,我没有看到var
没有为您效劳。还在努力......
您需要使用var包围符号project.db/validation-function
。这会将符号解析为var。
所以what-goes-here?
应该是
(defn what-goes-here? [pred]
(var pred))