2013-01-23 2 views
2

저는 clojure에서 웹 크롤러를 프로그래밍하고 있으며 함수에 제공하는 깊이와 독립적으로 일정한 시간이 걸립니다. 이것은 함수 자체입니다.Clojure 재귀 함수 실행 시간

(defn crawl [source current-depth max-depth] 
    (if (= current-depth 0) (write-to-hf "{" false)) 
    (let [targets (get-links source)] 
     (write-to-hf (str ":" source " " (seq targets) "\n") true) 
     (if (< current-depth max-depth) 
      (map crawl targets (repeat (inc current-depth)) (repeat max-depth)) 
      (if (= current-depth 0) 
       (do (write-to-hf "}" true) 
       targets) 
       targets)))) 

는 (쓰기에-HF하는 파일에 데이터를 쓰는 기능입니다, 그래서 제 생각 엔 너무 문제에 무관하다.) (이 clojure soup을 사용하고,하지만 난 무관하다 생각)

내가 REPL에 서면을 내 기능을 테스트

:

(crawl "http://bg.wikipedia.org" 0 1) 

그것은 모든 링크를 인쇄 한 시간 정도 걸립니다,하지만 난 VAR로 결과를 넣어 경우는 초 후 덜 걸립니다.

(def a (crawl "http://bg.wikipedia.org" 0 1)) 

, I/O 작업이 가장 많은 시간이 고가이기 때문에 이것은 나에게 정상 보이지만, 나는 그것이 재귀의 깊이 층 이상으로 VAR로 결과를 넣어하는 데 걸리는 시간이 얼마나 테스트하기 위해 노력하고 그것은 일정한 것처럼 보인다. 심지어 일 :

((crawl "http://bg.wikipedia.org" 0 100000000000)) 

는 같은 시간이 걸립니다.

왜 이것이 상수인지 설명 할 수 있습니까? 위키피디아 (모든 페이지에 수백 개의 링크가있는 거대한 웹 사이트)의 수십억 페이지와 더 많은 페이지의 링크를 취하는 것이 얼마나 적은 시간에 완료 될 수 있는지 상상할 수 없습니다.

답변

6

이 줄 크롤링 링크의 게으른 순서를 생산 :

링크 (이 경우에 REPL에 의해) 인쇄 그래서 당신은 단지 VAR 말아야에 저장할 때 때 실제 크롤링이 발생
(map crawl targets (repeat (inc current-depth)) (repeat max-depth)) 

그들을 보아라, 어떤 일도 끝나지 않고있다. 아무것도하지 않으면 거의 일정한 시간이 걸립니다. 그 전화를 doall으로 전화하여 게으름을 피하십시오.

+0

좋은 답변입니다. 내 이익을 위해 여기에 '도런 (dorun)'이 더 적절할 지/덜 적합 할 지 설명 할 수 있겠습니까? –

+2

dorun은 결과를 버리고 doall이 결과를 유지합니다. –