为什么Clojure Spec在这里进入无限循环?

时间:2018-07-19 15:15:24

标签: clojure clojure.spec

这是一个将视觉模式表示为Sshapes集合的应用程序。

Sshape(样式形状)是点列表和样式信息图。

APattern是包含Sshapes列表的记录。

这是规格:

在sshape.clj中

(spec/def ::stroke-weight int?)
(spec/def ::color (spec/* int?))
(spec/def ::stroke ::color)
(spec/def ::fill ::color)
(spec/def ::hidden boolean?)
(spec/def ::bezier boolean?)
(spec/def ::style (spec/keys :opt-un [::stroke-weight ::stroke ::fill ::hidden ::bezier]))
(spec/def ::point (spec/* number?))
(spec/def ::points (spec/* ::point))
(spec/def ::SShape (spec/keys :req-un [::style ::points]))

在groups.clj

(spec/def ::sshapes (spec/* :patterning.sshapes/SShape))
(spec/def ::APattern (spec/keys :req-un [::sshapes]))

然后在另一个文件中,我尝试测试将两个APatterns放在一起的叠加功能正在接受APatterns

(defn superimpose-layout "simplest layout, two patterns located on top of each other "
  [pat1 pat2]
  {:pre [(spec/valid? :patterning.groups/APattern pat1)]}
  (->APattern (concat (:sshapes pat1) (:sshapes pat2)))   )

在没有前提条件的情况下运行。

有了前提条件,我得到了无限递归和堆栈溢出。

Exception in thread "main" java.lang.StackOverflowError, compiling:(/tmp/form-init7774655152686087762.clj:1:73)
    at clojure.lang.Compiler.load(Compiler.java:7526)
    at clojure.lang.Compiler.loadFile(Compiler.java:7452)
    at clojure.main$load_script.invokeStatic(main.clj:278)
    at clojure.main$init_opt.invokeStatic(main.clj:280)
    at clojure.main$init_opt.invoke(main.clj:280)
    at clojure.main$initialize.invokeStatic(main.clj:311)
    at clojure.main$null_opt.invokeStatic(main.clj:345)
    at clojure.main$null_opt.invoke(main.clj:342)
    at clojure.main$main.invokeStatic(main.clj:424)
    at clojure.main$main.doInvoke(main.clj:387)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.lang.Var.applyTo(Var.java:702)
    at clojure.main.main(main.java:37)
Caused by: java.lang.StackOverflowError
    at clojure.spec.alpha$regex_QMARK_.invokeStatic(alpha.clj:81)
    at clojure.spec.alpha$regex_QMARK_.invoke(alpha.clj:78)
    at clojure.spec.alpha$maybe_spec.invokeStatic(alpha.clj:108)
    at clojure.spec.alpha$maybe_spec.invoke(alpha.clj:103)
    at clojure.spec.alpha$the_spec.invokeStatic(alpha.clj:117)
    at clojure.spec.alpha$the_spec.invoke(alpha.clj:114)
    at clojure.spec.alpha$dt.invokeStatic(alpha.clj:742)
    at clojure.spec.alpha$dt.invoke(alpha.clj:738)
    at clojure.spec.alpha$dt.invokeStatic(alpha.clj:739)
    at clojure.spec.alpha$dt.invoke(alpha.clj:738)
    at clojure.spec.alpha$deriv.invokeStatic(alpha.clj:1480)
    at clojure.spec.alpha$deriv.invoke(alpha.clj:1474)
    at clojure.spec.alpha$deriv.invokeStatic(alpha.clj:1491)
    at clojure.spec.alpha$deriv.invoke(alpha.clj:1474)
    at clojure.spec.alpha$deriv.invokeStatic(alpha.clj:1491)
    at clojure.spec.alpha$deriv.invoke(alpha.clj:1474)
    at clojure.spec.alpha$deriv.invokeStatic(alpha.clj:1492)
    at clojure.spec.alpha$deriv.invoke(alpha.clj:1474)
    at clojure.spec.alpha$deriv.invokeStatic(alpha.clj:1492)
    at clojure.spec.alpha$deriv.invoke(alpha.clj:1474)
    at clojure.spec.alpha$deriv.invokeStatic(alpha.clj:1492)

更新:

好。我已经把这个范围缩小了。

比方说,定义了一个点向量,使得pts

[[-0.3 -3.6739403974420595E-17] [1.3113417037298127E-8 -0.2999999999999997] [0.2999999999999989 2.6226834037856828E-8] [-3.934025103841547E-8 0.29999999999999744] [-0.3 -3.6739403974420595E-17]]

然后拨打电话

(spec/valid? :patterning.sshapes/points pts)

给我堆栈溢出:

StackOverflowError   clojure.spec.alpha/regex? (alpha.clj:81)

所以看起来像是因为我要匹配数字的spec / *的spec / *。

嵌套矢量触发这种无限递归是否有某些原因?

2 个答案:

答案 0 :(得分:4)

为此,您可能应该使用.container { width: 150px; height: 100px; background-image: url("http://i.stack.imgur.com/2OrtT.jpg"); background-size: cover; background-repeat: no-repeat; background-position: 50% 50%; }​ 而非spec/coll-of

s/*

答案 1 :(得分:1)

我相信,Clojure规范在这一方面存在一些错误。

这看起来像https://dev.clojure.org/jira/browse/CLJ-2002的一个实例。它在符合条件时触发:

(s/conform (s/* (s/* number?)) [[]])  ; => StackOverflowError