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
Macros Clojure-一个宏中的let';行不通_Macros_Clojure_Let - Fatal编程技术网

Macros Clojure-一个宏中的let';行不通

Macros Clojure-一个宏中的let';行不通,macros,clojure,let,Macros,Clojure,Let,我创建了一个宏,该宏创建了一个命名的调度程序,其中包含3个关联函数获取调度程序,设置调度程序和调用调度程序,以与调度程序一起工作(它们获取调度函数,添加一个或调用一个)。一切都很好!但是,现在我想自动创建相关的函数名,因此我将把宏的所有这些内部内容放入一个let,它定义了简单的构造函数。请注意,在下面的代码中,只有get-函数的名称是使用该自动化构造的。set-和call-的名字创建仍然有手动的味道 (defmacro create-dispatcher [name] ;creates a

我创建了一个宏,该宏创建了一个命名的
调度程序
,其中包含3个关联函数
获取调度程序
设置调度程序
调用调度程序
,以与调度程序一起工作(它们获取调度函数,添加一个或调用一个)。一切都很好!但是,现在我想自动创建相关的函数名,因此我将把宏的所有这些内部内容放入一个
let
,它定义了简单的构造函数。请注意,在下面的代码中,只有
get-
函数的名称是使用该自动化构造的。
set-
call-
的名字创建仍然有手动的味道

(defmacro create-dispatcher [name]
  ;creates a set of dispatching functions tagged

  `(do
    ;define dispatcher
    (def ~(symbol name) ~(atom {}))

    (let
      [name-w-prefix (fn [x] (~(symbol (str x "-" name))))]
        ; -- define getter
        (defn (name-w-prefix "get")
          "get-dispatcher [tag]: get a dispatcher fn by tag"
          (~'[] (println "no tag is provided for '" ~(str name) "' dispatcher"))
          (~'[tag]
            (do
              (println "dispatcher '" ~(str name) "' called with '" ~'tag "' tag")
              ; return the tagged dispatcher
              ( (keyword ~'tag) @~(symbol name) )))

        )
        ; -- define caller
        (defn ~(symbol (str "call-" name))
          "get-dispatcher [tag & args]: call a dispatcher fn by tag and apply to the args"
          ~'[tag & args]
          (apply (~(symbol (str "get-" name)) ~'tag) ~'args)
          )
        ; -- define setter
        (defn ~(symbol (str "set-" name))
          ~'[tag fn]
          "add-dispatcher [tag fn]: add a dispatcher fn associated with the tag"
          (swap! ~(symbol name) assoc (keyword ~'tag) ~'fn)
          )
     )

    ; -- report
    (println "created dispatcher set for '" ~(str name) "' ok!")
    ))
然而,有一个问题。
let
语句绑定中的
name-w-prefix
会导致错误。我怎样才能解决这个问题


(由于我是一名新手,这几乎是我在Clojure中写的第一件事,因此欢迎您提供任何改进建议)

宏中的所有符号都在当前名称空间中解析,并期望计算为变量。您可以引用
name-w-prefix
符号,但这可能会与在宏扩展期间传递给宏的符号发生冲突。因此,Clojure提供了一种特殊的语法,用于生成符号的语法引用形式——只需在符号末尾添加一个
#
,Clojure就会将其视为一个引用的、自动生成的符号。因此,在本例中,将出现的
name-w-prefix
替换为
name-w-prefix#
,您应该可以开始了

退一步,看看您的总体目标是什么,我认为您应该将
name-w-prefix
定义移到语法引号之外,然后使用语法转义来调用它。否则,您将得到更多错误,因为
defn
需要符号,因此一旦展开宏,必须生成一个
defn
表单,该表单的第二项为符号。大致如下:

(defmacro create-dispatcher [name]
  (let [name-w-prefix #(symbol (str % "-" name))]
    `(do
       (def ~(symbol name) (atom {}))
       (defn ~(name-w-prefix "get")
         ([] (println "no tag provided"))
         ([tag#] (println "called with tag" tag#))))))

请注意,我已根据上面所说的内容将
~'[tag]
更改为
[tag#]
,位于
defn
正文中。

谢谢您的解释!我不知道。。但我这样做了,现在它抱怨函数定义中的
x
符号..请参见编辑。我想你对语法引号的内部和外部有点困惑。是的,看起来像!例如,我认为因为它都是关于AST的,所以我可以像
~(expr)
一样从函数返回,它将替换调用者,就像在这里显式编写一样。但是看起来,
~
的工作方式不同。。。谢谢你的
~'
->
#
建议!现在我已经修复了所有宏,它工作得很好!