(这是一个关于风格的问题。我知道这可以用一堆条件,多方法等来完成。)
在以下函数中,每个实现都定义了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)))))
答案 0 :(得分: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)))))
这可能对你不满意,因为null-copy-vector
并非“内部”整体功能,但我认为这是非常惯用的。在一个没有多个arities的函数中,我可能会使用letfn来分隔出一个“内部”函数,但这在这里不起作用。
像这样突破也可以让你a)在其他地方重用基本的构建块函数,b)让你在更小的块中进行测试。您可能希望跳过defn-并使用defn来简化测试(尽管可以使用bit more work来测试defn。)
我还打破了一个新的4-arg表单,它将null-vector作为最后一个arg,让你直接传递它,如果你知道它,这样你就可以避免从已经为空的向量重新创建它。如果你想隐藏那个4-arg表格,你可以把它拉成一个单独的defn-helper函数。
无关的说明: