В ближайшем будущем, есть доза-подобная функция, которая получает функцию вместо тела - PullRequest
2 голосов
/ 04 февраля 2012

Я хочу многократно выполнять функцию для ее побочных эффектов в коллекции. Общий способ:

(defn my-func [x] (println x))
(doseq [x '(1 2 3) ]
       (my-func x))

Но переменная x немного громоздка. Я предпочитаю следующий код:

 ((comp doall map) my-func '(1 2 3))

Как вы думаете, это элегантное решение?

Ответы [ 6 ]

6 голосов
/ 05 февраля 2012

clojure.core/dorun лучше, чем doall, потому что doall хранит всю последовательность в памяти, чтобы вернуть ее вам. dorun возвращает nil, так же как и doseq. Сказать, что языковое ядро ​​«должно» предложить что-то вроде domap, немного агрессивно - для языка, который препятствует мутациям и побочным эффектам, у Clojure уже есть множество функций, которые очень близки к тому, что вы хотите и легко комбинируются.

4 голосов
/ 05 февраля 2012

Мне на самом деле очень нравится:

((comp dorun map) my-func '(1 2 3))

Это хороший пример «стиля без очков» в Clojure.Функция более высокого порядка (comp dorun map) потенциально полезна в другом месте .... вы можете назвать ее «применить к последовательности» или что-то подобное.

Вы также можете использовать следующее (предложение Амаллоя), которое также указывает-бесплатно и, возможно, немного более идиоматично:

(dorun (map my-func '(1 2 3)))

Однако имейте в виду, что оба решения, использующие map, создадут промежуточную (ленивую) последовательность для хранения результата функции map.Это подразумевает небольшую дополнительную нагрузку, поэтому, если вы заботитесь о производительности, то я думаю, что стандартный способ с использованием дозаq лучше, т.е.

 (doseq [x '(1 2 3)] (my-func x))
1 голос
/ 30 января 2014

Используйте doseq. Не комбинируйте ленивые последовательности с побочными эффектами. Это может привести к неожиданным результатам, например, с фрагментами последовательности.

0 голосов
/ 16 августа 2017

Большинство ответов здесь были написаны до выпуска 1.7, в котором такая функция была добавлена ​​в Clojure.

Эта функция run!.

(run! f coll) эквивалентно (dorun (map f coll)). Предпочитаю run! в Clojure 1.7 и позже.

0 голосов
/ 16 августа 2017

Я разделяю ваш интерес к лаконичному стилю карты, и мне также не нравится создавать временные переменные в таких случаях.

К счастью, вы можете легко написать эту функцию самостоятельно:у вас есть функция сопоставления для побочных эффектов:

(domap println '(1 2 3))
0 голосов
/ 04 февраля 2012

Почему бы вам просто не написать функцию, которая берет функцию и последовательность и применяет функцию к последовательности с помощью дозаq.

например,

user=> (defn doseqf [fun seq] (doseq [x seq] (fun x)))
#'user/doseqf
user=> (doseqf println '(1 2 3))
1
2
3
nil
...