2010-12-03 8 views
1

(Dies ist eine Frage in Bezug auf Stil. Ich weiß dies kann mit einem Bündel von conditionals, Multimethoden usw. durchgeführt werden)Ist es möglich, eine gemeinsame Bindung für alle Implementierungen in einer Mehrfachsignaturfunktion festzulegen?

In der folgenden Funktion wird null-vector auf jeder Implementierung definiert. Wie kann ich es einmal für die gesamte Funktion einstellen? Ist es allgemein möglich, eine gemeinsame Bindung für alle Implementierungen festzulegen?

Eine Schließung wird nicht funktionieren, da es null-vector braucht ein "Argument", aber ich nehme an, ich könnte partial es. Dies würde jedoch immer noch eine Berechnung des Größenparameters erfordern. Ich möchte offensichtlich vermeiden, Code zu wiederholen.

(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))))) 

Antwort

6

ich eine "private" Helferfunktion schaffen würde:

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

und dann rufen Sie einfach es in jedem Zweig der Funktion:

(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))))) 

Es mag sein, ist dies nicht Befriedigend für Sie, weil null-copy-vector ist nicht "innerhalb" der Gesamtfunktion hier, aber ich denke, das ist ziemlich idiomatisch. Bei einer Funktion, die nicht mehrere Aritäten benötigt, könnte ich letfn verwenden, um eine "interne" Funktion zu trennen, aber das wird hier nicht funktionieren.

Wenn Sie diese Dinge auflösen, können Sie a) die grundlegenden Bausteinfunktionen an anderer Stelle wiederverwenden und b) können Sie in kleineren Blöcken testen. Vielleicht möchten Sie die defn- überspringen und einfach Defn verwenden, um das Testen zu erleichtern (obwohl es möglich ist, defn- mit einem bit more work zu testen).

Ich brach auch eine neue 4-arg-Form aus, die den Null-Vektor als letzten Arg nimmt und Sie direkt übergeben kann, wenn Sie es wissen, so dass Sie vermeiden können, es aus einem bereits Null-Vektor neu zu erstellen. Wenn Sie das 4-Arg-Formular ausblenden wollten, könnten Sie es in eine separate Defn-Hilfsfunktion ziehen.

Unrelated Hinweise:

  1. I modifizierten ersten Zweig zu einer einfacheren (imho) impl zipmap und einer unendlichen Folge verwendet wird.
  2. Anstelle von (count (keys map)) reicht (count map) nur aus (die Anzahl ist hier in der Hilfsfunktion).
Verwandte Themen