Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 为什么可以';你们不能用普通(无引号的)代码解开接头吗?_Macros_Clojure_Quoting - Fatal编程技术网

Macros 为什么可以';你们不能用普通(无引号的)代码解开接头吗?

Macros 为什么可以';你们不能用普通(无引号的)代码解开接头吗?,macros,clojure,quoting,Macros,Clojure,Quoting,在Clojure中,您可以取消引用值列表以生成代码,例如 (def extra-values [1 2 3 4]) `(+ 100 200 ~@extra-values) => (clojure.core/+ 100 200 1 2 3 4) 同样的方法应该适用于无引号的上下文,这似乎是合乎逻辑的 (def extra-values [1 2 3 4]) (+ 1000 ~@extra-values) => [an error, but one could argue that

在Clojure中,您可以取消引用值列表以生成代码,例如

(def extra-values [1 2 3 4])

`(+ 100 200 ~@extra-values)
=> (clojure.core/+ 100 200 1 2 3 4)
同样的方法应该适用于无引号的上下文,这似乎是合乎逻辑的

(def extra-values [1 2 3 4])

(+ 1000 ~@extra-values)
=> [an error, but one could argue that the answer should be 1010??]

有没有什么深层次的技术/哲学原因可以解释为什么这样做行不通?

一个简单的原因就是这样

`(+ 100 200 ~@extra-values) 
定义不清:是否扩展到

(+ 100 200 1 2 3 4)

(+ 100 200 ~@extra-values)
??如果
~@
结构在该上下文中是合法的,则这两种解释都是有效的

这也在宏观体系中造成了严重问题。考虑

(defmacro foo [x & args]
  `(list ~x ~(count args)))

(let [data '(1 2 3)]
  (foo "three" ~@data))
foo
如何知道传递的参数是什么?它当然不能在编译时扩展它,所以现在unquote拼接只在一些未引用的上下文中有效

总的来说,它只是把语言弄得一团糟,以适应对核心概念理解不足的情况——如果您真的想取消引用splice来构建一个复杂的参数列表,您可以很容易地使用
apply
,例如

(apply + `(100 ~@extra-values 200))

syntax quote
unquote
unquote拼接的要点是帮助开发人员编写宏

例如,如果没有
syntax quote
unquote
,您将不得不编写

user=> (list :a extra-values)
(:a [1 2 3 4])
而不是:

user=> `(:a ~extra-values)
(:a [1 2 3 4])
user=> (concat `(+ 100 200) extra-values)
(clojure.core/+ 100 200 1 2 3 4)
在前一种情况下,读者(人类读者-而不是repl)更难理解结果形式的外观,而后一种情况则保持结果形式的“形状”

那么,如果我们不使用
向量
[1 2 3 4]
而希望将
额外值的内容作为元素拼接到结果表单中,该怎么办?我们需要
unquote拼接
,以便编写:

user=> `(+ 100 200 ~@extra-values)
(clojure.core/+ 100 200 1 2 3 4)
而不是:

user=> `(:a ~extra-values)
(:a [1 2 3 4])
user=> (concat `(+ 100 200) extra-values)
(clojure.core/+ 100 200 1 2 3 4)
同样,
unquote拼接
版本允许代码在计算代码时与结果形式的“形状”相似,而在后一版本中,“形状”在
apply
list
的噪音中丢失

这两个例子都很简单,但是
语法引号
和朋友们在编写更复杂的宏时,真的有了自己的想法

回到你的问题,为什么你不能写
(+1000~@额外值)
?我们在
apply
中已经有了该功能(还有一些限制):


可能是为了避免将语言的“元”特性与语言的“正常”特性混为一谈:)回答得好,我喜欢这些例子。谢谢