rbb*_*rbb 4 clojure clojure.spec
我最近在Cojure Conj 2016上观看了Rich Hickeys的演讲,尽管它非常有趣,但我并没有真正理解clojure.spec
你使用它的重点.似乎大多数想法,例如符合,有效等,已经在Clojure中具有类似的功能.
我现在只学习了大约3个月的clojure,所以这可能是由于缺乏编程/ Clojure经验.
clojure.spec和cljs.spec的工作方式与Clojure和Cljs类似,尽管它们不是100%相同,但它们基于相同的基本原则.
为了顺利表达硬规格,您需要Clojure.Spec!
Clojure.spec为您提供了统一的记录,指定和自动测试程序以及验证实时数据的方法.
它几乎偷走了它的每一个想法.而且它对你自己无能为力.
但在我的 - 几乎不知情的意见中,它改变了规范的经济性,使其在做得好的同时值得.一个改变游戏规则的人? - 很可能.
在上周的clojure/conj会议上,大概有一半的演讲以某种方式展示了规格,而且它甚至还没有出现.规范是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)))))
Run Code Online (Sandbox Code Playgroud)
使用符合上述args
规范的样本数据调用该函数:
(s/exercise-fn `subs)
Run Code Online (Sandbox Code Playgroud)
或运行1000次测试(这可能会失败几次,但继续运行并且它将起作用 - 这是由于内置生成器无法满足:args
谓词的第二部分;如果需要可以编写自定义生成器):
(stest/check `subs)
Run Code Online (Sandbox Code Playgroud)
或者,想要查看您的应用subs
是否在实时运行时对其进行无效调用?只需运行它,如果调用该函数并且不符合规范,您将获得规范异常:
(stest/instrument `subs)
Run Code Online (Sandbox Code Playgroud)
我们还没有将它集成到我们的工作流程中,因为它仍然是alpha版本而无法生产,但第一个目标是编写规范.我将它们放在相同的命名空间中,但目前放在单独的文件中.
我预见我们的工作流程是使用这个(在clojure规范指南中找到)运行spec'd函数的测试:
(-> (stest/enumerate-namespace 'user) stest/check)
Run Code Online (Sandbox Code Playgroud)
然后,打开所有功能的仪表,并按照我们通常测试它的负载运行应用程序,并确保"真实世界"数据有效,这将是有利的.
您还可以使用s/conform
在函数本身中解构复杂数据,或者s/valid
用作运行函数的前置条件和后置条件.我对此并不太热衷,因为它是生产系统的开销,但这是一种可能性.
天空是极限,我们只是划伤了表面!随着时间的推移,未来几个月和几年内会出现很酷的事