Аргументы функции всегда оцениваются перед вызовом функции. Если вы хотите отложить оценку или представить некоторые вычисления или код в виде объекта, у вас есть несколько вариантов:
- Используйте функцию (см. Мой код ниже)
- Используйте макрос и объедините некоторый код в другой код, который генерирует макрос
- пароль в виде списка в кавычках и
eval
его.
Использование функции - это то, что вы хотите делать в 99% случаев. 1% времени вам понадобятся макросы. Вам никогда не понадобится eval
, если вы не генерируете код во время выполнения или делаете очень странные вещи.
user> (defn runner [f]
(doseq [a (range 3)
b (range 3)]
(println a b (f a b))))
#'user/runner
user> (runner (fn [x y] (+ x y)))
0 0 0
0 1 1
0 2 2
1 0 1
1 1 2
1 2 3
2 0 2
2 1 3
2 2 4
Это также можно записать как (runner #(+ %1 %2)
или даже просто (runner +)
.
Нет необходимости передавать "a
" и "b
" в функцию в качестве аргументов. doseq
и for
вводят свои локальные, лексически ограниченные имена для вещей. Нет причин, по которым они должны использовать a
и b
; подойдет любое имя. То же самое для fn
. Я использовал x
и y
здесь, потому что это не имеет значения.
Я мог бы использовать a
и b
в теле fn
, но они были бы отличными a
и b
от тех, что doseq
видит. Вы можете прочитать о scope , если это не имеет смысла.