2012-02-26 5 views
6

저는 SICP를 통해 작업하고 있습니다. 한 가지 연습은 foreach (doseq)를 구현하는 것입니다. 이것은 학업 수행입니다. do는 Clojure의 특별한 형태이며 내가 그런 아무것도 있다고 생각하지 않기 때문에, 내가 바람을 피우고 do 경우에 대해 약간 어두운이야,클로저에 foreach (doseq)를 구현하십시오.

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

하지만 : Clojure에,이 내가 생각 해낸 것입니다 SICP에서 아직 소개되지 않았습니다. 더 미니멀리스트 답변이 있습니까?

여기에 마지막 요소 시저를 실행하는 또 다른 시도이다 :

(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 

편집 :

당신이 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))))) 
+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

도움이 되셨 다니 다행입니다. 나는 다시 한번 생각하고'행동이 없다 '라고 결정했다. – 4e6