Skip to content

Commit

Permalink
Version 0.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude authored Feb 7, 2019
1 parent f86e242 commit 17c9407
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 52 deletions.
112 changes: 62 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,78 @@
<img src="./logo/logo.svg">
<img src="./logo/logo-w320.png">

[![CircleCI](https://circleci.com/gh/borkdude/speculative/tree/master.svg?style=svg)](https://circleci.com/gh/borkdude/speculative/tree/master)
[![Clojars Project](https://img.shields.io/clojars/v/speculative.svg)](https://clojars.org/speculative)
[![cljdoc badge](https://cljdoc.org/badge/speculative/speculative)](https://cljdoc.org/d/speculative/speculative/CURRENT)

speculative is a collection of specs for the functions in `clojure.core`. While
its ultimate goal is to be rendered obsolete by these or similar specs being
added to `clojure.core` proper, speculative hopefully provides some value while
we're waiting for that to happen.
A collection of specs for the functions in `clojure.core`.

## Quickstart

``` clojure
Clojure 1.10.0
user=> (require '[speculative.instrument :as i])
nil
user=> (i/instrument)
[clojure.core/every-pred clojure.core/max clojure.string/join ...]
user=> (subs "foo" -1)
Execution error - invalid arguments to clojure.core/subs at (REPL:1).
-1 - failed: nat-int? at: [:start] spec: :speculative.specs/nat-int
```

## Rationale

With the new error-messages that are coming with Clojure 1.10, adding specs to
the `clojure.core` functions give much better error messages.
By writing, using and maintaining core specs, and reflecting upon them, we get
the following benefits:

Without specs on `clojure.core/map` the error looks like:
* Better error messages during development and testing
* Discover where Clojure and ClojureScript functions behave differently and when
possible fix it
* Discover the established usages of functions within the Clojure community
* Provide data for [re-find](https://re-find.it), an app that helps you find
functions using specs

```clojure
Clojure 1.10.0-RC1
user=> (map 'lol 'lol)
Error printing return value (IllegalArgumentException) at clojure.lang.RT.seqFrom (RT.java:551).
Don't know how to create ISeq from: clojure.lang.Symbol
user=>
```
With speculative, we get
## Disclaimer

```
user=> (map 1 'lol)
Evaluation error - invalid arguments to clojure.core/map at (NO_SOURCE_FILE:4).
1 - failed: ifn? at: [:f]
user=>
```
These specs reflect what we currently know about the newest versions of Clojure
and ClojureScript. These specs are in no way definitive or authoritative. They
may evolve based on new insights and changes in Clojure. These specs have no
official status, are not endorsed by Cognitect and are provided without
warranty.

## Installation

Add the relevant coordinates to your favourite build tool:
### Tools.deps

deps.edn

```
speculative {:mvn/version "0.0.2"}
``` clojure
{:deps {speculative {:mvn/version "0.0.3"}}}
```

lein
### Leiningen / Boot

```
[speculative "0.0.2"]
``` clojure
[speculative "0.0.3"]
```

## Usage

Speculative specs correspond to the namespaces in Clojure:

``` clojure
speculative.core -> clojure.core
speculative.set -> clojure.set
...
speculative.core -> clojure.core
speculative.set -> clojure.set
speculative.string -> clojure.string
```

To load all specs at once, you can require `speculative.instrument` which also
provides functions to only instrument speculative specs.

```clojure
``` clojure
$ clj
Clojure 1.10.0
user=> (require '[speculative.instrument :refer [instrument unstrument]])
nil
user=> (instrument)
[clojure.core/first clojure.core/apply clojure.core/assoc ...]
[clojure.core/every-pred clojure.core/max clojure.string/join ...]

user=> (merge-with 1 {:a 2} {:a 3})
Execution error - invalid arguments to clojure.core/merge-with at (REPL:1).
Expand All @@ -80,23 +85,30 @@ Execution error (ClassCastException) at user$eval344/invokeStatic (REPL:1).
java.lang.Long cannot be cast to clojure.lang.IFn
```

## Managing expectations
### Usage in testing

To instrument during testing, you can use the `fixture` from
`speculative.instrument`:

``` clojure
(require '[clojure.test :as t])
(require '[speculative.instrument :as i])
(t/use-fixtures :once i/fixture)
```

This will turn on instrumentation before the tests and turn it off after.

These specs try to be as accurate as possible, given what we know about the
newest releases of Clojure and ClojureScript. However, we cannot guarantee that
these specs are The Answer, once and for all. Our specs may be inaccurate and we
may change them based on new insights. Functions in future versions of Clojure
may allow different arguments and arities or return different values than we
account for at this time of writing. These specs have no official status, are
not endorsed by Cognitect and are provided without warranty.
If you run tests with [kaocha](https://github.com/lambdaisland/kaocha) you can
use the [speculative kaocha
plugin](https://github.com/borkdude/speculative-kaocha-plugin).

## Speculative broke my project

Speculative specs find, when instrumented, incorrect or undefined usage of
Clojure core functions. If code is under your control, you can fix it. If the
call was made in a library not under your control, you can unstrument the spec
using `clojure.spec.test.alpha/unstrument`, unload it using `(s/def spec-symbol
nil)` or disable it within the scope of a body using
Speculative specs find, when instrumented, invalid or undefined usage of Clojure
core functions. If code is under your control, you can fix it. If the call was
made in a library not under your control, you can unstrument the spec using
`clojure.spec.test.alpha/unstrument`, unload it using `(s/def spec-symbol nil)`
or disable it within the scope of a body using
`respeced.test/with-unstrumentation` (see
[respeced](https://github.com/borkdude/respeced)):

Expand Down Expand Up @@ -222,8 +234,8 @@ href="https://twitter.com/borkdude/status/1053404362062606336?ref_src=twsrc%5Etf

## Contributing

In the hope that the code in this project would be useful for `clojure.core`,
any contributer to this repo needs to have a [Contributor
In case this code will ever be useful to `clojure.core`, any contributer to this
project needs to sign the [Contributor
Agreement](https://clojure.org/community/contributing) for Clojure so that any
code in speculative can be used in either Clojure or Clojurescript.

Expand Down
4 changes: 2 additions & 2 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(defproject speculative "0.0.3-SNAPSHOT"
(defproject speculative "0.0.3"
:description "A collection of specs for clojure.core functions"
:url "https://github.com/borkdude/speculative"
:scm {:name "git"
Expand All @@ -7,7 +7,7 @@
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.10.0"]]
:profiles {:dev {:dependencies
[[org.clojure/clojurescript "1.10.439"]
[[org.clojure/clojurescript "1.10.516"]
[org.clojure/test.check "0.9.0"]]}}
:deploy-repositories [["clojars" {:url "https://clojars.org/repo"
:username :env/clojars_user
Expand Down

0 comments on commit 17c9407

Please sign in to comment.