Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function Schemas with clj-kondo integration #306

Merged
merged 9 commits into from
Nov 29, 2020
Merged

Function Schemas with clj-kondo integration #306

merged 9 commits into from
Nov 29, 2020

Conversation

ikitommi
Copy link
Member

@ikitommi ikitommi commented Nov 23, 2020

Function Schemas

alpha, subject to change

Functions can be described with :=>, which takes function arguments (as :tuple) and output schemas as children.

(defn plus [x y] (+ x y))

(def =>plus [:=> [:tuple int? int?] int?])

(m/validate =>plus plus)
; => true

By default, validation just checks if a valu ia ifn?:

(m/validate =>plus str)
; => true :(

We can use value generation for more comprehensive testing:

(m/validate =>plus plus {::m/=>validator mg/=>validator})
; => true

(m/validate =>plus str {::m/=>validator mg/=>validator})
; => false

A generated function implementation:

(def plus-gen (mg/generate =>plus))

(plus-gen 1 2)
; => -1

(plus-gen 1 "2")
; =throws=> :malli.generator/invalid-input {:schema [:tuple int? int?], :args [1 "2"]}

Multiple arities are WIP, currently defined using :or:

(m/validate
  [:or
   [:=> [:tuple pos-int?] pos-int?]
   [:=> [:tuple int? int?] int?]]
  (fn math
    ([x] (+ x x))
    ([x y] (+ x y)))
  {::m/=>validator mg/=>validator})
; => true

(def f (mg/generate
         [:or
          [:=> [:tuple int?] pos-int?]
          [:=> [:tuple int? int?] int?]]))

;; fixes the arity, which is not correct
(-> f meta :arity)
; => 1

(f 42)
; => 2

(f 42 42)
; =thrown=> :malli.generator/invalid-input {:schema [:tuple int?], :args [42 42]}

Varargs are WIP too (waiting for #180).

Function Schema Registry

Vars can be annotated with function schemas using m/=> macro, backed by a global registry:

(defn square [x] (* x x))

(m/=> square [:=> [:tuple int?] pos-int?])

Listing registered function Var schemas:

(m/=>schemas)
;{user
; {square
;  {:schema [:=> [:tuple int?] pos-int?]
;   :meta nil
;   :ns malli.generator-test
;   :name square}}}

Clj-kondo

Clj-kondo is a linter for Clojure code that sparks joy.

Given functions and function Schemas:

(defn square [x] (* x x))
(m/=> square [:=> [:tuple int?] nat-int?])

(defn plus
  ([x] x)
  ([x y] (+ x y)))

(m/=> plus [:or
            [:=> [:tuple int?] int?]
            [:=> [:tuple int? int?] int?]])

Generating clj-kondo configuration from current namespace:

(require '[malli.clj-kondo :as mc])

(-> (mc/collect *ns*) (mc/linter-config))
;{:lint-as #:malli.schema{defn schema.core/defn},
; :linters
; {:type-mismatch
;  {:namespaces
;   {user {square {:arities {1 {:args [:int]
;                               :ret :pos-int}}}
;          plus {:arities {1 {:args [:int]
;                             :ret :int},
;                          2 {:args [:int :int]
;                             :ret :int}}}}}}}}

Emitting confing into ./.clj-kondo/configs/malli/config.edn:

(mc/emit!)

In action:

clj-kondo

@ikitommi ikitommi changed the title Function Schemas DRAFT: Function Schemas Nov 23, 2020
@ikitommi ikitommi marked this pull request as ready for review November 29, 2020 14:56
@ikitommi ikitommi added the Clojurists Together Sponsored by Clojurists Together Q3 2020 label Nov 29, 2020
* no arity errors
@ikitommi ikitommi changed the title DRAFT: Function Schemas Function Schemas with clj-kondo integration Nov 29, 2020
@ikitommi ikitommi merged commit 23772de into master Nov 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clojurists Together Sponsored by Clojurists Together Q3 2020
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant