【问题标题】:Reusing the same let bindings重用相同的 let 绑定
【发布时间】:2018-08-16 18:45:42
【问题描述】:

我正在为 clojure 应用程序重构我的测试套件,并试图找出是否有办法保存 let 绑定以供重复使用以最大限度地减少复制代码,因为许多测试需要类似的设置,但会相互干扰并需要他们自己的灵巧。理想情况下,我希望它像这样工作:

(def let-bindings [bind1 val1 bind2 val2 bind3 val3])

(deftest test-1
  (testing "my test"
    (let (conj let-bindings [bind4 val4])
      ...)))

(deftest test-2
  (testing "my second test"
    (let (conj let-bindings [bind5 val5])
      ...)))

为了进一步说明,我需要在测试中评估 val1 和 val2,而不是在定义 let 绑定时,因为调用会以每次测试后需要重置的方式影响测试数据库。这是否意味着我需要一个宏?

【问题讨论】:

    标签: clojure let


    【解决方案1】:

    您可以使用fixture 重新定义跨测试的动态绑定并访问deftest 中的值。可以为所有或每个 deftest 定义一次夹具。

    (def ^:dynamic m)
    
    (defn once-fixture
      [tests]
      (binding [m {:a 1 :b 2}]
        (tests)))
    
    (use-fixtures :once once-fixture)
    
    (deftest testing-binding
      (is (= (:a m) 1)
        "Dynamic binding is working"))
    

    【讨论】:

      【解决方案2】:

      let 是一种特殊形式,因此尝试在不使用宏的情况下对其进行元编程是行不通的。也许您应该只定义通用绑定:

      (def bind1 val1) 
      (def bind2 val2) 
      (def bind3 val3)
      
      (deftest test-1
        (testing "my test"
          (let [bind4 val4]
            ;; here bind1...bind4 would be available
            ...)))
      
      ...
      

      编辑

      我想你可以用宏来做到这一点:

      ;; notice that the let will be recreated each time so if
      ;; val1 ... are computational hard consider caching. 
      (defmacro elet [ bindings & body ] 
        `(let [bind1 val1 bind2 val2 bind3 val3 ~@bindings] 
           ~@body))
      
      (deftest test-1
        (testing "my test"
          (elet [bind4 val4]
            ;; here bind1...bind4 would be available
            ...)))
      
      ...
      

      【讨论】:

      • 这是我目前正在做的事情,它可以使用但很笨重(许多测试组在一个 let 中有大约 10 个常见的绑定)。出于好奇,我将如何使用宏来做到这一点?这不是我真正有经验的事情。
      • @user1231120 我不是 Clojure 专家,但我相信我的编辑会奏效。
      • 谢谢!我只是在自学,从未使用过宏。
      【解决方案3】:

      要在没有宏的情况下执行此操作,您可以这样:

      (def m {:a 1 :b 2})
      
      (deftest foo []
        (println (m :a)))
      
      (foo)
      ;; prints 1
      
      (let [m (assoc m :c 3)]
        (deftest bar
          (println (m :c))))
      
      (bar)
      ;; prints 3
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-11
        • 1970-01-01
        • 2014-03-21
        • 2014-06-19
        • 1970-01-01
        • 2013-05-31
        • 1970-01-01
        相关资源
        最近更新 更多