2010-12-03 1 views
1

(これは、など、私はこれが条件文の束を行うことができます知っています。スタイルについての質問ですマルチメソッド)マルチシグネチャ関数内のすべての実装に共通のバインディングを設定することはできますか?次の関数で

null-vectorは、各実装に定義されています。どのように私は一度全体の機能のためにそれを設定することができますか?一般的に、すべての実装に共通のバインディングを設定することは可能ですか?

null-vectorには「引数」が必要なのでクロージャは機能しませんが、私はpartialと考えています。しかし、それでもsizeパラメータの計算が必要です。明らかにコードを繰り返さないようにしたいと思います。

(defn path 
    "Returns a lazy sequence of vectors representing a monotonic path 
    walked over coll in n-dimensional space, where n is the cardinality 
    of coll's alphabet." 

    ([coll] 
    (let [alphabet (set coll) 
      cardinality (count alphabet) 
      alpha-map (apply hash-map (interleave alphabet (range cardinality))) 
      null-vector (vec (repeat cardinality 0))] 
     (path coll null-vector alpha-map))) 

    ([coll alpha-map] 
    (let [null-vector (vec (repeat (count (keys alpha-map)) 0))] 
     (path coll null-vector alpha-map))) 

    ([coll origin alpha-map] 
    (let [null-vector (vec (repeat (count origin) 0)) 
      unit-vector #(assoc null-vector (alpha-map %) 1) 
      sum-vectors #(vec (map + %1 %2))] 
     (reductions sum-vectors origin (map unit-vector coll))))) 

答えて

6

私は「プライベート」ヘルパー関数を作成します:

(defn- null-copy-vector [coll] 
    (vec (repeat (count coll) 0))) 

をしてからちょうど関数の各支店でそれを呼び出す:

(defn path 
    "Returns a lazy sequence of vectors representing a monotonic path 
    walked over coll in n-dimensional space, where n is the cardinality 
    of coll's alphabet." 

    ([coll] 
    (let [alphabet (set coll) 
      alpha-map (zipmap alphabet (iterate inc 0)) ;; note 1 
      null-vector (null-copy-vector alphabet)] 
     (path coll null-vector alpha-map null-vector))) 

    ([coll alpha-map] 
    (let [null-vector (null-copy-vector alpha-map)]  ;; note 2 
     (path coll null-vector alpha-map null-vector))) 

    ([coll origin alpha-map] 
    (path coll origin alpha-map (null-copy-vector origin))) 

    ([coll origin alpha-map null-vector] 
    (let [unit-vector #(assoc null-vector (alpha-map %) 1) 
      sum-vectors #(vec (map + %1 %2))] 
     (reductions sum-vectors origin (map unit-vector coll))))) 

それはこれではないかもしれは全体的な機能の中にはありませんが、これはかなり慣れていると思います。複数のアライメントを取らなかった関数では、letfnを使用して「内部」関数を分離することができますが、ここでは機能しません。

このようにして、a)基本ビルディングブロックの機能を他の場所で再利用し、b)小さなチャンクでテストできるようにします。 defn-をスキップして、defnを使用してテストを簡単にすることができます(ただし、bit more workでdefnをテストすることは可能です)。

また、最後のargとしてnull-vectorをとる新しい4-arg形式を発見しました。既に認識されている場合は、直接渡して、既にヌルベクトルから再作成することを避けることができます。その4-arg形式を隠したければ、それを別のdefnヘルパー関数に引き出すことができます。

無関係ノート:

  1. 私はzipmapを使用して単純な(私見)のimplと無限の配列にあなたの最初の分岐を修正しました。
  2. (count(keys map))の代わりに、(count map)だけで十分です(ここでの数はあなたのヘルパー関数内にあります)。