Реализация foreach (dosq) в ближайшем будущем - PullRequest
6 голосов
/ 26 февраля 2012

Я работаю через SICP - одним из упражнений является реализация foreach (дозаq). Это академическое упражнение .Вкратце, это то, что я придумал:

(defn for-each [proc, items]
  (if (empty? items) nil
      (do
        (proc (first items))
        (recur proc (rest items)))))

, но я немного озадачен тем, что do обманывает, потому что do - это особая форма в clojure, и я не 'Не думаю, что что-то подобное было введено в SICP. есть ли более минималистичный ответ?

Вот еще одна попытка, которая выполняет proc только для последнего элемента:

(defn for-each-2 [proc, items]
  (let [f (first items)
        r (rest items)]
    (if (empty? r)
      (proc f)
      (recur proc r))))

Ответы [ 2 ]

3 голосов
/ 26 февраля 2012

Используйте doseq и все готово.Например:

(doseq [e '(1 2 3)]
       (prn e))

Напечатает:

1
2
3
nil

РЕДАКТИРОВАТЬ:

Если вы хотите реализовать for-each вручную и используякак можно меньше специальных форм, вот другая альтернатива, хотя в итоге она почти такая же короткая, как ваша:

(defn for-each [f l]
  (cond (empty? l) nil
        :else (do (f (first l)) 
                  (recur f (rest l)))))

Интересно, что ту же самую процедуру можно было бы написать более кратко на схеме, диалекте Лисп, используемом вSICP:

(define (for-each f l)
  (cond ((null? l) null)
        (else (f (first l))
              (for-each f (rest l)))))
1 голос
/ 27 февраля 2012

Вот моя попытка. Он просто выполняет выполнение функции во внутреннем цикле.

(defn for-each [fun, xs]
  (loop [fun fun
         xs xs
         action nil]
    (if (first xs)
      (recur fun (rest xs) (fun (first xs)))
      xs)))
...