Литерал функции Clojure с макросом "rest arguments" после макроса "discard"

Мне нужен литерал функции в Clojure, который может принимать любое количество аргументов, но на самом деле их не использует. Итак, я обнаружил %& ('rest arg' для функционального литерала) и #_ Макрос считывателя 'discard'.

Но как они работают вместе, меня удивляет

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

Это похоже на то, что я хотел (и, кажется, работает в конце), но так ли должен работать макрос сброса? Док говорит:

Форма, следующая за #_, полностью пропущена читателем.

Но видимо тут то игнорируется %& У формы есть побочный эффект, то есть он влияет на список букв функции args. Стоит ли полагаться на это поведение или оно больше похоже на ошибку?

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]

Я говорил слишком рано, вероятно, не ошибка, может быть, это следует запретить и дать ошибку. Но действительно #_ для отбрасывания форм, и %& это не форма, а макрос для читателя.

Так #_%& так же, как #_@, #_; и не работает. Читатель сброса #_ только для использования с "реальными формами", такими как () или же [] (так далее)

#_ пункт применяется только к форме. В вашем примере после него есть пробел, поэтому он не имеет никакого эффекта.

Добавить любой список / форму #_ полностью игнорировать

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

Другие вопросы по тегам