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中计算传递给def的符号_Clojure_Macros - Fatal编程技术网

在Clojure中计算传递给def的符号

在Clojure中计算传递给def的符号,clojure,macros,Clojure,Macros,我通过Clojure为勇敢和真诚的人工作。在有关宏的章节中,有以下练习: 编写一个宏,使用一个宏调用定义任意数量的属性检索函数。你可以这样称呼它: (defattrs c-int :intelligence c-str :strength c-dex :dexterity) 这些函数所做的是从映射中检索值。例如:(定义字符{:name“Travis”,:intelligence 20,:strength 23,:dextrity 13}) (c-int字

我通过Clojure为勇敢和真诚的人工作。在有关宏的章节中,有以下练习:

编写一个宏,使用一个宏调用定义任意数量的属性检索函数。你可以这样称呼它:

(defattrs c-int :intelligence
          c-str :strength
          c-dex :dexterity)
这些函数所做的是从映射中检索值。例如:
(定义字符{:name“Travis”,:intelligence 20,:strength 23,:dextrity 13})

(c-int字符)
的结果将是
20
当然,这样的函数可以很容易地定义为
(def c-int#(:intelligence%))

这就是我对这个问题的解决方案:

(defmacro defattrs
    [& attributes]
    `(let [attribute-pairs# (partition 2 (quote ~attributes))]
          (map (fn [[function-name# attribute-key#]]
                   (def function-name# #(attribute-key# %)))
           attribute-pairs#)))
我遇到的问题是,
def
使用生成的符号名而不是它解析的名称来定义函数(事后看来,考虑到
def
的使用,这是有意义的)。我尝试将表达式与定义函数一起使用,例如:

(let [x ['c-int :intelligence]]
  (def (first x) #((second x) %)))
已导致此错误:
CompilerException java.lang.RuntimeException:def的第一个参数必须是符号,compile:(/tmp/form-init566472754022288850.clj:2:1)


关于如何实现这一点,您有什么想法吗?

您已经找到了后引号和波浪线的用例。试试这个:

(let [x ['c-int :intelligence]]
  (eval `(def ~(first x) #(~(second x) %))))

(def character {:name "Travis", :intelligence 20, :strength 23, :dexterity 13})

(c-int character) => 20

后引号与单引号类似,因为它将下一个表单转换为列表、符号等的数据结构。不同之处在于,该数据结构旨在用作模板,其中可以使用瓷砖替换内部位。很酷的一点是,tilde不只是替代项,而是适用于可以是任意Clojure表达式的实时代码。

您已经找到了后引号和tilde的用例。试试这个:

(let [x ['c-int :intelligence]]
  (eval `(def ~(first x) #(~(second x) %))))

(def character {:name "Travis", :intelligence 20, :strength 23, :dexterity 13})

(c-int character) => 20

后引号与单引号类似,因为它将下一个表单转换为列表、符号等的数据结构。不同之处在于,该数据结构旨在用作模板,其中可以使用瓷砖替换内部位。很酷的一点是,tilde不仅仅替代项目,还适用于可以是任意Clojure表达式的实时代码。

您可以对
属性执行一些普通操作,这些操作不需要作为表单生成:

  • 将属性拆分为属性对;及
  • 定义为每对生成
    def
    表单的函数
将以上内容应用到您的代码中,我们得到

(defmacro defattrs [& attributes]
  (let [attribute-pairs (partition 2 attributes)]
     (map (fn [[function-name attribute-key]]
            `(def ~function-name #(~attribute-key %)))
          attribute-pairs)))
  • 后报价的范围仅限于我们希望生成的
    def
  • 函数的
    函数名
    属性键
    参数的值插入到
    def
    表单中
还有一个问题

  • map
    的结果是一系列
    def
    表单
  • 第一个将被解释为 适用于其他人
解决方案是将
cons
a
do
放在序列的前面:

(defmacro defattrs [& attributes]
  (let [attribute-pairs (partition 2 attributes)]
    (cons 'do
          (map (fn [[function-name attribute-key]]
                 `(def ~function-name ~attribute-key))
               attribute-pairs))))
我还在后面引用的表单中将
#(~attribute key%)
缩写为等价的
~attribute key

让我们看看扩展是什么样子的:

(macroexpand-1 '(defattrs dooby :brrr))
;(do (def dooby :brrr))
看起来不错。让我们试试看

(defattrs gosh :brrr)
(gosh {:brrr 777})
;777

它起作用了

对于
属性
参数,有一些普通操作不需要生成表单:

  • 将属性拆分为属性对;及
  • 定义为每对生成
    def
    表单的函数
将以上内容应用到您的代码中,我们得到

(defmacro defattrs [& attributes]
  (let [attribute-pairs (partition 2 attributes)]
     (map (fn [[function-name attribute-key]]
            `(def ~function-name #(~attribute-key %)))
          attribute-pairs)))
  • 后报价的范围仅限于我们希望生成的
    def
  • 函数的
    函数名
    属性键
    参数的值插入到
    def
    表单中
还有一个问题

  • map
    的结果是一系列
    def
    表单
  • 第一个将被解释为 适用于其他人
解决方案是将
cons
a
do
放在序列的前面:

(defmacro defattrs [& attributes]
  (let [attribute-pairs (partition 2 attributes)]
    (cons 'do
          (map (fn [[function-name attribute-key]]
                 `(def ~function-name ~attribute-key))
               attribute-pairs))))
我还在后面引用的表单中将
#(~attribute key%)
缩写为等价的
~attribute key

让我们看看扩展是什么样子的:

(macroexpand-1 '(defattrs dooby :brrr))
;(do (def dooby :brrr))
看起来不错。让我们试试看

(defattrs gosh :brrr)
(gosh {:brrr 777})
;777
它起作用了