2016-04-08 70 views
3

下面是我編寫的一些代碼,使用clojure.core.match,它執行相當常見的編程任務。一個函數需要一些「命令」(或「對象」,「記錄」或任何你喜歡稱之爲的東西),必須對每種類型做一些不同的事情,並且必須對它們進行解構以準確地確定要做什麼以及不同的命令類型可能會以不同的方式解構:在Clojure中解構命令的習慣性方式

(defn action->edits [g action] 
    "Returns vector of edits needed to perform action in graph g." 
    (match action 
    [:boost from to] 
     [[:add-edge from to 1.0]] 
    [:retract from to] 
     [[:remove-edge from to]] 
    [:normalize from to]  ; a change has just been made to from->to 
     (map (fn [that] [:remove-edge from that]) 
      (successors-except g from to)) 
    [:recip-normalize to from] ; a change has just been made to from->to 
     [] 
    [:reduce-to-unofficial from to competitor] 
     [[:remove-edge from to] (make-competitive-edge from competitor])) 

我主要模仿了人們通常使用方案的pmatch宏。我想知道在Clojure中做這件事的慣用方式是什麼。

這就是我喜歡上面的代碼:

  • 這是非常可讀性。

  • 這很容易寫。

這裏就是我不喜歡:

  • 從任何地方訪問fromto領域但match宏內部是非常不可讀的,而且容易出錯。例如,要從大多數動作向量中提取from元素,請編寫(action 1)。如果我添加了新的動作,那麼該代碼將會中斷,並且現在在:recip-normalize中斷。

  • match生成的代碼效率低下:它通過重複拋出和捕獲異常來進行搜索。它不會產生一個大的嵌套if

我嘗試一點與代表命令,地圖,但它似乎變得冗長,以及命令的名稱並不突出好,大大降低了可讀性:

(match action 
    {:action :boost :from from :to to} 
     [{:edit :add-edge :from from :to to :weight 1.0}] 
    {:action :retract :from from :to to} 
     [{:edit :remove-edge :from from :to to}] 
    . . .) 

可能未來版本的match將生成更好的代碼,但現在生成的糟糕代碼(以及缺乏對記錄的支持)表明,在Clojure中,人們多年來一直在愉快地處理這種事情,而沒有match。那麼如何在Clojure中做這樣的事情?做什麼

+0

爲什麼不'(DEFN動作 - >編輯[G [行動英尺]'和'(condp =行動:提升 「助推」',還是我失去了一些東西 - 換句話說,爲什麼不首先解構fn參數? – birdspider

+0

@birdspider謝謝,'condp'可能正是我需要的!我只用了幾天的Clojure,因此我寫了「Clojure中的Scheme」。發表一個答案!順便說一句,在我的例子中,所有的記錄看起來都有相同的兩個參數。通常當我做這種事情時,他們會有所不同。我現在修改這個例子,因爲我對這個成語很感興趣對於如何解構變體記錄 - 但在我的實際代碼中,我會像使用通用模式一樣利用你建議。:) –

回答

0

我會利用clojure的內置destructuring facilities,因爲我沒有在這裏看到core.match的要求 - 但我可能會錯過一些東西。

例如:

(defn action->edits [g [action from to]] 
    (condp = action 
    :boost "boosting" 
    :retract "retracting" 
    :normalize-ksp-style (recur g [:boost from to]) 
    nil)) 

(action->edits 2 [:normalize-ksp-style 1 2]) 
;=> "boosting" 
+0

謝謝 - 這可能就是這個Clojure noob所需要的。三個問題:1)什麼是「KSP風格」? ([This](https://en.wikipedia.org/wiki/Kerbal_Space_Program)?)2)如果他們有不同的參數,是否有簡單的方法來解構不同的動作? 3)你通常會如何訪問代碼中其他地方的'from'和'to'字段? '(行動1)'和'(行動2)',總是去結構化,最好是使用地圖而不是矢量,還有其他的東西? –

+0

@BenKovitz 1)是啊! 1只是測試ksp 1.1prerelease和你的問題與提升出現 - 無法抗拒。 2)你可以在(地圖)鍵上進行解構(參見我提供的鏈接 - 向下滾動),3)可讀性強的原因爲什麼不在'(let [[aft] action])中 - 但我想沒有困難規則,(除了表演,那麼你想'defrecord's) – birdspider

相關問題