想象一下,有一个为cat动态生成的规范
[:first-name string? :surname string?]现在我想在cljs.spec.alpha/cat中使用它们。
在普通的Clojure中,我可以编写一个宏,它将使用args对宏进行cons并求值,对吗?但对于ClojureScript来说,这并不容易,因为macros是编译时的野兽,而且eval也是一种不同的东西。
要将参数矢量应用于ClojureScript中的宏,有哪些解决方法?
发布于 2018-08-31 19:42:11
不幸的是,这对于动态/数据驱动的规范来说并不容易,但这显然是在未来的版本中进行的。
我认为唯一的解决办法是使用eval,或者像你提到的那样使用cljs.spec.alpha内部实现。
cljs.user=> (def cat-args [:x string?])
#'cljs.user/cat-args
cljs.user=> (s/def ::foo (eval (cons 's/cat cat-args)))
:cljs.user/foo
cljs.user=> (s/conform ::foo '("foo"))
{:x "foo"}发布于 2018-09-01 05:26:05
您的规范是在编译时以符号方式生成的吗?如果是这样的话,也许您可以按照您的建议使用宏。
(ns foo.core)
(defmacro gen-spec []
`'~(into '[:first-name string?] '[:surname string?]))
(defmacro apply-macro [name args-form]
`(~name ~@(eval args-form)))下面是一个使用它的示例
$ clj -m cljs.main
ClojureScript 1.10.339
cljs.user=> (require '[clojure.spec.alpha :as s])
nil
cljs.user=> (require-macros 'foo.core)
nil
cljs.user=> (foo.core/gen-spec)
[:first-name string? :surname string?]
cljs.user=> (foo.core/apply-macro s/cat (foo.core/gen-spec))
{:cljs.spec.alpha/op :cljs.spec.alpha/pcat, :ps [#object[cljs$core$string_QMARK_] #object[cljs$core$string_QMARK_]], :ret {}, :ks [:first-name :surname], :forms [cljs.core/string? cljs.core/string?], :rep+ nil}请注意gen-spec如何以符号方式构建规范并以引用的形式返回它。
https://stackoverflow.com/questions/52114521
复制相似问题