2014-10-30 6 views
8

Rich Hickey's Strange Loop transducers presentation은 Clojure 1.6에 의 시퀀스에 대해 하나, core.async에있는 채널에 대해 하나씩 map의 두 가지 구현이 있음을 알 수 있습니다.core.async가 시퀀스 측면에서 해당 기능을 구현할 수 있습니까?

enter image description here

이제 우리는 1.7에서 우리가 수집 기능을 제공하지만 때 foldr (reduce) 함수가 mapfilter 같은 고차 함수에서 반환되는 트랜스 듀서를 가지고 있음을 알고있다.

내가 명확하고 실패하려는 이유는 core.async 함수가 시퀀스를 반환 할 수 없거나 Seq과 같은 이유입니다. '인터페이스'(프로토콜)가 다르지만 어떻게 볼 수없는 느낌이 들었습니다.

확실히 채널에서 첫 번째 항목을 가져 오는 경우 시퀀스에서 첫 번째 항목을 가져 오는 것으로 표현할 수 있습니까?

내 질문 : core.async은 시퀀스와 관련하여 해당 기능을 구현할 수 있습니까?

답변

7

네, 그렇다고 할 수 있습니다. 당신은 블록을 이동 무시한다면, 정말 다음과 같이 아무 문제가 없다 (순간의 그렇게하자) :

(defn chan-seq [ch] 
    (when-some [v (<!! c)] 
    (cons v (lazy-seq (chan-seq ch))))) 

그러나 여기 <!! 전화를 확인할 수 있습니다. 이것을 "테이크 블로킹 (take blocking)"이라고 부릅니다.이 함수 내부에는 현재 실행중인 스레드가 채널에서 값을 사용할 수있을 때까지 정지하게하는 약속 및 잠금이 있습니다. 자바 스레드를 아무 것도하지 않고 앉아도 괜찮다면 괜찮을 것입니다.

go 블록의 아이디어는 논리적 프로세스를 훨씬 저렴하게 만드는 것입니다. 이를 수행하기 위해 go 블록은 블록 본문을 채널에 연결된 일련의 콜백으로 다시 작성하므로 내부적으로 go 블록 안의 <!에 대한 호출이 (take! c k)과 같이 변환됩니다. 여기서 k은 나머지 이동 블록.

참된 연속성이 있거나 JVM이 경량 스레드를 지원한다면 yes, go-blocks과 blocking takes를 결합 할 수 있습니다. 그러나 이것은 현재 Pulsar/Quasar 프로젝트와 같은 깊은 바이트 코드 재 작성 또는 일부 비표준 JVM 기능을 포함합니다. 그 두 가지 옵션 모두 local.block 변환을 구현할 때 훨씬 간단하게 (그리고 훨씬 더 간단하게 추론 할 수 있기를 바랍니다) local go 블록 변환을 위해 core.async를 만드는 것을 배제했습니다.