【问题标题】:how write a clojure macro for simplify the vertx eventbus communication如何编写 clojure 宏来简化 vertx eventbus 通信
【发布时间】:2015-02-27 21:02:54
【问题描述】:

美好的一天..我正在使用 vertx,它非常令人愉快,但对于事件总线通信,它需要大量样板文件,甚至最糟糕的是,如果我需要更改某些函数名称,我需要在 4 或 5 个不同的地方更改它..

只知道,我正在使用抽象来将顶点回调转换为通道..就像这样

;;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 %)))))

正如您所看到的那样,它有很多样板文件,而且我担心每次更改函数名称时我都可能会错过在某些时候更改它并且我的代码失败,消息上的参数我遵循使用我的约定命名空间后跟“:”和函数名

我在想这样的东西可能会更好

(defbus blah
        [name]
         (str "hi! " name))

此宏构建函数 blah 并为带有“render”命名空间的消息创建总线侦听器(我可以访问宏内的命名空间吗?是个好方法吗?

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

以及发送消息的宏

(<eb namespace:blah "john Smith") ;; could be a key like :namespace:blah too

比翻译成这样的东西

(defn namespace:blah [message]
   (let [ch (chan 1)]
      (eb/send "namespace:blah" message #(put! ch %)))) 

(namespace:blah "john Smith")

使用这些宏,我会避免样板,更改 promise 的回调或避免函数名称不一致...

这是一个好方法吗?有可能写这些宏还是我忽略了一些点?..我是clojure的新手,我不知道它是否可能以及为什么它还不存在......

感谢任何帮助,也许可以更正我的代码(我用心编写代码)

---------编辑 1------------------------------------ ----------------------

我写了这个宏(感谢 Arthur)...它比仅用于演示的最终宏要简单一些

(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#)))))

我认为宏扩展非常好......但是当我尝试使用它时,我得到了

(defbus blah [a b] (str "just " a " " b))

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

似乎我可以直接使用 blah 但一个符号或字符串...我错过了什么吗? (我是一个使用宏的新手,所有示例都与我需要的非常不同)谢谢!...

【问题讨论】:

    标签: clojure macros


    【解决方案1】:

    您可以在名称*ns* 下的任何位置访问名称空间表单。在这种情况下,如果您的宏使用正在调用的名称空间而不是您定义帮助函数的名称空间定义事件总线,或者宏。

    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-message 的代码,然后将在调用者命名空间中进行评估,其中 ns 绑定到 that 命名空间,我' m 假设是你想要的。

    【讨论】:

    • 谢谢亚瑟..如果我使用这个宏,我需要使用符号或字符串作为总线名称,例如 (defbus :blah [a b](str a b)) 或者我可以使用 blah直接???...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多