首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >clojure.test中的线程箭头私有防御

clojure.test中的线程箭头私有防御
EN

Stack Overflow用户
提问于 2016-10-01 22:05:37
回答 1查看 140关注 0票数 1

考虑一下来自新lein new app arrow-mve的MVE (最小可行示例)命名空间中的以下函数。函数extract-one是公共的,函数extract-two是私有的。我只是为了完整性和问题中包含main-函数的可能性而包含了这个函数:

代码语言:javascript
复制
(ns arrow-mve.core
  (:gen-class))

(defn extract-one [m]
  (-> m :a))

(defn- extract-two [m]
  (-> m :a))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))

在我的并行测试命名空间中,我可以如下所示测试这些函数。我可以通过直接调用或使用箭头线程宏extract-one来测试公共函数->。还请注意,我在直接调用中通过其完整的extract-two引用私有函数Var没有问题。这些测试通过:

代码语言:javascript
复制
(ns arrow-mve.core-test
  (:require [clojure.test :refer :all]
            [arrow-mve.core :refer :all]))

(deftest test-one-a
  (is (= 1 (extract-one {:a 1, :b 2}))))

(deftest test-one-b
  (is (= 1 (-> {:a 1, :b 2}
               extract-one))))

(deftest test-two-a
  (is (= 1 (#'arrow-mve.core/extract-two
            {:a 1, :b 2}))))

但是,当我试图用箭头宏调用私有函数extract-two时,会出现编译错误:

代码语言:javascript
复制
(deftest test-two-b
  (is (= 1 (-> {:a 1, :b 2}
               #'arrow-mve.core/extract-two))))

$ lein test

线程"main“中的异常:无法解析var: arrow.mve.core/提取--在此上下文中,编译:(arrow_mve/core_test.clj:10:12)在clojure.lang.Compiler.analyzeSeq(Compiler.java:6875) at clojure.lang.Compiler.analyze(Compiler.java:6669) at clojure.lang.Compiler.analyze(Compiler.java:6625)

当我让测试变得更复杂的时候,事情就变得更奇怪了。

代码语言:javascript
复制
(deftest test-two-b
  (is (= {:x 3.14, :y 2.72}
         (-> {:a {:x 3.14, :y 2.72}, :b 2}
             #'arrow-mve.core/extract-two))))

$ lein test

线程"main“clojure.lang.Compiler.analyzeSeq(Compiler.java:6875):clojure.lang.PersistentArrayMap中的异常不能转换为clojure.lang.Symbol,编译:(arrow_mve/core_test.clj:18:10)在clojure.lang.Compiler.analyze(Compiler.java:6669) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6856)时

同样,测试以直接调用形式通过:

代码语言:javascript
复制
(deftest test-two-b
  (is (= {:x 3.14, :y 2.72}
         (#'arrow-mve.core/extract-two
          {:a {:x 3.14, :y 2.72}, :b 2}))))

我怀疑这个问题是通过deftestisVar读取器#'和箭头宏链接宏的局限性,并怀疑是通过设计还是潜在的错误。当然,在我的实际应用程序(不是这个MVE)中,我有长而深的调用链,这使得使用箭头宏非常理想。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-01 22:54:38

以下是答案(不同的ns):

主命名空间:

代码语言:javascript
复制
(ns clj.core
  (:require [tupelo.core :as t] ))
(t/refer-tupelo)

(defn extract-one [m]
  (-> m :a))

(defn- extract-two [m]
  (-> m :a))

测试命名空间:

代码语言:javascript
复制
(ns tst.clj.core
  (:use clj.core
        clojure.test )
  (:require [tupelo.core :as t]))
(t/refer-tupelo)

(deftest test-one-a
  (is (= 1 (extract-one {:a 1, :b 2}))))

(deftest test-one-b
  (is (= 1 (-> {:a 1, :b 2}
               extract-one))))

(deftest test-two-a1
  (is (= 1 (#'clj.core/extract-two {:a 1, :b 2}))))

;(deftest test-two-b
;  (is (= 1 (-> {:a 1, :b 2}
;               clj.core/extract-two))))  ; fails: not public

;(deftest test-two-b1
;  (is (= 1 (-> {:a 1, :b 2}
;               #'clj.core/extract-two))))
;     fails: can't cast PersistentArrayMap to Symbol

(deftest test-two-b
  (is (= 1 (-> {:a 1, :b 2} 
               (#'clj.core/extract-two)))))  ; works

答案是var引用需要在括号内。线程宏都有表单的测试(伪代码):

代码语言:javascript
复制
(if (not (list? form))
  '(form)
  form)

所以像这样的表格

代码语言:javascript
复制
(-> 1
    inc)

转化成

代码语言:javascript
复制
(-> 1
    (inc))

在剩下的线程发生之前。对于您来说,if测试似乎失败了,因为var不是符号。将变量封装在一个列表中作为函数调用解决了这个问题。

我更喜欢将函数调用以线程形式括在括号中,而不使用任何“裸”函数,即使通常允许:

代码语言:javascript
复制
(-> 1
    (inc)    ; could have typed "inc" w/o parens
    (* 2))   ; must use parens since more than 1 arg
;=> 4
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39811892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档