Clojure 函数文字,在读取器宏之后'rest arguments'宏'discard'



我想要一个在Clojure中可以接受任意数量的参数的函数文字,但实际上并不使用它们。 所以我发现了%&(函数文字的"rest arg"(和#_("丢弃"阅读器宏(。

但是它们如何协同工作让我感到惊讶:

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

这看起来像我想要的(并且似乎最终有效(,但这是丢弃宏应该的工作方式吗? 文档说:

#_ 后面的表单被读者完全跳过。

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

丢弃读取器宏#_不应单独使用。 在这里,您可以看到它的实际效果:

以前:

(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]

我说得太早了,可能不是错误,也许应该禁止并给出错误。但真正#_是丢弃表单%&不是形式,而是阅读器宏。

所以#_%&就像#_@一样,#_;,不起作用。丢弃读取器#_只能与"真实形式"一起使用,如()[](等(

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

在任何列表/表单前面加上#_以完全忽略它:

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

相关内容

最新更新