2

我有以下 EDN 文件

:abc #request/builder/abc {
    "def" #request/builder/def {
          "someVector" ["sample1", "sample2"]
    }
}

我在 Clojure 中定义了自定义标签阅读器,它在内部调用 java 代码

(defn custom-readers []
    {
        #request/builder/def defBuilder
        #request/builder/abc abcBuilder
    }
)

(defn defBuilder [params]
    (.defBuilder (someJavaUtilityClass.) params)
)

(defn abcBuilder [params]
    (.abcBuilder (someJavaUtilityClass.) params)
)

当我使用 edn/read-string 读取 EDN 时,defBuilder 首先执行,它的值被传递给 abcBuilder。

我想在不修改 EDN 的情况下反转执行顺序。我想修改 abcBuilder 代码,这样如果 abcBuilder 中的 java 调用返回一些值,则只执行 defBuilder。我怎样才能做到这一点。

我尝试通过修改代码如下

(defn defBuilder [params]
    '(.defBuilder (someJavaUtilityClass.) params)
)

(defn abcBuilder [params]
    if((.abcBuilder (someJavaUtilityClass.) params)
       (eval (get params "def"))
    )
)

但这会引发类似“无法解析 someJavaUtilityClass 和参数”的错误。有没有更好的方法来解决这个问题?

4

1 回答 1

0

恐怕这是不可能的。这不是 EDN 的标记文字的工作方式。读取表单调用标记处理程序,其中包括为表单中的任何标记文字调用标记处理程序。换句话说,标签处理程序被称为由内而外。

如果不是这种情况,那么标签的含义将取决于该标签文字所在的位置,这与上下文无关。

查看:https ://github.com/edn-format/edn#tagged-elements

这是相关部分:

当遇到一个标签时,阅读器会首先读取下一个元素(它本身可能是或包含其他标签元素),然后将结果传递给相应的处理程序进行进一步解释,处理程序的结果将是产生的数据值标记+标记元素,即读取标记和标记元素产生一个值。

另请查看:https ://clojure.org/reference/reader#tagged_literals

这是关于 Clojure 阅读器的。再一次,这里是相关的位:

#'my.project.foo/bar通过在向量上调用 Var [1 2 3]。数据读取器函数在表单被读取器作为普通 Clojure 数据结构读取后在表单上调用。

此外,符号只能包含一个/,用于分隔命名空间和名称。查看:https ://github.com/edn-format/edn#symbols

于 2019-12-24T16:26:29.370 回答