2010-11-29 2 views
14

풍부한 Hickey와 다른 사람들은 Clojure가 JVM 7 또는 8에 대해 예정된 invokeDynamic에서 상당한 개선을 얻지는 않을 것이지만 꼬리 재귀를 통해 성능이 향상 될 것이라고 언급했습니다.Clojure JVM 7/8 개선

윌 꼬리 재귀 내가 컴파일러는 아마 이미 루프 구조를 생성하기 때문에 그들이 더 빨리 얻을 기대하지 않습니다

(fn [...] (recur ...)) 

또는

(loop [...] (recur ...)) 

에 어떤 영향을 미칩니다.

답변

17

비 당신은 이미 당신이 꼬리 재귀 함수를 컴파일러에게 이것은 (일반 필수적 루프처럼) goto를 사용하는 바이트 코드

를 생성하는 컴파일러를 허용 recur 사용하는 경우 때문에 예를 빨리 얻을 것이다

JVM이 꼬리 호출 최적화를 얻는다면 물론 약간의 이점이 있습니다.

당신은 늘 (당신이 원하지 않는 경우) 더 이상 재발 이용해야하므로 JVM이 감지 할 수 없습니다 Nowdays이 같은 함수 (꼬리 재귀 함수)

(defn testfn [n] (when (not= 1000 n) (testfn n))) 

을 쓸 수 있습니다 꼬리 재귀. 당신이 쓴 것처럼 위의 기능을 확인하기 위해 JVM이 수 꼬리 호출 최적화의 추가로이 (따라서 필수적 루프 속도를 얻을) :

(defn testfn [n] (when (not= 1000 n) (recur n))) 

그래서 개선의 크지 않은 그이지만 거기에 또 다른 꼬리 전화 최적화가 정말 좋은 경우.

서로 (때로는 둘 이상)를 호출하고 스택을 유지할 필요가없는 (꼬리 재귀) 함수가있는 경우 JVM에서이를 최적화 할 수 있습니다. recur에게 다른 기능으로 건너 뛰라고 말할 수 없기 때문에 이것은 불가능합니다. 다음은 그 예입니다.

(defn even [n] (if (zero? n) true (odd? (dec n))) 
(defn odd [n] (if (zero? n) false (even (dec n))) 

이 큰 번호를하려고하면

는 스택을 날려하지만 당신은하지 않습니다 꼬리 호출 최적화 알고 있습니다.

나는 조금 더 남겼습니다.

http://pramode.net/clojure/2010/05/08/clojure-trampoline/

하십시오 대신 trampoline을 설명 당신이 (프로그래밍 스타일과 약간의 오버 헤드에 약간의 변화)가 이미이 작업을 수행 할 수 있도록 trampoline라는 함수를 내가 정확히 수행하는 블로그를 참조 할가