2012-02-26 8 views
6

私はSICPを使って作業しています.1つの練習はforeach(doseq)を実装することです。 これは学問的な演習です。 doはClojureの中で特別な形であり、私はそのようなものは持っていないと思うので、私は浮気されdo場合について少し暗いよ、clojureでforeach(doseq)を実装しています

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

しかし:Clojureのでは、これは私が思い付いたものですまだSICPに導入されていない。 もっとミニマルな答えがありますか?

はここだけ最後の要素にprocのを実行し、別の試みです:

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

あなたは問題ありません。 SICPはここでは扱いにくいです。脚注3の非常に小さなテキストをhttp://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#call_footnote_Temp_323でご覧ください。 SICPで 'cond 'を実行するときはいつでも、' cond'の各節に対して暗黙の 'begin'があります。そして、SICPの 'begin'はClojureでかなり' do'です。 – dyoo

答えて

3

使用doseq、あなたはすべてのセットです。たとえば:

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

が印刷されます:

1 
2 
3 
nil 

EDIT:

あなたはfor-each手で、できるだけ少数の特殊な形式を使用して実装する場合は、ここでは別の代替があるが、ですあなたと同じくらい短いことになります:

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

は興味深いことに、同じ手順を、スキーム、SICPで使用されるLispの方言で、より簡潔に書かれている可能性:ここでは

(define (for-each f l) 
    (cond ((null? l) null) 
     (else (f (first l)) 
       (for-each f (rest l))))) 
+0

はい、できるだけ特殊な書式で実装したいと思います。 –

+0

@DustinGetz私の回答を別のオプションで更新しましたが、それは実際にはそれほど短くはありません –

+1

そして、少なくともClojureでは、複数のステートメントを順番に実行する必要があることを示すために 'do'を避けることはできません –

1

は私の試みです。内部ループ内で関数の実行を伝えるだけです。

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

は非常に賢明です。ループの括弧で囲まれた部分は、順番に実行されるバインディングのリストであるという事実を利用しています。今私は理解しています、これは 'do'アプローチと同等の複雑さです。 –

+0

あなたが役に立ったことをうれしく思っています。私はもう一度考えて、 'action nil'がうまくいくと決めました。 – 4e6

関連する問題