Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

implementing foreach (doseq) in clojure

i'm working through SICP - one exercise is to implement foreach (doseq). This is an academic exercise. In clojure, this is what I came up with:

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

but, i'm a little murky about if do is cheating, because do is a special form in clojure and i don't think anything like that has been introduced yet in SICP. is there a more minimalist answer?

Here's another attempt which only executes proc on the last element:

(defn for-each-2 [proc, items]
  (let [f (first items)
        r (rest items)]
    (if (empty? r)
      (proc f)
      (recur proc r))))
like image 551
Dustin Getz Avatar asked Feb 26 '12 18:02

Dustin Getz


1 Answers

Use doseq and you're all set. For example:

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

Will print:

1
2
3
nil

EDIT :

If you want to implement for-each by hand and using as few special forms as possible, here's another alternative, although it ends up being almost as short as yours:

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

Interestingly, the same procedure could have been written more succinctly in Scheme, the Lisp dialect used in SICP:

(define (for-each f l)
  (cond ((null? l) null)
        (else (f (first l))
              (for-each f (rest l)))))
like image 184
Óscar López Avatar answered Sep 24 '22 00:09

Óscar López