В чем разница между функциями door dorun doseq и для?
В чем разница между функциями doall
, dorun
, doseq
и for
?
Я нашел некоторую информацию, разбросанную по всему Интернету, но я думаю, что было бы лучше централизовать эту информацию здесь.
Ответы
Ответ 1
dorun
, doall
и doseq
- все для форсирования ленивых последовательностей, предположительно для получения побочных эффектов.
-
dorun
- не удерживайте целую секцию в памяти во время форсирования, возвратите nil
-
doall
- удерживать целую секцию в памяти при форсировании (т.е. все) и возвращать seq
-
doseq
- то же самое, что и dorun
, но дает вам шанс сделать что-то с каждым элементом, поскольку он принудительно; возвращает nil
for
отличается тем, что он понимает список и не связан с принудительными эффектами. doseq
и for
имеют один и тот же синтаксис связывания, который может быть источником путаницы, но doseq
всегда возвращает nil
, а for
возвращает ленивый seq.
Ответ 2
Вы можете видеть, как dorun
и doall
относятся друг к другу, глядя на (упрощенный) исходный код:
(defn dorun [coll]
(when (seq coll) (recur (next coll))))
(defn doall [coll] (dorun coll) coll)
-
dorun
пробегает последовательность, забывая ее, как она идет,
в конечном итоге возвращая nil
.
-
doall
возвращает свой аргумент последовательности, теперь реализуемый dorun
.
Аналогично, мы могли бы реализовать doseq
в терминах dorun
и for
:
(defmacro doseq [seq-exprs & body]
`(dorun (for ~seq-exprs [email protected])))
По какой-то причине производительность, возможно, не выполняется. Стандарт doseq
записывается полностью, подражая for
.