【问题标题】:Testing Clojure's comp function测试 Clojure 的 comp 函数
【发布时间】:2016-03-03 12:34:34
【问题描述】:

我一直在用另一种语言重新实现一些 Clojure 函数,使用测试作为参考,我对 the testsclojure.core/comp 有点困惑。

(deftest test-comp
  (let [c0 (comp)]
    (are [x] (= (identity x) (c0 x))
         nil
         42
         [1 2 3]
         #{}
         :foo)
    (are [x y] (= (identity x) (c0 y))
         (+ 1 2 3) 6
         (keyword "foo") :foo)))

comp 本身只使用一次并且没有参数。这种行为似乎没有记录在案,但the source 表明它只返回identity 函数。

(defn comp
  ([] identity)
  ([f] f)
  ([f g] 
     (fn 
       ([] (f (g)))
       ([x] (f (g x)))
       ([x y] (f (g x y)))
       ([x y z] (f (g x y z)))
       ([x y z & args] (f (apply g x y z args)))))
  ([f g & fs]
     (reduce1 comp (list* f g fs))))

这是否意味着这些 arities 中有 3/4 没有经过测试?或者是否有测试保存在其他地方?我通过 GitHub 搜索找到了这些测试,但它们并不总是完全可靠。

为什么零元形式有测试,而它似乎是最没用的变体?

【问题讨论】:

    标签: clojure


    【解决方案1】:
    1. 是的。只在这里测试。事实上,在 v1.3.0 中添加零参数版本之前,没有对 comp 进行测试。检查此commit 及其parent
    2. 零参数comp 很有用,它有助于消除极端情况下的琐碎分支代码。假设您要对给定的输入进行一系列转换。但这些转换是动态生成的,并且可能会降级到不应该进行转换的程度。

    编辑: 举例说明我的第 2 点:

    (defn my-format
      "Returns an HTML representation of the given text in a paragraph,
       supports `:b' for bold and `:i' for italic font, and possibly more
       in the future."
      [text & more-args]
      (let [wrap (fn [w t] (str "<" w ">" t "</" w ">"))]
        (wrap "p" ((apply comp 
                          (map #(partial wrap (name %)) more-args))
                   text)))
    ; => (my-format "hello world" :b :i)
    ; "<p><b><i>hello world</i></b></p>
    ; => (my-format "hello world")
    ; "<p>hello world</p>
    

    代码 sn-p 是微不足道的,但你明白了。如果comp 不支持 0-arity 版本,代码看起来就不会那么优雅了。

    【讨论】:

    • 不要完全遵循第二点。你有机会添加一个简单的例子吗?
    • @DanPrince 更新了答案,HTH
    猜你喜欢
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    相关资源
    最近更新 更多