当函数返回其符号时,如何从var中提取元数据?

时间:2018-05-06 15:59:07

标签: clojurescript clojure.spec re-frame

我使用re-framespec来验证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是我能找到的最接近的讨论,但我无法解决。

帮助!

2 个答案:

答案 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获取的数据。如果您感到好奇,相关的analyzercompiler代码是有益的。

因此,如果(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))