2012-06-14 3 views
11

다소 비싸지 만 (데이터베이스 시작) 약간의 계산이 있습니다. 실제로 사용하려고하면 데이터베이스를 만들고 싶습니다. 내가 사용되는 (또는 dereferenced) 이벤트에서 해당 값을 평가할 수있는 참조 변수 (또는 가능한 경우 일반 변수를 찾고 있는데요. 뭔가 개념적으로 다음과 같습니다. 나도 방금 var에 V를 사용하거나 @v 전화 Clojure에 지연 변수가 있습니까?

(def v (lazy-var (fn [] (do (println "REALLY EXPENSIVE FUNCTION") true)))) 

와 미래

, 그때는 "정말 비싸다 기능"을 인쇄 할 수 및 V 그에서 것은 참의 값을 갖습니다. 여기서 중요한 점은 변수가 참조 될 때까지 fn이 평가되지 않았다는 것입니다. 필요한 경우 변수의 값을 계산하기 위해 함수가 한 번만 평가됩니다. 이것이 클로제에서 가능합니까?

답변

25

delay이 응용 프로그램에 대한 완벽한 것 :

delay- (delay & body)

는 표현의 몸을 가져 와서 함께 (몸을가 강제로 첫 번째 시간을 호출하는 지연 개체를 얻을 수 force 또는 deref/@) 결과를 캐시하고 모든 후속 force 호출에 반환합니다.

Var로 저장된 delay 호출 본문 내에 데이터베이스 핸들을 구성하는 코드를 배치하십시오. 그런 다음 DB 핸들을 사용해야 할 때마다이 Var를 참조 해제하십시오. 첫 번째 역 참조에서 본문이 실행되고 이후의 역 참조시에 캐시 된 핸들이 반환됩니다. 이러한 목적

(def db (delay (println "DB stuff") x)) 

(select @db ...) ; "DB stuff" printed, x returned 
(insert @db ...) ; x returned (cached) 
+1

이런, 내가 이것을 보려고 할 때 왜 그 단어를 생각하지 않았습니까? –

6

Clojure의 소개 1.3 memoize 기능 :

(memoize의 F)

는 referentially 투명 memoized 기능의 버전을 반환. 함수의 memoized 버전은 인수에서 결과로 매핑의 캐시를 유지하고 동일한 인수가있는 호출이 자주 반복 될 경우 높은 메모리를 희생하여 성능이 향상됩니다. 당신의 예에서

는 memoize에 존재하지 않는 게으른-VAR을 대체 :

(def v (memoize (fn [] (do (println "REALLY EXPENSIVE FUNCTION") true)))) 
(v) 
=>REALLY EXPENSIVE FUNCTION 
=>true 
(v) 
=>true 

(지연 EXPR)도 일을 다른 대답은 설명한다. dereferencing 지연에 대한 추가 설명 - force와 deref/@의 차이점은 지연이 아닌 변수에 사용될 경우 force가 예외를 throw하지 않는다는 것입니다. 반면 deref/@는 ClassCastException을 던질 수 있습니다. "clojure.lang.IDeref에 캐스팅 할 수 없습니다".

관련 문제