2012-08-28 109 views
2

我正在学习clojure。我的问题是可以在( - >)里面使用(case)。 例如,我想是这样的(这个代码不工作):切换箭头运算符

(defn eval-xpath [document xpath return-type] 
     (-> (XPathFactory/newInstance) 
     .newXPath 
     (.compile xpath) 
     (case return-type 
      :node-list (.evaluate document XPathConstants/NODESET) 
      :node (.evaluate document XPathConstants/NODE) 
      :number (.evaluate document XPathConstants/NUMBER) 
     ) 
    )) 

还是会更好地使用多方法呢?什么是正确的clojure方式呢?

谢谢。

回答

4

箭头宏( - >)只是重写其参数,以便将第n个窗体的值作为第n + 1个窗体的第一个参数插入。什么你写等同于:

(case 
    (.compile 
    (.newXPath (XPathFactory/newInstance)) 
    xpath) 
    return-type 
    :node-list (.evaluate document XPathConstants/NODESET) 
    :node (.evaluate document XPathConstants/NODE) 
    :number (.evaluate document XPathConstants/NUMBER) 

在一般情况下,你可以选择的三种形式之一使用let是你的尾巴形式的时间提前,然后跟帖说在穿线宏的结尾。像这样:

(defn eval-xpath [document xpath return-type] 
    (let [evaluator (case return-type 
        :node-list #(.evaluate % document XPathConstants/NODESET) 
        :node #(.evaluate % document XPathConstants/NODE) 
        :number #(.evaluate % document XPathConstants/NUMBER))] 
    (-> (XPathFactory/newInstance) 
     .newXPath 
     (.compile xpath) 
     (evaluator)))) 

但是,你真正想要做的是将关键字映射到XPathConstants上的常量。这可以通过地图来完成。考虑以下内容:

(defn eval-xpath [document xpath return-type] 
    (let [constants-mapping {:node-list XPathConstants/NODESET 
          :node XPathConstants/NODE 
          :number XPathConstants/NUMBER}] 
    (-> (XPathFactory/newInstance) 
     .newXPath 
     (.compile xpath) 
     (.evaluate document (constants-mapping return-type))))) 

您有关键字到常量的映射,所以使用Clojure的数据结构来表示它。此外,线程宏的真正价值在于帮助您编译xpath。不要害怕给你使用本地范围名称的数据来帮助你跟踪你正在做的事情。它还可以帮助您避免尝试将事情拧入真正不适合的线程宏。