构建协议 Clojure 宏

发布于 2024-11-16 04:36:55 字数 1555 浏览 1 评论 0原文

作为我的上一个问题的后续问题,我正在尝试编写一个构建 defprotocol: 的宏,

(build-protocol AProtocol
  [(a-method [this]) (b-method [this that])]
  (map (fn [name] `(~(symbol (str name "-method")) [~'this ~'that ~'the-other]))
    ["foo" "bar" "baz"])
  (map (fn [name] `(~(symbol (str name "-method")) [~'_]))
    ["hello" "goodbye"]))

应该扩展为

(defprotocol AProtocol
  (a-method [this])
  (b-method [this that])
  (foo-method [this that the-other])
  (bar-method [this that the-other])
  (baz-method [this that the-other])
  (hello-fn [_])
  (goodbye-fn [_]))

My attempts:

(defmacro build-protocol [name simple & complex]
  `(defprotocol ~name ~@simple
     ~@(loop [complex complex ret []]
         (if (seq complex)
           (recur (rest complex) (into ret (eval (first complex))))
           ret))))

并扩展 (macroexpand-1 '(...)):

(clojure.core/defprotocol AProtocol
  (a-method [this])
  (b-method [this that])
  (foo-method [this that the-other])
  (bar-method [this that the-other])
  (baz-method [this that the-other])
  (hello-method [_])
  (goodbye-method [_]))

我不是真的很高兴关于评估。另外,map 表达式非常难看。有更好的办法吗?欢迎任何和所有评论。

一旦我开始工作,我将为 (build-reify ...) 做一个类似的宏。我正在编写一个相当大的 Swing 应用程序,并且有几个组件(JButtons、JCheckBoxes 等),它们具有几乎相同的方法签名和操作。

As a follow-up to my previous question, I am trying to write a macro that builds a defprotocol:

(build-protocol AProtocol
  [(a-method [this]) (b-method [this that])]
  (map (fn [name] `(~(symbol (str name "-method")) [~'this ~'that ~'the-other]))
    ["foo" "bar" "baz"])
  (map (fn [name] `(~(symbol (str name "-method")) [~'_]))
    ["hello" "goodbye"]))

should expand to

(defprotocol AProtocol
  (a-method [this])
  (b-method [this that])
  (foo-method [this that the-other])
  (bar-method [this that the-other])
  (baz-method [this that the-other])
  (hello-fn [_])
  (goodbye-fn [_]))

My attempt:

(defmacro build-protocol [name simple & complex]
  `(defprotocol ~name ~@simple
     ~@(loop [complex complex ret []]
         (if (seq complex)
           (recur (rest complex) (into ret (eval (first complex))))
           ret))))

and expansion (macroexpand-1 '(...)):

(clojure.core/defprotocol AProtocol
  (a-method [this])
  (b-method [this that])
  (foo-method [this that the-other])
  (bar-method [this that the-other])
  (baz-method [this that the-other])
  (hello-method [_])
  (goodbye-method [_]))

I'm not really happy about the eval. Also, the map expressions are pretty ugly. Is there a better way? Any and all comments welcome.

Once I get this working, I'm going to do a similar macro for (build-reify ...). I'm writing a rather large Swing application and have several components (JButtons, JCheckBoxes, etc.) that have almost identical method signatures and actions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

×眷恋的温暖 2024-11-23 04:36:55

我认为你这样做是颠倒了。首先指定“-method”内容,将其包装在某种容器中,以便构建协议知道什么是什么,并让它在宏内执行映射。例如:

(build-protocol AProtocol
  {[this that whatever] [foo bar baz],
   [_] [hello goodbye]}
  ; a-method and b-method...
)

I think you're doing it upside down. Specify the "-method" stuff first, wrapped in a container of some kind so build-protocol knows what's what, and let it do the map inside the macro. e.g:

(build-protocol AProtocol
  {[this that whatever] [foo bar baz],
   [_] [hello goodbye]}
  ; a-method and b-method...
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文