我最近看过Rich Hickeys talk at Cojure Conj 2016虽然这很有意思,但我并没有真正理解clojure.spec
或者你使用它时的观点。似乎大多数想法,例如符合,有效等,已经在Clojure中具有类似的功能。
我现在只学习了大约3个月的clojure,所以这可能是由于缺乏编程/ Clojure经验。
clojure.spec和cljs.spec的工作方式与Clojure和Cljs类似,尽管它们不是100%相同,但它们基于相同的基本原则。
答案 0 :(得分:9)
为了顺利表达硬性规格,您需要 Clojure.Spec !
Clojure.spec为您提供统一的记录,指定和自动测试程序以及验证实时数据的方法。
它几乎窃取了每一个想法。而且它对你自己无能为力。
但在我的 - 几乎不知情的意见 - 中,它改变了规范的经济性,使其在做得好的同时值得。一个改变游戏规则的人? - 很可能。
答案 1 :(得分:5)
在上周的clojure / conj会议上,可能有一半的演讲以某种方式展示了规格,而且它甚至还没有出现。 spec是clojure的 主要 功能;它就在这里,它很强大。
作为其力量的一个例子,采取静态类型检查,被许多人称为一种安全网,并且是许多编程语言的定义特征。它非常有限,因为它只在编译时很好,而且它只检查类型。另一方面,spec验证并符合args的任何谓词(不仅仅是类型),返回,还可以验证两者之间的 关系 。所有这些都在函数代码的外部,将函数的逻辑与验证和代码文档混合在一起。
关于工作流程:
关系检查的好处的一个原型示例,而不仅仅是类型检查,是一个计算字符串子串的函数。类型检查可确保(subs s start end)
s
中的start
为字符串,end
和start
为整数。但是,必须在函数内进行其他检查,以确保end
和end
为正整数,start
大于(s/fdef clojure.core/subs
:args (s/and (s/cat :s string? :start nat-int? :end (s/? nat-int?))
(fn [{:keys [s start end]}]
(if end
(<= 0 start end (count s))
(<= 0 start (count s)))))
:ret string?
:fn (fn [{{:keys [s start end]} :args, substring :ret}]
(and (if end
(= (- end start) (count substring))
(= (- (count s) start) (count substring)))
(<= (count substring) (count s)))))
,并且生成的子字符串为否大于原始字符串。例如,所有这些事情都可以指出(如果其中一些有点多余或甚至可能不准确,请原谅我):
args
使用符合上述(s/exercise-fn `subs)
规范的示例数据调用该函数:
:args
或者运行1000次测试(这可能会失败几次,但是继续运行并且它会起作用 - 这是由于内置生成器无法满足(stest/check `subs)
谓词的第二部分;如果需要,可以编写自定义生成器):
subs
或者,想要查看您的应用是否在实时运行时拨打(stest/instrument `subs)
无效的电话?只需运行此命令,如果调用该函数并且未满足规范,您将获得规范异常:
(-> (stest/enumerate-namespace 'user) stest/check)
我们尚未将其整合到我们的工作流程中,并且因为它仍处于alpha状态而无法生产,但第一个目标是编写规范。我将它们放在相同的命名空间中,但目前放在不同的文件中。
我预见到我们的工作流程是使用此功能(在clojure规范指南中找到)运行规范功能的测试:
s/conform
然后,打开所有功能的仪表,并按照我们通常会测试的负载运行应用程序,并确保&#34;真实世界&#34;数据有效。
您还可以使用s/valid
来解析函数本身中的复杂数据,或者使用{{1}}作为运行函数的前置条件和后置条件。我不太热衷于此,因为它是生产系统中的开销,但这是一种可能性。
天空是极限,我们只是划伤了表面!在接下来的几个月和几年里,有一些很酷的东西出现在规范中!