Clojure函数文字带有' rest arguments'放弃'放弃'读者宏

时间:2017-03-16 16:51:24

标签: clojure reader-macro

我想在Clojure中使用一个函数文字,它可以使用任意数量的参数,但实际上并没有使用它们。所以我发现了%&('休息arg' for function literal)和#_(' discard' reader macro)。

但他们如何合作让我感到惊讶:

=> (macroexpand `#(... #_ %&))
(fn* [& rest__125459__125460__auto__] (...))

这看起来像我想要的(并且似乎最终会起作用),但是丢弃宏应该如何工作?文档says

  

读者完全跳过#_后的表格。

但显然这里忽略的%&形式有副作用,即它影响函数文字args列表。我应该依赖这种行为还是看起来更像是一个错误?

3 个答案:

答案 0 :(得分:2)

弃牌阅读器宏#_不能单独使用。在这里你可以看到它的实际效果:

在:

(println "first")
(do
  (print "second ")
  (dotimes [i 5]
    (print i " "))
  (newline))
(println "third")

first
second 0  1  2  3  4  
third

之后:

(println "first")
#_(do
    (print "second ")
    (dotimes [i 5]
      (print i " "))
    (newline))
(println "third")

first
third

因此,添加#_(递归地)会丢弃它所应用的表单中的所有内容。

关于忽略参数的原始问题,您有几个选择:

(mapv  #(do %& 42)        (range 3)) => [42 42 42]
(mapv   (fn [& _]   42)   (range 3)) => [42 42 42]
(mapv   (constantly 42)   (range 3)) => [42 42 42]

答案 1 :(得分:0)

我说得太快了,可能不是一个bug,也许它应该被禁止并给出错误。但实际上#_用于放弃表单,而%&不是but also a reader macro形式。

所以#_%&就像#_@#_;一样无效。丢弃阅读器#_仅用于"真实形式"例如()[](等)

答案 2 :(得分:0)

#_子句仅适用于表单。在您的示例中,后面有一个空格,因此它没有任何效果。

使用#_添加任何列表/表单以完全忽略它:

#_(do (print 42) (/ 0 0)) ;; there won't be an error