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

Add ifn? schema #416

Merged
merged 1 commit into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino

Malli is in [alpha](README.md#alpha).

## 0.5.0 (2021-04-13)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure what to put here so guessed this would be a minor version bump rather than just a patch.

The date comes across as quite presumptuous of me, and can absolutely be changed! 🙈


* Add `ifn?` predicate, [#416](https://github.com/metosin/malli/pull/416)

## 0.4.0 (2021-03-31)

* `:nil` schema, [#401](https://github.com/metosin/malli/pull/401)
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,22 @@ Using regular expressions:
; => false
```

`ifn?` accepts any value that implements Clojure(Script)'s IFn:

```clj
(m/validate ifn? :keyword)
; => true

(m/validate ifn? [])
; => true

(m/validate ifn? {})
; => true

(s/validate ifn? 123)
; => false
```

Copy link
Contributor Author

@jcf jcf Apr 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure of the best place to add this information. Hope it's okay.

## Serializable Functions

Enabling serializable function schemas requires [sci](https://github.com/borkdude/sci) as external dependency. If
Expand Down
1 change: 1 addition & 0 deletions src/malli/clj_kondo.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
(defmethod accept 'sequential? [_ _ _ _] :sequential)
(defmethod accept 'ratio? [_ _ _ _] :int) ;;??
(defmethod accept 'bytes? [_ _ _ _] :char-sequence) ;;??
(defmethod accept 'ifn? [_ _ _ _] :ifn)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please align all the 'ifn? mappings after the fn? in all the relevant places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved any ifn? code after corresponding fn? code in both the implementation and tests. If there's any more clean up you'd like me to do, happy to do so.


(defmethod accept :> [_ _ _ _] :number) ;;??
(defmethod accept :>= [_ _ _ _] :number) ;;??
Expand Down
3 changes: 2 additions & 1 deletion src/malli/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1752,7 +1752,8 @@
#'boolean? #'string? #'ident? #'simple-ident? #'qualified-ident? #'keyword? #'simple-keyword?
#'qualified-keyword? #'symbol? #'simple-symbol? #'qualified-symbol? #'uuid? #'uri? #?(:clj #'decimal?)
#'inst? #'seqable? #'indexed? #'map? #'vector? #'list? #'seq? #'char? #'set? #'nil? #'false? #'true?
#'zero? #?(:clj #'rational?) #'coll? #'empty? #'associative? #'sequential? #?(:clj #'ratio?) #?(:clj #'bytes?)]
#'zero? #?(:clj #'rational?) #'coll? #'empty? #'associative? #'sequential? #?(:clj #'ratio?) #?(:clj #'bytes?)
#'ifn?]
(reduce -register-var {})))

(defn class-schemas []
Expand Down
1 change: 1 addition & 0 deletions src/malli/error.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#?@(:clj ['bytes? {:error/message {:en "should be bytes"}}])
:re {:error/message {:en "should match regex"}}
:=> {:error/message {:en "invalid function"}}
'ifn? {:error/message {:en "should be an ifn"}}
:enum {:error/fn {:en (fn [{:keys [schema]} _]
(str "should be "
(if (= 1 (count (m/children schema)))
Expand Down
1 change: 1 addition & 0 deletions src/malli/generator.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@

(defmethod -schema-generator :=> [schema options] (-=>-gen schema options))
(defmethod -schema-generator :function [schema options] (-function-gen schema options))
(defmethod -schema-generator 'ifn? [_ _] gen/keyword)
(defmethod -schema-generator :ref [schema options] (-ref-gen schema options))
(defmethod -schema-generator :schema [schema options] (generator (m/deref schema) options))
(defmethod -schema-generator ::m/schema [schema options] (generator (m/deref schema) options))
Expand Down
10 changes: 9 additions & 1 deletion test/malli/clj_kondo_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
[:=> [:cat :int] [:int {:min 0}]]
[:=> [:cat :int :int [:* :int]] :int]])

(defn siren
[f coll]
(into {} (map (juxt f identity) coll)))

(m/=> siren [:=> [:cat ifn? coll?] map?])

(deftest clj-kondo-integration-test

(is (= {:op :keys,
Expand All @@ -48,7 +54,9 @@
:ret :int},
:varargs {:args [:int :int {:op :rest, :spec :int}],
:ret :int,
:min-arity 2}}}}}
:min-arity 2}}}
'siren
{:arities {2 {:args [:ifn :coll], :ret :map}}}}}
(-> 'malli.clj-kondo-test
(clj-kondo/collect)
(clj-kondo/linter-config)
Expand Down
10 changes: 10 additions & 0 deletions test/malli/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,16 @@

(is (= form (m/form schema))))))

(testing "ifn schemas"
(let [schema (m/schema ifn?)]
(is (true? (m/validate schema (fn []))))
(is (true? (m/validate schema (constantly 1))))
(is (true? (m/validate schema :keyword)))
(is (true? (m/validate schema #?(:clj (reify clojure.lang.IFn
(invoke [_] "Invoked!"))
:cljs (reify IFn
(-invoke [_] "Invoked!"))))))))

(testing "fn schemas"
(doseq [fn ['(fn [x] (and (int? x) (< 10 x 18)))
"(fn [x] (and (int? x) (< 10 x 18)))"]]
Expand Down
4 changes: 4 additions & 0 deletions test/malli/error_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@
(m/explain 123)
(me/humanize)))))

(deftest ifn-test
(is (= ["should be an ifn"]
(me/humanize (m/explain ifn? 123)))))

(deftest multi-error-test
(let [schema [:multi {:dispatch :type}
["plus" [:map [:value int?]]]
Expand Down
1 change: 1 addition & 0 deletions test/malli/json_schema_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@

[[:=> :cat int?] {} :fn]
[[:function [:=> :cat int?]] {} :fn]
[ifn? {}]

[integer? {:type "integer"}]
#?@(:clj [[ratio? {:type "number"}]
Expand Down
1 change: 1 addition & 0 deletions test/malli/transform_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,7 @@
[[:enum P1 "S" "M" "L"] "s" "S"]
[[:re P1 ".*"] "kikka" "KIKKA"]
[[:fn P1 'string?] "kikka" "KIKKA"]
[[ifn? P1] "kikka" "KIKKA"]
[[:maybe P1 keyword?] "kikka" :KIKKA]
[[:vector PS keyword?] ["kikka"] [:KIKKA]]
[[:sequential PS keyword?] ["kikka"] [:KIKKA]]
Expand Down