2014-04-15 3 views
1

나는 web-page에있는 RabbitMQ 튜토리얼을 실행 중이고 좀 더 일반적이고 구성하기 쉽도록 예제를 리펙토링하려고 노력 중이다. 나는 두 번째 "blabbr"예에 머물러있다. 내가 매크로하고 다음과 같이 함수에서 호출 수 있다고 생각RabbitMQ 패닝을위한 Clojure 코드의 리팩토링 리팩토링

(defn -main 
    [& args] 
    (let [conn (rmq/connect) 
     ch (lch/open conn) 
     ex "nba.scores" 
     users ["joe" "aaron" "bob"]] 
    (le/declare ch ex "fanout" :durable false :auto-delete true) 
    (doseq [u users] 
     (start-consumer ch ex u)) 
    (lb/publish ch ex "" "BOS 101, NYK 89" :content-type "text/plain" :type "scores.update") 
    (lb/publish ch ex "" "ORL 85, ALT 88" :content-type "text/plain" :type "scores.update") 
    (Thread/sleep 2000) 
    (rmq/close ch) 
    (rmq/close conn))) 

: 여기에 내가 리팩토링하고 싶은 기능은 내가에서 자체적으로 wrap-publish 매크로를 테스트

(defmacro wrap-publish [default-exchange-name content mType data] 
    `(for [datum# data] 
    (lb/publish ch ex default-exchange-name datum# :content-type ~content :type ~mType))) 

(defn -main 
     [...] 
... 
(wrap-publish default-exchange-name content-type mType data) 
... 

REPL은, 그러나,이 오류가 발생합니다 :

java.lang.ClassCastException: clojure.lang.Var$Unbound cannot be cast to` com.novemberain.langohr.Channel basic.clj:89 langohr.basic/publish 

내 바르 결합하지 것이다가는 글로벌 뭔가가있는 것 같다,하지만 난 무엇인지 전혀 모른다. 나는 내 쫓아 낸 source-code을 쫓아 갔다. 거기서 막 다른 골목을 때렸다. 나는 단지 무엇을해야할지 모른다. 저는 비동기와 매크로의 세계로 아기 발을 들여다 보는 새로운 프로그래머입니다. 따라서 저의 목표를 성취하는 데 도움이 될만한 조언은 물론, 기본적인 접근 방식을 취하고 있는지를 알려주는 일반적인 통찰력을 제공합니다. langohr 의존성 [com.novemberain/langohr "2.9.0"]을 사용하고 있습니다. 당신이 당신의 매크로 정의의 일부 unquotes 누락처럼

답변

3

기록 된 매크로에 관해서는 것 같습니다. 그 라이브러리를 사용하지 않고 SSCCE을 제공하지 않았으므로 테스트하지 말라고 조언합니다.

당신 매크로 가능성이

(defmacro wrap-publish [default-exchange-name content mType data] 
    `(doseq [datum# ~data] 
    (lb/publish ~'ch ~'ex ~default-exchange-name datum# :content-type ~content :type ~mType))) 

참고 chex에 '~ 추가되고이 datadefault-exchange-name에 ~ 추가해야합니다. for에서 doseq으로 변경된 내용이 있으므로 for은 게으른 것입니다. 이 기호 chex를 포함하는 코드를

(macroexpand-1 '(wrap-publish "" "text/plain" "scores.update" ["BOS 101, NYK 89", "ORL 85, ALT 88"])) 
;=> (clojure.core/doseq [datum__1237__auto__ ["BOS 101, NYK 89" "ORL 85, ALT 88"]] 
;  (lb/publish ch ex "" datum__1237__auto__ :content-type "text/plain" :type "scores.update")) 

을 생산하기 때문에

당신이

... 
(let [... 
     ch ... 
     ex ... 
     ...] ; end let bindings 
... 
(wrap-publish "" "text/plain" "scores.update" ["BOS 101, NYK 89", "ORL 85, ALT 88"])) 
... 

처럼 사용하는 것입니다, 그들은 let 바인딩에 사용할 수 있어야합니다. 어드바이스에 관해서는

여기에 매크로를 기록 할 좋은 이유가 정말 없습니다

을 요청했다. 조언을 구하는 경우 Clojure를 사용하여 처음 6-12 개월 동안 매크로를 작성하지 마십시오. 기능적 프로그래밍 기술에 중점을 둡니다. 그 후에도 가능한 한 매크로를 작성하지 마십시오! 대신 자신의 매크로 (doseq 매크로 자체가) 작성 덤비는의

(doseq [d ["BOS 101, NYK 89" "ORL 85, ALT 88"]] 
    (lb/publish ch ex "" d :content-type "text/plain" :type "scores.update")) 

:이 매크로는 아마 당신이 작성한 코드해야 생산

코드입니다.

여러 장소에서 비슷한 작업을 수행해야하는 경우 기능을 정의하면됩니다. 반복 할 필요가 없거나 어휘 범위를 벗어나는 상황 (예 : chex)이있는 경우 클로저를 만듭니다.

+0

"... * 당신도 * 신경 쓰지 않아도 * * 또한 어휘 범위를 벗어날 필요가 없습니다 ..."? – Thumbnail

+0

설명과 매크로 수정에 감사드립니다. 그래도 ~ '구문을 조금 더 설명해 주시겠습니까? 나는 그것을 성공적으로 google 수 없었다. dosq은 매력처럼 일했습니다! SSCCE 지적했다. – kurofune

+1

@kurofune http://blog.8thlight.com/colin-jones/2012/05/22/quoting-without-confusion.html 도움이되었습니다. –