我是clojure的新手,我正在尝试使用clojure.contrib.strint来构建一个URL。例如,我可能会将其用于谷歌搜索:
(def search_base_url "http://www.google.com/search?hl=en&q=~{query}")
(defn search_url [search_term]
(let [query (.replaceAll search_term "\\s+" "+")]
(<< search_base_url)))
但这给了我编译错误:
error:java.lang.RuntimeException:java.lang.RuntimeException:java.lang.IllegalArgumentException:找不到匹配的方法:class clojure.lang.Symbol的indexOf。
我认为strint使用了indexOf几次,所以不知怎的,我没有给出&lt;&lt;似乎功能它想要什么。
我也尝试了(def search_base_url '(<< "http://myurl.com?~{params}"))
,但后来我无法弄清楚如何在let的上下文中评估该表单。我可以把字符串放在search_url函数中,但这感觉不如我,我希望这个答案可以帮助我更好地理解clojure。
由于
答案 0 :(得分:1)
问题是,“&lt;&lt;&lt;&lt;宏需要一个字符串,而不是评估为字符串的东西。也就是说,它试图在名为“search_base_url”的符号上调用.indexOf,而不是在其值上调用。
所以解决这个问题的一种方法是:
(defn search-url [search-term]
(let [query (.replaceAll search-term "\\s+" "+")]
(<< "http://www.google.com/search?hl=en&q=~{query}")))
答案 1 :(得分:0)
我查看了<<
on github的源代码......我无法按照您想要的方式工作。
BUT
如果你像这样重写宏:
(defmacro <<<
[string]
`(apply str (map #(eval %) (interpolate ~string))))
然后
(def query "queryitem")
(def basesearch "http://www.google.com/search?hl=en&q=~{query}")
(<<< basesearch)
将返回
"http://www.google.com/search?hl=en&q=queryitem"
这是你想要的。 原因是:
(interpolate basesearch)
返回一个不执行序列评估的lazy-seq:
("http://www.google.com/search?hl=en&q=" query "")
永远不会在query
宏中评估<<
符号,并按原样返回。
由于silent-read
和interpolate
是私有的,您可以使用一些复制粘贴,但最终用法非常酷。