Литерал функции 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