宏for可以支持循环
下面继续前面的xml的例子,演示如何用for遍历xml-seq返回的sequence.
user=> (for [x r] (println "^" x)) (^ {:tag :service, :attrs nil, :content [{:tag :mongodb, :attrs nil, :content [{:tag :uri, :attrs nil, :content [localhost]}]} {:tag :socket, :attrs nil, :content [{:tag :port_number, :attrs nil, :content [7777]} {:tag :login_timeout, :attrs nil, :content [200]} {:tag :check_timeout, :attrs nil, :content [200]}]}]} ^ {:tag :mongodb, :attrs nil, :content [{:tag :uri, :attrs nil, :content [localhost]}]} nil ^ {:tag :uri, :attrs nil, :content [localhost]} nil ^ localhost nil ^ {:tag :socket, :attrs nil, :content [{:tag :port_number, :attrs nil, :content [7777]} {:tag :login_timeout, :attrs nil, :content [200]} {:tag :check_timeout, :attrs nil, :content [200]}]} nil ^ {:tag :port_number, :attrs nil, :content [7777]} nil ^ 7777 nil ^ {:tag :login_timeout, :attrs nil, :content [200]} nil ^ 200 nil ^ {:tag :check_timeout, :attrs nil, :content [200]} nil ^ 200 nil nil)
每个sequence元素前打印一个^符号便于分辨。
加上条件过滤,比如只取:tag 为:mongodb的
user=> (for [x r :when (= :mongodb (:tag x))] x) ({:tag :mongodb, :attrs nil, :content [{:tag :uri, :attrs nil, :content ["localhost"]}]}) user=>
for 后面的方括号是一个vector,r是xml-seq返回的sequence,x是sequence中的元素,每次循环都自动获取下一个元素,:when(...)是条件判断语句。当when(...)返回true的时候就执行vector后面的表达式,因为这里仅仅是x,所以将这个符号条件的元素作为for的返回值。
:when 不会阻止循环提前结束,但是:while就不同了。
如果:while(...) 计算出结果为false,则循环立刻退出。
所以下面返回空list
user=> (for [x r :while (= :mongodb (:tag x))] x) ()
因为第一个元素的:tag值是:service,不等于:mongodb,因此循环停止。