gpt4 book ai didi

clojure - 在宏中正确处理符号解析

转载 作者:行者123 更新时间:2023-12-04 20:20:41 25 4
gpt4 key购买 nike

假设我想做一个 Clojure 宏来执行以下操作:

If x is a list calling the function "bar"
return :foobar
else
return x as a string

但是, bar没有定义;相反,它只在宏内部使用,如下所示:
(foo (bar))
:foobar

(foo 1)
"1"

可以做这样的事情:
(defmacro foo [x] 
(if (and (coll? x) (= (first x) 'bar))
:foobar
(str x)))

这适用于 (bar)大小写,以及文字。但是,符号不能按预期工作,给出符号名称而不是其关联值:
user=> (def y 2)
#'user/y
user=> (foo y)
"y"

可以调用 eval x上的功能在传递给 str 之前, 但是在使用 let 中的函数时会导致问题:
user=> (let [a 3 b (foo a)] b)
java.lang.UnsupportedOperationException: Can't eval locals (NO_SOURCE_FILE:89)

据推测,问题与符号解析有关,所以也许我们尝试使用语法引用来解决问题:
(defmacro foo [x] 
`(if (and (coll? '~x) (= (first '~x) '~'bar))
:foobar
(str ~x)))

现在,问题在于 (foo (bar)) ,因为这会将 else 子句扩展为 (clojure.core/str (bar)) ,引发异常,如 bar没有定义。然后我尝试用 eval 做一些恶作剧:
(defmacro foo [x] 
`(if (and (coll? '~x) (= (first '~x) '~'bar))
:foobar
(eval '(str ~x))))

但这不适用于 let再次绑定(bind):
user=> (let [a 1 b (foo a)] b)
java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:153)

所以我在这里真的很茫然。似乎解决一个问题会破坏另一个问题。有没有更好、更简单的方法来制作这个宏,使其在以下情况下工作:
  • let绑定(bind)
  • (bar)
  • 带符号

  • 附言如果有人对我为什么要这样做感到好奇,我正在为 Yahoo 的 YQL 服务开发 DSL,我希望能够做 (select (table :t) ...) 之类的事情。 ,但我需要能够传递符号以及文字。

    最佳答案

    我相信这应该有效。

    (defmacro foo [x]
    (if (and (coll? x) (= (first x) 'bar))
    :foobar
    `(str ~x)))

    关于clojure - 在宏中正确处理符号解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6904124/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com