Muotti
Noun.
- mould/mold (hollow form or matrix for shaping a fluid or plastic substance)
- cast (mould used to make cast objects)
- die
- form (thing that gives shape to other things as in a mold)
(source: https://en.wiktionary.org/wiki/muotti)
Muotti is a graph based value transformer library which aims to solve value transformation by utilizing a digraph of known transformations to produce a transformer chain which is then used to perform the actual transformation.
Given a map of adjacencies - that is, edges of a graph - with validation and transformer functions:
(require '[muotti.core :as muotti])
(def config {:transformations {[:keyword :string] {:validator keyword?
:transformer name}
[:string :number] {:validator string?
:transformer parse-long}
[:string :boolean] {:validator string?
:transformer boolean}
[:number :string] {:validator number?
:transformer str}}})
a transformer can be created:
(def t (muotti/->transformer config))
which is then immediately usable for transforming values:
(muotti/transform t :keyword :number :123)
; => 123
(muotti/transform t :number :boolean 123)
; => true ;; non-empty values are treated as ´true´ by clojure.core/boolean
Unresolvable transformations return a special value:
(muotti/transform t :keyword :double :3.14)
; => ::unknown-path
Transformer chain validation errors also return a special value:
(def broken-adjacency {:transformations {[:a :b] {:validator keyword?
:transformer str}}})
(def t2 (muotti/->transformer broken-adjacency))
(muotti/transform t2 :a :b "not a number")
;; => ::invalid-value
All possible paths in the graph will be tested to resolve a result:
(def multiple {:transformations {[:in :num] {:transformer #(Integer/parseInt %)}
[:in :str] {:transformer str}
[:str :out] {:transformer #(= "magic!" %)}
[:num :out] {:transformer #(= 6 %)}}})
(def t3 (muotti/->transformer multiple))
(muotti/transform t3 :in :out "6")
;;=> true
(muotti/transform t3 :in :out "magic!")
;;=> true
(muotti/transform t3 :in :out "0")
;;=> false
(muotti/transform t3 :in :out "anything")
;;=> false
Resolving order of paths is not guaranteed to be stable!
Muotti is made to complement Malli's decoding and encoding capabilities through Malli's Value Transformation capability.
Create a Malli transformer and then use it to call eg. malli.core/decode
with the transformer:
(require '[malli.core :as malli])
(require '[muotti.malli :as mm])
(def malli-transformer (mm/transformer (muotti/->transformer mm/malli-config)))
(malli/decode
[:map
[:a {:muotti/ignore true} :uuid]
[:b :int]]
{:a :invalid
:b "123"}
malli-transformer)
;;=> {:a nil, :b 123}
Use :muotti/source
and :muotti/target
properties to override transformation types.
See muotti.malli-tests/override-types for examples.
nil
inputsUse :muotti/default
to provide a default value.
(malli/decode
[:string {:muotti/default "hello"}]
nil
malli-transformer)
;;=> hello
Muotti's aim is to support all major Malli types and predicates which are too numerous to list here. Instead see either
muotti.malli-tests
namespace orIt is possible to output the graph contained by the transformer as DOT:
(->> (muotti/->transformer mm/malli-config)
(muotti/visualize-dot)
(spit "/tmp/graph.dot"))
The resulting file can be input into GraphViz:
dot -Tpng /tmp/graph.dot > graph.png
which results in
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close