2

我使用re-frame with spec来验证app-db,就像在todomvc示例中一样。

当用户输入无效条目时,我正在使用s/explain-data(在重新帧拦截器中)返回一个命名导致验证失败problems的 icate 的地图。:pred这个谓词是一个类似的符号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"
  • metanil
  • var给出编译时错误“无法解析 var: p1__46744# in this context”

我认为问题在于我得到了一个符号,但我需要它所引用的 var,这是元数据所在的位置。

我试过使用宏,但真的不知道我在做什么。是我能找到的最接近的讨论,但我无法解决。

帮助!

4

2 回答 2

2

通常,您不能这样做,因为 var 在 ClojureScript 中没有具体化。

来自https://clojurescript.org/about/differences#_special_forms

  • 变量注释
    • 变量在运行时不会被具体化。当编译器遇到 var 特殊形式时,它会发出一个反映编译时元数据的 Var 实例。(这满足了许多常见的静态用例。)

在 REPL,当你评估

(meta #'project.db/validation-function)

这和

(meta (var project.db/validation-function))

编译时(var project.db/validation-function),会发出 JavaScript 代码以创建一个cljs.core/Var实例,其中包含您可以使用meta. 如果你很好奇,相关的分析器编译器代码很有指导意义。

因此,如果(var project.db/validation-function)(或读者等价物#'project.db/validation-function)在您的源代码中的任何地方都不存在(或间接通过使用类似的东西ns-publics),则此数据在运行时将不可用。

在优化代码大小时,省略 var reification 是一件好事。如果启用:repl-verbose REPL 选项,您将看到表达式(var project.db/validation-function)发出大量 JavaScript 代码。

在 REPL 中使用s 时,编译器携带了足够的分析元数据,并且以构建您正在使用具体化 Clojure var 的错觉的名义,def完成了一些事情——比如让表单的评估返回 var 而不是值。def但这种错觉在为生产交付生成代码时有意消失,只保留必要的运行时行为。

于 2018-05-07T01:22:17.877 回答
0

编辑:对不起,我没有看到这var对你不起作用。还在努力...

您需要project.db/validation-functionvar包围符号。这会将符号解析为 var。

所以what-goes-here?应该是

(defn what-goes-here? [pred]
  (var pred))
于 2018-05-06T16:10:30.077 回答