首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何编写clojure宏以简化vertx事件总线通信

如何编写clojure宏以简化vertx事件总线通信
EN

Stack Overflow用户
提问于 2015-02-27 21:02:54
回答 1查看 125关注 0票数 0

您好。我正在使用vertx,它非常有趣,但是对于事件总线通信,它需要大量的样板,甚至最糟糕的是,如果我需要更改某个函数名,我需要在4或5个地方更改它。

只需知道,我正在使用一个抽象来将vertx回调转换为channels..like

代码语言:javascript
复制
;;helper
(defn send [add msg]
   (let [ch (chan 1)]
      (eb/send add msg #(put! ch %))))

;;I wrap the event bus sender in a function for make a bit cleaner the code
(defn eb-get-cached-view [name id]
   (send "render:get-cached-view" [name id])) ;;return chan[response]

(eb-get-cached-view "something" "here");;and finally I use it

;;in other verticle, I write the funcion
(defn get-cached-view [name id]
   (...))

;;and enable an event bus listener pointing to that function
;; basically I receive a vector, pass it to my function, which return a channel, then I reply to the message with the response
(eb/on-message "render:get-cache-view" #(go (eb/reply (<! (apply get-cached-view %)))))

正如您所看到的,这是很多样板,而且我担心每次更改函数名时,我都会错过在某个点更改它,而且我的代码会失败,我遵循使用我的命名空间的惯例的on消息参数后面跟着":“和函数名。

我在想比这更好的事情

代码语言:javascript
复制
(defbus blah
        [name]
         (str "hi! " name))

这个宏构建函数blah,并为具有“呈现”命名空间的消息创建总线监听器(,我可以访问宏中的命名空间吗?是好方法吗?)

代码语言:javascript
复制
(eb/on-message "namespace:blah" #(go (eb/reply (<!(apply get-cached-view %))))) ;;apply is necessary because the messages are received inside a vctor

以及用于发送消息的宏。

代码语言:javascript
复制
(<eb namespace:blah "john Smith") ;; could be a key like :namespace:blah too

也不愿翻译成这样

代码语言:javascript
复制
(defn namespace:blah [message]
   (let [ch (chan 1)]
      (eb/send "namespace:blah" message #(put! ch %)))) 

(namespace:blah "john Smith")

使用这些宏,我可以避免模板,更改回调以实现承诺,或者避免函数名称中的不一致。

这是个好方法吗?写这些宏是可能的,还是我忽略了某个点?.我对clojure有点陌生,我不知道它是否有可能,为什么它还不存在.

我很感激对我的代码的任何帮助或更正(我背诵了这段代码)

-“编辑1----------------------------------------------------------”

我写了这个宏(多亏了亚瑟).它比最后的宏简单一些,只用于演示

代码语言:javascript
复制
(defmacro defbus [bus-name args code]
   `(let [fun# (fn ~args ~code)]
       (println (str *ns* ":" ~bus-name))
       (eb/on-message (str *ns* ":" ~bus-name) (fn [arg#] (apply fun# arg#)))))

我认为,当我尝试使用它时,宏扩展是相当well...but的。

代码语言:javascript
复制
(defbus blah [a b] (str "just " a " " b))

java.lang.RuntimeException: Unable to resolve symbol: blah in this context

似乎比我可以直接使用blah,但是一个simbol或string...Am,我遗漏了什么?(我是一个使用宏的新手,所有的例子都与我所需要的非常不同)谢谢!

EN

回答 1

Stack Overflow用户

发布于 2015-02-27 22:22:57

您可以在名称*ns*的任何地方访问命名空间表单--在这种情况下,如果宏使用正在调用的名称空间定义事件总线,而不是使用定义助手函数或宏的名称空间,则会非常方便。

代码语言:javascript
复制
user> (defmacro defbus [bus-name]
        `(eb/on-message (str *ns* ":" ~bus-name) :dostuff))
#'user/defbus

user> (macroexpand-1 '(defbus foo))
(eb/on-message (clojure.core/str clojure.core/*ns* ":" foo) :dostuff)

这个宏将返回调用on消息的代码,然后在调用者名称空间中计算它,其中ns被绑定到该名称空间,我假设这就是您想要的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28774203

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档