그래서 Clojure go-block은 많은 이유로 함수 경계에서 변환을 중지하지만 가장 큰 것은 단순성입니다.
(go (lazy-seq (<! c)))
이런 식으로 컴파일 된 가져옵니다 :
이제
(go (clojure.lang.LazySeq. (fn [] (<! c))))
이의이 진짜 빨리 ... 무엇을해야이 복귀에 대해 생각하게 게으른 서열을 구성 할 때 가장 일반적으로 볼 수있다? 당신이 원했던 것이 c에서 가져온 값을 포함하고있는 lazy seq이지만, <!
은 함수의 나머지 코드를 콜백으로 변환 할 필요가 있지만, LazySeq은 함수가 동기 될 것으로 기대하고있다. 이 한계를 극복하는 방법은 없습니다.
그래서 macroexpand for
이 실제로 루프되지 않는다는 것을 알게 될 것입니다. 대신에 결국 lazy-seq
을 호출하는 코드 묶음으로 확장되므로 주차 ops가 본문 내부에서 작동하지 않습니다. doseq
(및 dotimes
)은 loop
/recur
에 의해 뒷받침되므로 완벽하게 정상적으로 작동합니다.
with-bindings
이 하나의 예가 될 수있는 몇 가지 다른 장소가 있습니다. 기본적으로 매크로가 core.async 파킹 작업을 중첩 된 함수에 집어 넣으면이 오류가 발생합니다.
내 제안은 가능한 한 간단하게 이동 블록의 몸을 유지하는 것입니다. 순수 함수를 작성한 다음 이동 블록 본문을 IO를 수행 할 위치로 처리하십시오.
------------ 기능의 경계에서 정지 번역에 의해 편집 -------------
,이 의미 : 이동 블록은 소요 몸체를 상태 머신으로 변환합니다. <!
>!
또는 alts!
(및 기타 몇 개)에 대한 각 호출은 블록 실행이 일시 중지 될 수있는 상태 시스템 전환으로 간주됩니다. 각 포인트에서 기계는 콜백으로 바뀌고 채널에 연결됩니다. 이 매크로가 fn
양식에 도달하면 번역이 중지됩니다. 따라서 코드 블록 내부의 함수가 아닌 이동 블록 안에서만 <!
에 전화를 걸 수 있습니다.
이것은 core.async의 마법의 일부입니다. go 매크로가 없다면, core.async 코드는 다른 langauges에서 callback-hell처럼 보일 것입니다.
"for"in clojure is not a loop - 목록 이해입니다. 이 점을 염두에두고''for'' 예제는'>에 영향을주는 부작용을 나타내는 관용적 인 방법이 아닙니다!'함수. 어쩌면 컴파일러 메시지가 개선되어야 할 수도 있지만 근본적인 문제는 이런 식으로''for ''를 사용하는 것이 감각을 갖지 못한다는 것입니다. ''doseq''는 완벽합니다. – sw1nn
>! 블록을 읽으면 다른 사람이 채널에서 읽을 때까지 기다립니다. 먼저 파트 읽기를 시도하거나 put을 사용하십시오! – edbond
@edbond 와우,이게 실제로 작동합니다 ..하지만 더 혼란 스럽습니다. Timothy Baldridge가 async/go가'async/go' 블록에서'fn'을 처리 할 수 없다고 말하지 않았습니까? – xudifsd