Есть ли стандартная функция foreach в Clojure? - PullRequest
17 голосов
/ 06 сентября 2011
Clojure> (doc foreach)
Unable to resolve var: foreach in this context

Clojure> (doc map)
-------------------------
clojure.core/map
([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])

Конечно, я могу использовать «карту» для имитации «foreach», но карта всегда возвращает nil, что делает вывод уродливым в следующей функции:

(defn div618 [p1 p2]
    (let [ratio [0.,0.191,0.236,0.382,0.5,0.618,0.809,1.]
          price (fn [r] (if (<= p1 p2) (+ p1 (* (- p2 p1) r)) (- p1 (* (- p1 p2) r))))]

    (if (<= p1 p2)
        (**map** #(println (format "-------%.3f   %.2f-------" %1 (price %1))) (reverse ratio))
        (**map** #(println (format "-------%.3f   %.2f-------" %1 (price %1)))  ratio))))

С уважением!

Ответы [ 6 ]

57 голосов
/ 06 сентября 2011

Я думаю, что doseq может быть тем, что вы ищете:

(doseq [i [0 1 2 3]] (println i))

Однако это все равно вернет nil - все формы в Clojure оценятся в некоторое значение;нет эквивалента для Common Lisp (values).

6 голосов
/ 28 октября 2016

Начиная с Clojure 1.7 вы можете использовать run!:

user=> (run! println (range 10))

0
1
2
3
4
5
6
7
8
9
=> nil  ; returns nil

См. этот ответ до Как напечатать каждый элемент списка в отдельной строке?

3 голосов
/ 14 сентября 2011

Вы можете использовать доза или Доалл. Ниже приведен пример использования doall.

(defn div618 [p1 p2]
    (let [ratio [0.,0.191,0.236,0.382,0.5,0.618,0.809,1.]
          price (fn [r] (if (<= p1 p2) (+ p1 (* (- p2 p1) r)) (- p1 (* (- p1 p2) r))))]

    (doall (map #(println (format "-------%.3f   %.2f-------" %1 (price %1))) (if (<= p1 p2) (reverse ratio) ratio)))))

Вы также можете отделить печать от вычисления функции следующим образом:

(defn div618 [p1 p2]
    (let [ratio [0.,0.191,0.236,0.382,0.5,0.618,0.809,1.]
          price (fn [r] (if (<= p1 p2) (+ p1 (* (- p2 p1) r)) (- p1 (* (- p1 p2) r))))]

    (map (fn [x] [x (price x)]) (if (<= p1 p2) (reverse ratio) ratio))))

(doall (map #(println (format "-------%.3f   %.2f-------" (first %1) (last %1))) (div618 1 2)))
2 голосов
/ 06 сентября 2011

map используется для применения функции f к каждому элементу seq, в вашем случае вы применяете print, которая возвращает nil, поэтому вы получаете промежуточный seq из nils, который затем выбрасываете.Когда вам нужны побочные эффекты, такие как печать, вы используете дозаq.

Clojure не имеет единой карты форм foreach, сокращает фильтр и т. Д. Технически это все формы foreach, которые все делают что-то для каждого элемента в последовательности.Карта также ленива, ваш пример будет печататься только в ответе, потому что repl заставляет lazy seq понять, что они говорят, что если вы упакуете это в банку, это ничего не даст.

0 голосов
/ 22 октября 2015
(defn div618 [p1 p2]
  (let [ratio [0.000 0.191 0.236 0.382 0.500 0.618 0.809 1.000]            
        price #(if (<= p1 p2)
                 (-> p2 (- p1) (* %) (+ p1))
                 (-> p1 (- p2) (* %) (- p1)))
        print-all #(doseq [item %]
                     (printf "-------%.3f   %.2f-------\n" item (price item)))]
    (if (<= p1 p2)
      (print-all (reverse ratio))
      (print-all ratio))))
0 голосов
/ 06 сентября 2011

Я думаю, вы хотите понять список Clojure, см .: http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#List_Comprehension

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...