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
调用特殊表单“set!”在clojure宏中_Clojure_Macros - Fatal编程技术网

调用特殊表单“set!”在clojure宏中

调用特殊表单“set!”在clojure宏中,clojure,macros,Clojure,Macros,给定Java实例obj和成员名(字符串)“Foo”,以及映射conf,我试图生成如下所示的Clojure代码: (如果(获取conf“Foo”) (设置!(.Foo obj)(获取配置“Foo”) (obj) 另外,如果我知道“SomeEnum”是一个Java enum名称,代码如下: 以下是我的想法: (defmacro set-java [obj conf obj-name] `(if (get ~conf ~obj-name) (set! (. ~obj ~(symbol

给定Java实例
obj
和成员名(字符串)
“Foo”
,以及映射
conf
,我试图生成如下所示的Clojure代码:

(如果(获取conf“Foo”)
(设置!(.Foo obj)(获取配置“Foo”)
(obj)
另外,如果我知道
“SomeEnum”
是一个Java enum名称,代码如下:

以下是我的想法:

(defmacro set-java [obj conf obj-name]
  `(if (get ~conf ~obj-name)
     (set! (. ~obj ~(symbol obj-name)) (get ~conf ~obj-name))
     ~obj))

(defn lowercase-first [s]
  (apply str (Character/toLowerCase (first s)) (rest s)))

(defmacro set-java-enum [obj conf obj-name]
  `(if (get ~conf ~obj-name)
     (set! (. ~obj ~(symbol (lowercase-first obj-name)))
           (Enum/valueOf ~(symbol obj-name) (get ~conf ~obj-name)))
     ~obj))
使用
macroexpand
进行测试似乎给出了正确的结果,但在尝试之后:

我收到了一个奇怪的无休止的反射警告循环

---编辑---

在与之斗争了很长一段时间后,我放弃了线程化(
->
),并以以下内容结束:

(defmacro set-java [obj conf obj-name]
  `(when (get ~conf ~obj-name)
     (set! (. ~obj ~(symbol obj-name)) (get ~conf ~obj-name))))

(defn lowercase-first [s]
  (apply str (Character/toLowerCase ^Character (first s)) (rest s)))

(defmacro set-java-enum [obj conf obj-name]
  `(when (get ~conf ~obj-name)
     (set! (. ~obj ~(symbol (lowercase-first obj-name)))
           (Enum/valueOf ~(symbol obj-name) (get ~conf ~obj-name)))))

(defn map->write-policy [conf]
  (let [wp (WritePolicy. (map->policy conf))]
    (set-java-enum wp conf "CommitLevel")
    (set-java wp conf "durableDelete")
    ;; more non threaded object manipulation
    wp))

因此,我仍然不确定反射警告无止境循环是关于什么的,但这也很有希望,并且可以进一步改进。

我认为这是由于您在每个宏中多次插入
~obj
。您的“循环”实际上是无止境的,还是只有~128或~256步长

在任何情况下,该特定问题的解决方案(无论它是否是您描述的问题的根本原因)是将表单包装在
(让[obj#~obj]…)
中,然后参考下面的
obj
,因此该参数只插入一次


您也可以(应该!)使用
conf
obj name
来实现这一点,但至少在您提供的使用代码中,它们可能不会主动导致问题。

(.foo X)
是一个方法调用。您可能希望实例字段访问
(-foo X)
。@akond sharp eye!(有文档记录)我修复并编辑了这个问题,但它仍然会进入循环。另一个错误是,
set!
本质上是一种特殊形式,不会返回结果,只会导致副作用。因此,在这种情况下,
~obj
也应该返回(为了在以后遍历表达式。在这种情况下,我认为您希望
doto
而不是
->
(defn ^Policy map->policy [conf]
  (-> (Policy.)
      (set-java-enum conf "CommitLevel")
      (set-java conf "durableDelete")
      (set-java conf "expiration")
      (set-java conf "generation")
      (set-java-enum conf "GenerationPolicy")
      (set-java-enum conf "RecordExistsAction")
      (set-java conf "respondAllOps")))
(defmacro set-java [obj conf obj-name]
  `(when (get ~conf ~obj-name)
     (set! (. ~obj ~(symbol obj-name)) (get ~conf ~obj-name))))

(defn lowercase-first [s]
  (apply str (Character/toLowerCase ^Character (first s)) (rest s)))

(defmacro set-java-enum [obj conf obj-name]
  `(when (get ~conf ~obj-name)
     (set! (. ~obj ~(symbol (lowercase-first obj-name)))
           (Enum/valueOf ~(symbol obj-name) (get ~conf ~obj-name)))))

(defn map->write-policy [conf]
  (let [wp (WritePolicy. (map->policy conf))]
    (set-java-enum wp conf "CommitLevel")
    (set-java wp conf "durableDelete")
    ;; more non threaded object manipulation
    wp))