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
创建使用字符串调用java函数的Clojure宏_Clojure_Macros - Fatal编程技术网

创建使用字符串调用java函数的Clojure宏

创建使用字符串调用java函数的Clojure宏,clojure,macros,Clojure,Macros,因此,我正在尝试制作一个Clojure宏,它可以方便地利用构建器模式与Java类进行互操作 这是我到目前为止试过的 (defmacro test-macro [] (list (symbol ".queryParam") (-> (ClientBuilder/newClient) (.target "https://www.test.com")) "key1" (object-array ["val1"]))) 扩展到下面 (.

因此,我正在尝试制作一个Clojure宏,它可以方便地利用构建器模式与Java类进行互操作

这是我到目前为止试过的

(defmacro test-macro
  []
  (list
   (symbol ".queryParam")
   (-> (ClientBuilder/newClient)
       (.target "https://www.test.com"))
   "key1"   
   (object-array ["val1"])))
扩展到下面

(. 
  #object[org.glassfish.jersey.client.JerseyWebTarget 0x107a5073 "org.glassfish.jersey.client.JerseyWebTarget@107a5073"] 
  queryParam 
  "key1" 
  #object["[Ljava.lang.Object;" 0x16751ba2 "[Ljava.lang.Object;@16751ba2"])
预期的结果是:

 (.queryParam
  #object[org.glassfish.jersey.client.JerseyWebTarget 0x107a5073 "org.glassfish.jersey.client.JerseyWebTarget@107a5073"]       
  "key1" 
  #object["[Ljava.lang.Object;" 0x16751ba2 "[Ljava.lang.Object;@16751ba2"]) 
我猜
导致了一些东西被评估和移动?在这种情况下,解决办法是引用它。但是如何引用计算表达式的结果呢

我的目标是将映射转换为代码,通过将映射键作为要调用的函数,将值作为传递到Java函数的参数来构建对象


我了解如何使用线程和do to宏,但我正在尝试使请求构建函数数据驱动。我希望能够接受一个映射,其中键为“queryParam”,值为参数。通过这样做,我可以充分利用java类函数的全部功能,只需自己编写一个函数,并且有足够的1对1映射,我不相信其他人会觉得这很神奇

(def test-map {"target" ["https://www.test.com"]
               "path" ["qa" "rest/service"] 
               "queryParam" [["key1" (object-array ["val1"])]
                              ["key2" (object-array ["val21" "val22" "val23"])]] })

 (-> (ClientBuilder/newClient)
     (.target "https://www.test.com")
     (.path "qa")
     (.path "rest/service")
     (.queryParam "key1" (object-array ["val1"]))
     (.queryParam "key2" (object-array ["val21" "val22" "val23"])))

从您的问题来看,还不清楚是否必须使用map作为构建器数据结构。我建议使用threading宏直接处理实现构建器模式的Java类:

(-> (ClientBuilder.)
      (.forEndpoint "http://example.com")
      (.withQueryParam "key1" "value1")
      (.build))
对于未实现生成器模式的类及其方法返回
void
(例如setter方法),可以使用
doto
宏:

(doto (Client.)
  (.setEndpoint "http://example.com")
  (.setQueryParam "key1" "value1"))
使用映射对Java方法调用进行编码来实现宏是可能的,但很尴尬。您必须将每个方法参数保持在一个序列中(映射值中),以便能够调用具有多个参数的方法,或者具有存储单参数方法参数、处理varargs、,使用map来指定方法调用并不能保证调用顺序等。它会给代码增加很多复杂性和魔力

这是您可以实现它的方式:

(defmacro builder [b m]
  (let [method-calls
        (map (fn [[k v]] `(. (~(symbol k) ~@v))) m)]
    `(-> ~b
         ~@method-calls))) 

(macroexpand-1
  '(builder (StringBuilder.) {"append" ["a"]})) 
;; => (clojure.core/-> (StringBuilder.) (. (append "a"))) 

(str
  (builder (StringBuilder.) {"append" ["a"] })) 
;; => "a"