Clojure 无名称空间的取消引用
我需要不带名称空间的引用,并将其与取消引用相结合。比如:Clojure 无名称空间的取消引用,clojure,clojurescript,Clojure,Clojurescript,我需要不带名称空间的引用,并将其与取消引用相结合。比如: '[a b ~c] 不幸的是,取消引用仅适用于语法引用: `[a b ~c] 但随后它扩展到 [user/a user/b 7] 我想在不使用名称空间的情况下进行扩展。clojurians slack channel上的建议如下: 对符号使用“quote unquote”组合以去除名称空间: `[~'a ~'b ~c] 这非常有效。作为参考,我一直在研究一种类似的功能,它不需要像~'a那样对每个希望保持不变的符号进行防御处理。它还
'[a b ~c]
不幸的是,取消引用仅适用于语法引用:
`[a b ~c]
但随后它扩展到
[user/a user/b 7]
我想在不使用名称空间的情况下进行扩展。clojurians slack channel上的建议如下: 对符号使用“quote unquote”组合以去除名称空间:
`[~'a ~'b ~c]
这非常有效。作为参考,我一直在研究一种类似的功能,它不需要像
~'a
那样对每个希望保持不变的符号进行防御处理。它还没有出版,但这里是技术:
;-----------------------------------------------------------------------------
(defn unquote-form?
[arg]
(and (list? arg)
(= (quote unquote) (first arg))))
(defn unquote-splicing-form?
[arg]
(and (list? arg)
(= (quote unquote-splicing) (first arg))))
(defn quote-template-impl
[form]
(walk/prewalk
(fn [item]
(cond
(unquote-form? item) (eval (xsecond item))
(sequential? item) (let [unquoted-vec (apply glue
(forv [it item]
(if (unquote-splicing-form? it)
(eval (xsecond it))
[it])))
final-result (if (list? item)
(t/->list unquoted-vec)
unquoted-vec)]
final-result)
:else item))
form))
(defmacro quote-template
[form]
(quote-template-impl form))
和单元测试,以显示它的作用:
;-----------------------------------------------------------------------------
(def vec234 [2 3 4])
(dotest
(is (td/unquote-form? (quote (unquote (+ 2 3)))))
(is (td/unquote-splicing-form? (quote (unquote-splicing (+ 2 3)))))
(is= (td/quote-template {:a 1 :b (unquote (+ 2 3))})
{:a 1, :b 5})
(is= (td/quote-template {:a 1 :b (unquote (vec (range 3)))})
{:a 1, :b [0 1 2]})
(is= (td/quote-template {:a 1 :b (unquote vec234)})
{:a 1, :b [2 3 4]})
(let [result (td/quote-template (list 1 2 (unquote (inc 2)) 4 5))]
(is (list? result))
(is= result (quote (1 2 3 4 5))))
(is= (td/quote-template [1 (unquote-splicing vec234) 5]) ; unqualified name OK here
[1 2 3 4 5])
(is= (td/quote-template [1 (unquote-splicing (t/thru 2 4)) 5])
[1 2 3 4 5])
(is= (td/quote-template [1 (unquote (t/thru 2 4)) 5])
[1 [2 3 4] 5])
)
因此,您可以使用
quote模板
,而不是Clojure的语法引号(即backquote)。然后,使用unquote
或unquote-picting
将值插入到带引号的模板中,而不将名称空间预先添加到其他符号中。我知道这可能不是您想要的答案,为什么不使用代码来构造您想要的东西呢?为什么要强迫它在一个表达式中完成?例如,你可以使用
(conj '[a b] c)