Last active
September 27, 2017 09:55
-
-
Save david-mcneil/a46b091c05a91adb8336 to your computer and use it in GitHub Desktop.
examples of prismatic schema extension to higher order functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; (:require [lonocloud.step.async.pschema :as s]) | |
;; Define a higher-order function. Note the 'format-f' argument that is specified to be a function | |
;; of one arity that takes a String and an s/Int to produce a String | |
(s/defn write-person [format-f :- (s/fn String [String s/Int]) | |
person :- {:name String | |
:age s/Int}] | |
(format-f (:name person) (:age person))) | |
(def joe {:name "joe" :age 19}) | |
;; Define a function whose type signature matches what the higher-order function specifies. | |
(s/defn simple-format :- String | |
[name :- String | |
age :- s/Int] | |
(str name " " age)) | |
(write-person simple-format joe) | |
;; => "joe 19" | |
(s/defn other-fn :- String [name :- String]) | |
(write-person other-fn joe) | |
;; => ExceptionInfo Input to write-person does not match schema: [(named [#<...$eval70697$other_fn__70698...$eval70697$other_fn__70698@2c073f78> not "typed function {:output-schema java.lang.String, :input-schemas [[java.lang.String Int]]}"] format-f) nil] | |
;; Alternatively, if we invoke the higher-order function with a parameter that does not have type | |
;; information, then it is assumed to be of the correct type. | |
(write-person (fn [n a] (str n a)) joe) | |
;;=> "joe19" | |
;; If a function has more arities than are specified in the higher-order function ... | |
(s/defn another-format :- String | |
([name :- String] | |
(str "name: " name)) | |
([name :- String | |
age :- s/Int] | |
(str "name: " name " age: " age)) | |
([name :- String | |
age :- s/Int | |
job :- String] | |
(str "name: " name " age: " age " job: " job))) | |
;; ... then it works. | |
(write-person another-format joe) | |
;; => "name: joe age: 19" | |
;; A higher-order function can specify that multiple arities are needed. | |
(s/defn write-person-2 [format-f :- (s/fn String | |
[String s/Int] | |
[String s/Int String]) | |
person :- {:name String | |
:age s/Int}] | |
(format-f (:name person) (:age person))) | |
;; As long as the provided function parameter matches all of the arities then it will pass | |
;; validation. | |
(write-person-2 another-format joe) | |
;; => "name: joe age: 19" | |
(write-person other-fn joe) | |
;; => ExceptionInfo Input to write-person-2 does not match schema: ... | |
;; Varargs are supported in parameter functions. | |
(s/defn flexible-format :- String | |
[name :- String | |
age :- s/Int | |
& other :- [String]] | |
(str name " " [age other])) | |
(write-person-2 flexible-format joe) | |
;; => "joe [19 nil]" | |
;; Varargs are also supported in the higher-order function argument specifications. | |
(s/defn write-person-3 [format-f :- (s/fn String | |
[String s/Int] | |
[String s/Int String & [String]]) | |
person :- {:name String | |
:age s/Int}] | |
(format-f (:name person) (:age person) "...")) | |
;; Note in this case the varargs occur at different positions, but the call is still allowed. The | |
;; tool understands how to expand the varargs to make the signatures match. | |
(write-person-3 flexible-format joe) | |
;; => "joe [19 (\"...\")]" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment