2010-11-22 3 views
5

다음과 같은 Clojure 코드는 (avg-bids 4000 10 5)를 호출하면 java.lang.StackOverflowError가됩니다. 나는 sum-bids가 tail-recursive 함수로 쓰여졌 기 때문에 그 이유를 알아 내려고 노력했다. Clojure 1.2 사용.tail-recursive 함수에서 StackOverflowError

왜 이런 일이 발생하는지 알고 계십니까?

(ns fixedprice.core 
    (:use (incanter core stats charts))) 

(def *bid-mean* 100) 

(defn bid [x std-dev] 
    (sample-normal x :mean *bid-mean* :sd std-dev)) 

(defn sum-bids [n offers std-dev] 
    (loop [n n sum (repeat offers 0)] 
    (if (zero? n) 
     sum 
     (recur (dec n) (map + sum (reductions min (bid offers std-dev))))))) 

(defn avg-bids [n offers std-dev] 
    (map #(/ % n) (sum-bids n offers std-dev))) 
+0

꼬리 재귀 함수는 자신을 마지막으로 호출합니다. 나는 당신의 코드에서 그런 것을 보지 못했다. – Gabe

+0

@Gabe : loop-recur는 tail-recursion-like 동작을 발생시킵니다. http://clojure.org/special_forms를 참조하십시오. – Ralph

+0

Ralph :'loop-recur'는'for' 루프 패턴입니다. 'recur'를 함수에서 마지막으로 호출하는 것은 꼬리 재귀입니다. – Gabe

답변

8

map 게으른, 당신은 recur를 통해 매핑의 매우 중첩 매핑을 구축하고 있습니다. 역 추적은 게으름을 물리 치기 위해 주위 doall을 넣어하는 것입니다 해결하기 위해

Caused by: java.lang.StackOverflowError 
     at clojure.lang.LazySeq.seq(LazySeq.java:56) 
     at clojure.lang.RT.seq(RT.java:450) 
     at clojure.core$seq.invoke(core.clj:122) 
     at clojure.core$map$fn__3699.invoke(core.clj:2099) 
     at clojure.lang.LazySeq.sval(LazySeq.java:42) 
     at clojure.lang.LazySeq.seq(LazySeq.java:56) 
     at clojure.lang.RT.seq(RT.java:450) 
     at clojure.core$seq.invoke(core.clj:122) 
     at clojure.core$map$fn__3699.invoke(core.clj:2099) 
     at clojure.lang.LazySeq.sval(LazySeq.java:42) 
     at clojure.lang.LazySeq.seq(LazySeq.java:56) 
     at clojure.lang.RT.seq(RT.java:450) 
     at clojure.core$seq.invoke(core.clj:122) 
     at clojure.core$map$fn__3699.invoke(core.clj:2099) 
     at clojure.lang.LazySeq.sval(LazySeq.java:42) 
     at clojure.lang.LazySeq.seq(LazySeq.java:56) 
     at clojure.lang.RT.seq(RT.java:450) 
     at clojure.core$seq.invoke(core.clj:122) 
     at clojure.core$map$fn__3699.invoke(core.clj:2099) 

한 가지 방법 ... 조금 애매하지만, 자세히 보면 당신은지도,지도,지도를 볼 수 있습니다.

(defn sum-bids [n offers std-dev] 
    (loop [n n sum (repeat offers 0)] 
    (if (zero? n) 
     sum 
     (recur (dec n) (doall (map + sum (reductions min (bid offers std-dev)))))))) 

user> (avg-bids 4000 10 5) 
(100.07129114746716 97.15856005697917 95.81372899072466 94.89235550905231 94.22478826109985 93.72441188690516 93.32420819224373 92.97449591314158 92.67155818823753 92.37275046342015) 
+1

브라이언, 고마워요. 나는 게으른 시퀀스의 결과를 좀 더주의 깊게 알아야만한다고 생각한다. –

관련 문제