在clojure中实现foreach(doseq)

Dus*_*etz 6 lisp recursion scheme clojure sicp

我正在通过SICP工作 - 一个练习就是实施foreach(doseq).这是一项学术活动.在clojure中,这就是我想出的:

(defn for-each [proc, items]
  (if (empty? items) nil
      (do
        (proc (first items))
        (recur proc (rest items)))))
Run Code Online (Sandbox Code Playgroud)

但是,如果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))))
Run Code Online (Sandbox Code Playgroud)

Ósc*_*pez 3

使用doseq即可。例如:

(doseq [e '(1 2 3)]
       (prn e))
Run Code Online (Sandbox Code Playgroud)

将打印:

1
2
3
nil
Run Code Online (Sandbox Code Playgroud)

编辑 :

如果您想手动实现for-each并使用尽可能少的特殊形式,这里还有另一种选择,尽管它最终几乎和您的一样短:

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

有趣的是,相同的过程可以在Scheme(SICP 中使用的 Lisp 方言)中编写得更简洁:

(define (for-each f l)
  (cond ((null? l) null)
        (else (f (first l))
              (for-each f (rest l)))))
Run Code Online (Sandbox Code Playgroud)

  • 啊。所以区别在于,在方案中,else 子句是“do”表达式的列表。clojure 使这一点变得明确,因此需要依赖于某种可以执行语句列表的特殊形式。谢谢! (2认同)