Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 宏中符号分辨率的正确处理_Clojure - Fatal编程技术网

Clojure 宏中符号分辨率的正确处理

Clojure 宏中符号分辨率的正确处理,clojure,Clojure,假设我想制作一个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))

假设我想制作一个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"
在将函数传递给
str
之前,可以在
x
上调用
eval
函数,但在
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
绑定:

user=> (let [a 1 b (foo a)] b)
java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:153)
所以我在这里真的不知所措。似乎解决一个问题会破坏另一个问题。是否有更好、更简单的方法制作此宏,使其在以下情况下工作:

  • 中让
    绑定
  • 使用
    (条形)
  • 用符号

另外,如果有人想知道我为什么要这么做,我正在为雅虎的YQL服务开发一个DSL,我希望能够做类似于
(选择(表:t)…
)的事情,但我需要能够传递符号以及文字。

我相信这应该可以

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

我想我并不认为语法只引用一部分表达式,但似乎是这样做的。谢谢