4

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

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

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

这看起来像我想要的(并且最终似乎可以工作),但是丢弃宏应该如何工作?医生

#_ 后面的形式被读者完全跳过。

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

4

3 回答 3

3

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

前:

(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]
于 2017-03-16T21:55:27.187 回答
1

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

所以#_%&就像#_@#_;并且不起作用。丢弃阅读器#_只能用于“真实形式”,如()[](等)

于 2017-03-16T18:05:07.857 回答
0

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

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

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

于 2017-03-18T14:38:12.823 回答