[clojure] Clojure에서 lazy 시퀀스를 non-lazy로 변환하는 방법

Clojure에서 다음을 시도했는데 지연되지 않은 시퀀스의 클래스가 반환 될 것으로 예상했습니다.

(.getClass (doall (take 3 (repeatedly rand))))

그러나 이것은 여전히 clojure.lang.LazySeq. 내 생각 엔 doall전체 시퀀스를 평가하지만 메모 화에 여전히 유용하므로 원래 시퀀스를 반환합니다.

그렇다면 게으른 시퀀스에서 지연되지 않은 시퀀스를 만드는 관용적 수단은 무엇입니까?



답변

doall당신이 필요한 전부입니다. (가) 그냥 있기 때문에 seq이 유형 LazySeq은 평가를 보류중인 것을 의미하지 않는다. Lazy seq는 결과를 캐시하므로 모든 작업 을 강제 seqdoall수행하기 위해 한 번 (그대로 ) 게으른 상태로 걸어 가기 만하면됩니다. 전체 컬렉션을 강제로 평가 seq하지 않습니다 .


답변

이것은 어느 정도 분류의 문제입니다. 게으른 시퀀스는 목록, 벡터 또는 맵과 같은 시퀀스 유형 중 하나 입니다. 그래서 대답은 당연히 “당신이 얻고 자하는 non lazy sequence의 유형에 달려
있습니다.

  • 전 게으른 (완전히 평가 된) 게으른 시퀀스 (doall ... )
  • 순차 액세스 목록 (apply list (my-lazy-seq)) OR (into () ...)
  • 나중에 랜덤 액세스를위한 벡터 (vec (my-lazy-seq))
  • 특별한 목적이 있다면지도 나 세트.

당신은 당신이 필요로하는 대부분의 스위트에 어떤 유형의 시퀀스를 가질 수 있습니다.


답변

이 부자는 그의 클로저를 알고있는 것 같고 절대적으로 옳습니다.
그러나 귀하의 예제를 사용하는이 코드 스 니펫 이이 질문에 대한 유용한 보완이 될 수 있다고 생각합니다.

=> (realized? (take 3 (repeatedly rand))) 
false
=> (realized? (doall (take 3 (repeatedly rand)))) 
true

실제로 유형 은 변경되지 않았지만 실현


답변

블로그 게시물 doall에서 재귀 적이 지 않다는 것을 우연히 발견했습니다 . 이를 위해 게시물의 첫 번째 댓글이 트릭을 수행했음을 발견했습니다. 라인을 따라 뭔가 :

(use 'closure.walk)
(postwalk identity nested-lazy-thing)

map오류 조건을 강제하기 위해 일부 중첩 된 응용 프로그램의 평가를 강제하려는 단위 테스트에서이 기능이 유용하다는 것을 알았습니다 .


답변

(.getClass (into '() (take 3 (repeatedly rand))))


답변