SlideShare a Scribd company logo
1 of 43
Download to read offline
Designing
with
Malli
London Clojurians
12.08.2020
Tommi Reiman
@ikitommi
a new data validation and specification
library for Clojure/Script. It provides unified
tools for building data-driven schema systems
covering schema definition, validation, (human)
errors, value and schema transformation, value and
schema generation, registries and much more.
https://github.com/metosin/malli
Malli
(def address
{:id "123"
:tags #{:garage :chicken}
:address {:street "Jl. Pacar No.15, Sumerta Kauh"
:city "Densapar"
:zip 80236
:latlon [-8.652037 115.226808]}})
data
(def Address
{:id s/Str
:tags #{s/Keyword}
:address {:street s/Str
:city s/Str
:zip s/Int
:latlon [(s/one Double "lat")
(s/one Double "lon")]}})
plumatic schema
(require '[clojure.spec.alpha :as s])
(s/def ::id string?)
(s/def ::tags (s/coll-of keyword? :kind set?))
(s/def ::street string?)
(s/def ::city string?)
(s/def ::zip int?)
(s/def ::latlon (s/tuple double? double?))
(s/def :address/address
(s/keys :req-un [::street ::city ::zip ::latlon]))
(s/def ::address
(s/keys :req-un [::id ::tags :address/address]))
clojure.spec
(def Address
[:map
[:id string?]
[:tags [:set keyword?]]
[:address
[:map
[:street string?]
[:city string?]
[:zip int?]
[:latlon [:tuple double? double?]]]]])
Hiccup syntax
Just data and functions
Maps are open
by default
Keys are
required by
default
Malli
Ordered
Keys
(def Address
[:map
[:id string?]
[:tags [:set keyword?]]
[:address
[:map
[:street string?]
[:city string?]
[:zip int?]
[:latlon [:tuple double? double?]]]]])
Malli
(def Address
[:map {:title “Address”
:summary “An address"}
[:id string?]
[:tags {:optional true} [:set keyword?]]
[:address
[:map {:closed true}
[:street string?]
[:city string?]
[:zip {:default "33800"} int?]
[:latlon [:tuple double? double?]]]]])
Malli
Schema applications
• Validation and Machine-readable errors
• Spell-checking and human-readable errors
• Two-way value transformations
• Schema transformations (walkers, visitors, utils, JSON Schema, DOT, ..)
• GeneratingValues & Schemas
• (Parsing)
(def invalid-address
{:id 123
:tags #{:garage :chicken}
:address {:streetz "Jl. Pacar No.15"
:city "Densapar"
:latlon [-8.652037 115.226808]}})
(-> Address
(m/explain invalid-address)
(me/with-spell-checking)
(me/humanize))
;{:id ["should be a string"]
; :address {:zip ["missing required key"]
; :streetz ["should be spelled :street"]}}
(require '[malli.generator :as mg])
(mg/generate Address {:size 10, :seed 20})
;{:id "A1f05U4uE5",
; :tags #{:FqNN/Ti. :b3/h. :Ni/h? :Yg*-/GW*Y :jhL/k! :_/QnR},
; :address {:street "ABM74Q96S4"
; :city "k6z3OD4cy"
; :zip -1
; :latlon [-0.32421875 -1.8125]}}
The
Registry
Registries
• Schema types are looked from a registry
• Registry is passed as explicit option into schema functions
• Default registry has ~100 types and is immutable
• Other registry types: mutable, dynamic, lazy, local and composite
• Special JVM / Closure compiler option to swap the default registry
• Default to global mutable registry in Malli 1.0.0?
(def Order
[:schema
{:registry {"Country" [:map
[:name [:enum :FI :PO]]
[:neighbors [:vector [:ref "Country"]]]]
"Burger" [:map
[:name string?]
[:description {:optional true} string?]
[:origin [:maybe "Country"]]
[:price pos-int?]]
"OrderLine" [:map
[:burger "Burger"]
[:amount int?]]
"Order" [:map
[:lines [:vector "OrderLine"]]
[:delivery [:map
[:delivered boolean?]
[:address [:map
[:street string?]
[:zip int?]
[:country "Country"]]]]]]}}
"Order"])
Decomplect
maps, keys
and values
::id int?
::id int?
(s/def :address/id string?)
(s/def :address/tags (s/coll-of keyword? :kind set?))
(s/def :address/street string?)
(s/def :address/city string?)
(s/def :address/zip int?)
(s/def :address/latlon (s/tuple double? double?))
(s/def :address.address/address
(s/keys :req [::street ::city ::zip ::latlon]))
(s/def :address/address
(s/keys :req [::id ::tags :address/address]))
[:schema
{:registry {::id string?
::tags [:set keyword?]
::street string?
::city string?
::zip int?
::latlon [:tuple double? double?]
:address/address [:map ::street ::city ::zip ::latlon]
::address [:map ::id ::tags :address/address]}}
::address]
[:map
{:registry {::id string?
::tags [:set keyword?]
::address [:map
{:registry {::street string?
::city string?
::zip int?
::latlon [:tuple double? double?]}}
::street ::city ::zip ::latlon]}}
::id ::tags ::address]
In Real
World
Coercion
• We are dealing with various data sources with different capabilities,
e.g. JSON,YAML and XML data
• We need to decode from X to EDN and encode from EDN to X’
• … or just apply default values. Or convert strings into keyword keys
• Malli has fast two-way interceptor-based transformers
• Transforming based on Schema type and properties
(def Address
[:map {:title “Address”
:summary “An address"}
[:id string?]
[:tags {:optional true} [:set keyword?]]
[:address
[:map {:closed true}
[:street string?]
[:city string?]
[:zip {:default "33800"} int?]
[:latlon [:tuple double? double?]]]]])
(require '[malli.transform :as mt])
(m/decode
Address
{:id "123"
:tags [“garage” “chicken”]
:address {:street "Jl. Pacar No.15"
:city "Densapar"
:zip 80236
:latlon [-8.652037 115.226808]}}
(mt/json-transformer))
;{:id "123"
; :tags #{:garage :chicken},
; :address {:street "Jl. Pacar No.15, Sumerta Kauh, Kec."
; :city "Densapar"
; :zip 80236
; :latlon [-8.652037 115.226808]}}
(m/decode
Address
{:id "Lillan"
:EVIL "LYN"
:tags ["coffee" "artesan" "garden"]
:address {:street "Ahlmanintie 29"
:DARK "ORKO"
:city "Tampere"
:lonlat [61.4858322 23.7854658]}}
(mt/transformer
(mt/strip-extra-keys-transformer)
(mt/default-value-transformer)
(mt/json-transformer)))
;{:id "Lillan"
; :tags #{:coffee :artesan :garden}
; :address {:street "Ahlmanintie 29"
; :city "Tampere"
; :zip "33800"}}
(def LegacyString
[:string {:decode/string '(fn [x] (str/lower-case (subs x 4)))
:encode/string '(fn [x] (str/upper-case (str "HAL_" x)))}])
(m/decode LegacyString "HAL_KIKKA" (mt/string-transformer))
; => "kikka"
(m/encode LegacyString "kikka" (mt/string-transformer))
; => "HAL_KIKKA"
(m/decode
[:string {:decode/string {:enter '#(str "olipa_" %)
:leave '#(str % "_avaruus")}}]
"kerran"
(mt/string-transformer))
; => "olipa_kerran_avaruus"
Inferring values
• Opposite of GeneratingValues - return a Schema that validates
against the sample values
• Crawled legacy MongoDB collection (5+ years of accumulated stuff)
• For each value, inferred a schema + accumulated schema union
• All documents have timestamps —>Temporal Schema index!
(require '[malli.provider :as mp])
(mp/provide
[{:id "123"
:tags #{:garage :chicken}
:address {:street "Jl. Pacar No.15, Sumerta Kauh, Kec."
:city "Densapar"
:zip 80236
:latlon [-8.652037 115.226808]}}
{:id "Lillan"
:tags #{:coffee :artesan :garden}
:address {:street "Ahlmanintie 29"
:city "Tampere"
:lonlat [61.4858322 23.7854658]}}])
;[:map
; [:id string?]
; [:tags [:set keyword?]]
; [:address
; [:map
; [:street string?]
; [:city string?]
; [:zip {:optional true} int?]
; [:latlon {:optional true} [:vector double?]]
; [:lonlat {:optional true} [:vector double?]]]]]
Serialising Schemas
• Thanks to SCI (https://github.com/borkdude/sci) and Edamame
(https://github.com/borkdude/edamame), mostly all schemas can be
• Thanks to SCI (https://github.com/borkdude/sci) and Edamame
(https://github.com/borkdude/edamame), mostly all schemas can be
persisted (and read back) to EDN
• Works with all of clj (JVM & GraalVM) and cljs, no eval needed
• Big leverage in building truly dynamic systems
• Playground at malli.io
(def Adult
[:map {:registry {::age [:and int? [:> 18]]}}
[:age ::age]])
(-> Adult
(malli.edn/write-string)
(malli.edn/read-string)
(m/validate {:age 46}))
; => true
Programming
with Schemas
malli.util
• Schemas can be transformed, just like data
• Pre- & postwalk for generic walking over schemas
• update-properties, get, assoc, update, get-in, assoc-in, update-in, dissoc,
select-keys, …
• subschemas for
• Backed by the Schema & LensSchema protocols
Dev-
tooling
Function Schemas
• (Higher order) functions can also be described with Malli
• Any existing ClojureVar can be annotated with Malli Schemas
• Support multi-rarities with custom return values for each
• Does not support varargs (WIP, the sequence schemas)
• Integrates to CLJ-kondo, plumatic schema style inline schemas WIP
• Aave, Ghostwheel-port for Malli (https://github.com/teknql/aave)
CLJS
• Designed to be light, DCE can remove most of the unneeded core
• Starts from few kilos zipped (validation with minimal registry)
GraalVM
• Works on GraalVM too, binaries starting from 14mb
Malli 1.0.0
Malli 1.0.0
• Support for sequence schemas (WIP, Pauli)
• Support for Schema parsing
• Protocol-based Fast Schema Inferrer
• Describe Malli Schemas with Malli (recall spec-of-specs)
• Expound-grade pretty printer (WIP)
• Proper documentation
• Re-visit some design decision (including the global registry)
Wrap-up
Designing with Malli
• Where was the designing part??? ;)
• Malli in a clean slate fusion of the best parts of existing libraries
(plumatic schema and clojure.spec)
• In alpha, under active development
• Lot’s of ideas, so little (extra) time, help welcome
• Try reitit-malli to get started…

More Related Content

What's hot

Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...
Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...
Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...Monica Beckwith
 
JupyterHub - A "Thing Explainer" Overview
JupyterHub - A "Thing Explainer" OverviewJupyterHub - A "Thing Explainer" Overview
JupyterHub - A "Thing Explainer" OverviewCarol Willing
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐりKazuyuki TAKASE
 
プログラミング言語とシステムデザイン
プログラミング言語とシステムデザインプログラミング言語とシステムデザイン
プログラミング言語とシステムデザインTsutomu Yano
 
Extending Flink SQL for stream processing use cases
Extending Flink SQL for stream processing use casesExtending Flink SQL for stream processing use cases
Extending Flink SQL for stream processing use casesFlink Forward
 
WebRTC multitrack / multistream
WebRTC multitrack / multistreamWebRTC multitrack / multistream
WebRTC multitrack / multistreammganeko
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Metosin Oy
 
ClojureではじめるSTM入門
ClojureではじめるSTM入門ClojureではじめるSTM入門
ClojureではじめるSTM入門sohta
 
Hot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect ForwardingHot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect ForwardingAndrey Upadyshev
 
Care and Feeding of Catalyst Optimizer
Care and Feeding of Catalyst OptimizerCare and Feeding of Catalyst Optimizer
Care and Feeding of Catalyst OptimizerDatabricks
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.specKent Ohashi
 
Microservices OSGi-running-with-apache-karaf
Microservices OSGi-running-with-apache-karafMicroservices OSGi-running-with-apache-karaf
Microservices OSGi-running-with-apache-karafAchim Nierbeck
 
Spark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in Spark
Spark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in SparkSpark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in Spark
Spark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in SparkBo Yang
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニックGenya Murakami
 
DWARF Data Representation
DWARF Data RepresentationDWARF Data Representation
DWARF Data RepresentationWang Hsiangkai
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...Philip Schwarz
 
Blazing Performance with Flame Graphs
Blazing Performance with Flame GraphsBlazing Performance with Flame Graphs
Blazing Performance with Flame GraphsBrendan Gregg
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Scott Wlaschin
 

What's hot (20)

Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...
Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...
Garbage First Garbage Collector (G1 GC) - Migration to, Expectations and Adva...
 
JupyterHub - A "Thing Explainer" Overview
JupyterHub - A "Thing Explainer" OverviewJupyterHub - A "Thing Explainer" Overview
JupyterHub - A "Thing Explainer" Overview
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
 
プログラミング言語とシステムデザイン
プログラミング言語とシステムデザインプログラミング言語とシステムデザイン
プログラミング言語とシステムデザイン
 
Extending Flink SQL for stream processing use cases
Extending Flink SQL for stream processing use casesExtending Flink SQL for stream processing use cases
Extending Flink SQL for stream processing use cases
 
WebRTC multitrack / multistream
WebRTC multitrack / multistreamWebRTC multitrack / multistream
WebRTC multitrack / multistream
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
 
ClojureではじめるSTM入門
ClojureではじめるSTM入門ClojureではじめるSTM入門
ClojureではじめるSTM入門
 
Hot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect ForwardingHot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect Forwarding
 
Care and Feeding of Catalyst Optimizer
Care and Feeding of Catalyst OptimizerCare and Feeding of Catalyst Optimizer
Care and Feeding of Catalyst Optimizer
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.spec
 
Microservices OSGi-running-with-apache-karaf
Microservices OSGi-running-with-apache-karafMicroservices OSGi-running-with-apache-karaf
Microservices OSGi-running-with-apache-karaf
 
Spark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in Spark
Spark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in SparkSpark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in Spark
Spark Shuffle Deep Dive (Explained In Depth) - How Shuffle Works in Spark
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 
DWARF Data Representation
DWARF Data RepresentationDWARF Data Representation
DWARF Data Representation
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
 
Blazing Performance with Flame Graphs
Blazing Performance with Flame GraphsBlazing Performance with Flame Graphs
Blazing Performance with Flame Graphs
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
 
Effective CMake
Effective CMakeEffective CMake
Effective CMake
 

Similar to Designing with malli

Parallel SQL and Analytics with Solr: Presented by Yonik Seeley, Cloudera
Parallel SQL and Analytics with Solr: Presented by Yonik Seeley, ClouderaParallel SQL and Analytics with Solr: Presented by Yonik Seeley, Cloudera
Parallel SQL and Analytics with Solr: Presented by Yonik Seeley, ClouderaLucidworks
 
ELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardGeorg Sorst
 
State of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open SourceState of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open SourceOSCON Byrum
 
Megamodeling of Complex, Distributed, Heterogeneous CPS Systems
Megamodeling of Complex, Distributed, Heterogeneous CPS SystemsMegamodeling of Complex, Distributed, Heterogeneous CPS Systems
Megamodeling of Complex, Distributed, Heterogeneous CPS SystemsEugenio Villar
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsMatt Stubbs
 
Scalding big ADta
Scalding big ADtaScalding big ADta
Scalding big ADtab0ris_1
 
Real-Time Analytics with Solr: Presented by Yonik Seeley, Cloudera
Real-Time Analytics with Solr: Presented by Yonik Seeley, ClouderaReal-Time Analytics with Solr: Presented by Yonik Seeley, Cloudera
Real-Time Analytics with Solr: Presented by Yonik Seeley, ClouderaLucidworks
 
Reigniting the API Description Wars with TypeSpec and the Next Generation of ...
Reigniting the API Description Wars with TypeSpec and the Next Generation of...Reigniting the API Description Wars with TypeSpec and the Next Generation of...
Reigniting the API Description Wars with TypeSpec and the Next Generation of ...Nordic APIs
 
Streaming Solr - Activate 2018 talk
Streaming Solr - Activate 2018 talkStreaming Solr - Activate 2018 talk
Streaming Solr - Activate 2018 talkAmrit Sarkar
 
Building Analytics Applications with Streaming Expressions in Apache Solr - A...
Building Analytics Applications with Streaming Expressions in Apache Solr - A...Building Analytics Applications with Streaming Expressions in Apache Solr - A...
Building Analytics Applications with Streaming Expressions in Apache Solr - A...Lucidworks
 
2019 hashiconf consul-templaterb
2019 hashiconf consul-templaterb2019 hashiconf consul-templaterb
2019 hashiconf consul-templaterbPierre Souchay
 
Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015eddiebaggott
 
ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale Subbu Allamaraju
 
Clojure ♥ cassandra
Clojure ♥ cassandra Clojure ♥ cassandra
Clojure ♥ cassandra Max Penet
 
The Aggregation Framework
The Aggregation FrameworkThe Aggregation Framework
The Aggregation FrameworkMongoDB
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomyDongmin Yu
 

Similar to Designing with malli (20)

Parallel SQL and Analytics with Solr: Presented by Yonik Seeley, Cloudera
Parallel SQL and Analytics with Solr: Presented by Yonik Seeley, ClouderaParallel SQL and Analytics with Solr: Presented by Yonik Seeley, Cloudera
Parallel SQL and Analytics with Solr: Presented by Yonik Seeley, Cloudera
 
ELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboard
 
State of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open SourceState of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open Source
 
Megamodeling of Complex, Distributed, Heterogeneous CPS Systems
Megamodeling of Complex, Distributed, Heterogeneous CPS SystemsMegamodeling of Complex, Distributed, Heterogeneous CPS Systems
Megamodeling of Complex, Distributed, Heterogeneous CPS Systems
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
 
SVGD3Angular2React
SVGD3Angular2ReactSVGD3Angular2React
SVGD3Angular2React
 
Scalding big ADta
Scalding big ADtaScalding big ADta
Scalding big ADta
 
Real-Time Analytics with Solr: Presented by Yonik Seeley, Cloudera
Real-Time Analytics with Solr: Presented by Yonik Seeley, ClouderaReal-Time Analytics with Solr: Presented by Yonik Seeley, Cloudera
Real-Time Analytics with Solr: Presented by Yonik Seeley, Cloudera
 
Om nom nom nom
Om nom nom nomOm nom nom nom
Om nom nom nom
 
Angular2 for Beginners
Angular2 for BeginnersAngular2 for Beginners
Angular2 for Beginners
 
Reigniting the API Description Wars with TypeSpec and the Next Generation of ...
Reigniting the API Description Wars with TypeSpec and the Next Generation of...Reigniting the API Description Wars with TypeSpec and the Next Generation of...
Reigniting the API Description Wars with TypeSpec and the Next Generation of ...
 
Azure F#unctions
Azure F#unctionsAzure F#unctions
Azure F#unctions
 
Streaming Solr - Activate 2018 talk
Streaming Solr - Activate 2018 talkStreaming Solr - Activate 2018 talk
Streaming Solr - Activate 2018 talk
 
Building Analytics Applications with Streaming Expressions in Apache Solr - A...
Building Analytics Applications with Streaming Expressions in Apache Solr - A...Building Analytics Applications with Streaming Expressions in Apache Solr - A...
Building Analytics Applications with Streaming Expressions in Apache Solr - A...
 
2019 hashiconf consul-templaterb
2019 hashiconf consul-templaterb2019 hashiconf consul-templaterb
2019 hashiconf consul-templaterb
 
Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015
 
ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale ql.io: Consuming HTTP at Scale
ql.io: Consuming HTTP at Scale
 
Clojure ♥ cassandra
Clojure ♥ cassandra Clojure ♥ cassandra
Clojure ♥ cassandra
 
The Aggregation Framework
The Aggregation FrameworkThe Aggregation Framework
The Aggregation Framework
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 

More from Metosin Oy

Navigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas SaariMetosin Oy
 
Where is Technical Debt?
Where is Technical Debt?Where is Technical Debt?
Where is Technical Debt?Metosin Oy
 
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...Metosin Oy
 
Serverless Clojure and ML prototyping: an experience report
Serverless Clojure and ML prototyping: an experience reportServerless Clojure and ML prototyping: an experience report
Serverless Clojure and ML prototyping: an experience reportMetosin Oy
 
Naked Performance With Clojure
Naked Performance With ClojureNaked Performance With Clojure
Naked Performance With ClojureMetosin Oy
 
Fun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Fun with errors? - Clojure Finland Meetup 26.3.2019 TampereFun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Fun with errors? - Clojure Finland Meetup 26.3.2019 TampereMetosin Oy
 
Clojutre Real Life (2012 ClojuTRE Retro Edition)
Clojutre Real Life (2012 ClojuTRE Retro Edition)Clojutre Real Life (2012 ClojuTRE Retro Edition)
Clojutre Real Life (2012 ClojuTRE Retro Edition)Metosin Oy
 
The Ancient Art of Data-Driven - reitit, the library -
The Ancient Art of Data-Driven - reitit, the library - The Ancient Art of Data-Driven - reitit, the library -
The Ancient Art of Data-Driven - reitit, the library - Metosin Oy
 
Craft Beer & Clojure
Craft Beer & ClojureCraft Beer & Clojure
Craft Beer & ClojureMetosin Oy
 
Performance and Abstractions
Performance and AbstractionsPerformance and Abstractions
Performance and AbstractionsMetosin Oy
 
ClojuTRE2016 Opening slides
ClojuTRE2016 Opening slidesClojuTRE2016 Opening slides
ClojuTRE2016 Opening slidesMetosin Oy
 
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016Metosin Oy
 
ClojuTRE - a (very) brief history
ClojuTRE - a (very) brief historyClojuTRE - a (very) brief history
ClojuTRE - a (very) brief historyMetosin Oy
 
Wieldy remote apis with Kekkonen - ClojureD 2016
Wieldy remote apis with Kekkonen - ClojureD 2016Wieldy remote apis with Kekkonen - ClojureD 2016
Wieldy remote apis with Kekkonen - ClojureD 2016Metosin Oy
 
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesomeClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesomeMetosin Oy
 
Clojure in real life 17.10.2014
Clojure in real life 17.10.2014Clojure in real life 17.10.2014
Clojure in real life 17.10.2014Metosin Oy
 
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesomeEuroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesomeMetosin Oy
 
Swaggered web apis in Clojure
Swaggered web apis in ClojureSwaggered web apis in Clojure
Swaggered web apis in ClojureMetosin Oy
 

More from Metosin Oy (18)

Navigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas Saari
 
Where is Technical Debt?
Where is Technical Debt?Where is Technical Debt?
Where is Technical Debt?
 
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
Creating an experimental GraphQL formatter using Clojure, Instaparse, and Gra...
 
Serverless Clojure and ML prototyping: an experience report
Serverless Clojure and ML prototyping: an experience reportServerless Clojure and ML prototyping: an experience report
Serverless Clojure and ML prototyping: an experience report
 
Naked Performance With Clojure
Naked Performance With ClojureNaked Performance With Clojure
Naked Performance With Clojure
 
Fun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Fun with errors? - Clojure Finland Meetup 26.3.2019 TampereFun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
Fun with errors? - Clojure Finland Meetup 26.3.2019 Tampere
 
Clojutre Real Life (2012 ClojuTRE Retro Edition)
Clojutre Real Life (2012 ClojuTRE Retro Edition)Clojutre Real Life (2012 ClojuTRE Retro Edition)
Clojutre Real Life (2012 ClojuTRE Retro Edition)
 
The Ancient Art of Data-Driven - reitit, the library -
The Ancient Art of Data-Driven - reitit, the library - The Ancient Art of Data-Driven - reitit, the library -
The Ancient Art of Data-Driven - reitit, the library -
 
Craft Beer & Clojure
Craft Beer & ClojureCraft Beer & Clojure
Craft Beer & Clojure
 
Performance and Abstractions
Performance and AbstractionsPerformance and Abstractions
Performance and Abstractions
 
ClojuTRE2016 Opening slides
ClojuTRE2016 Opening slidesClojuTRE2016 Opening slides
ClojuTRE2016 Opening slides
 
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
Schema tools-and-trics-and-quick-intro-to-clojure-spec-22.6.2016
 
ClojuTRE - a (very) brief history
ClojuTRE - a (very) brief historyClojuTRE - a (very) brief history
ClojuTRE - a (very) brief history
 
Wieldy remote apis with Kekkonen - ClojureD 2016
Wieldy remote apis with Kekkonen - ClojureD 2016Wieldy remote apis with Kekkonen - ClojureD 2016
Wieldy remote apis with Kekkonen - ClojureD 2016
 
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesomeClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
 
Clojure in real life 17.10.2014
Clojure in real life 17.10.2014Clojure in real life 17.10.2014
Clojure in real life 17.10.2014
 
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesomeEuroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
 
Swaggered web apis in Clojure
Swaggered web apis in ClojureSwaggered web apis in Clojure
Swaggered web apis in Clojure
 

Recently uploaded

The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningVitsRangannavar
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 

Recently uploaded (20)

The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learning
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 

Designing with malli

  • 2. a new data validation and specification library for Clojure/Script. It provides unified tools for building data-driven schema systems covering schema definition, validation, (human) errors, value and schema transformation, value and schema generation, registries and much more. https://github.com/metosin/malli Malli
  • 3. (def address {:id "123" :tags #{:garage :chicken} :address {:street "Jl. Pacar No.15, Sumerta Kauh" :city "Densapar" :zip 80236 :latlon [-8.652037 115.226808]}}) data
  • 4. (def Address {:id s/Str :tags #{s/Keyword} :address {:street s/Str :city s/Str :zip s/Int :latlon [(s/one Double "lat") (s/one Double "lon")]}}) plumatic schema
  • 5. (require '[clojure.spec.alpha :as s]) (s/def ::id string?) (s/def ::tags (s/coll-of keyword? :kind set?)) (s/def ::street string?) (s/def ::city string?) (s/def ::zip int?) (s/def ::latlon (s/tuple double? double?)) (s/def :address/address (s/keys :req-un [::street ::city ::zip ::latlon])) (s/def ::address (s/keys :req-un [::id ::tags :address/address])) clojure.spec
  • 6. (def Address [:map [:id string?] [:tags [:set keyword?]] [:address [:map [:street string?] [:city string?] [:zip int?] [:latlon [:tuple double? double?]]]]]) Hiccup syntax Just data and functions Maps are open by default Keys are required by default Malli Ordered Keys
  • 7. (def Address [:map [:id string?] [:tags [:set keyword?]] [:address [:map [:street string?] [:city string?] [:zip int?] [:latlon [:tuple double? double?]]]]]) Malli
  • 8. (def Address [:map {:title “Address” :summary “An address"} [:id string?] [:tags {:optional true} [:set keyword?]] [:address [:map {:closed true} [:street string?] [:city string?] [:zip {:default "33800"} int?] [:latlon [:tuple double? double?]]]]]) Malli
  • 9. Schema applications • Validation and Machine-readable errors • Spell-checking and human-readable errors • Two-way value transformations • Schema transformations (walkers, visitors, utils, JSON Schema, DOT, ..) • GeneratingValues & Schemas • (Parsing)
  • 10. (def invalid-address {:id 123 :tags #{:garage :chicken} :address {:streetz "Jl. Pacar No.15" :city "Densapar" :latlon [-8.652037 115.226808]}}) (-> Address (m/explain invalid-address) (me/with-spell-checking) (me/humanize)) ;{:id ["should be a string"] ; :address {:zip ["missing required key"] ; :streetz ["should be spelled :street"]}}
  • 11. (require '[malli.generator :as mg]) (mg/generate Address {:size 10, :seed 20}) ;{:id "A1f05U4uE5", ; :tags #{:FqNN/Ti. :b3/h. :Ni/h? :Yg*-/GW*Y :jhL/k! :_/QnR}, ; :address {:street "ABM74Q96S4" ; :city "k6z3OD4cy" ; :zip -1 ; :latlon [-0.32421875 -1.8125]}}
  • 13. Registries • Schema types are looked from a registry • Registry is passed as explicit option into schema functions • Default registry has ~100 types and is immutable • Other registry types: mutable, dynamic, lazy, local and composite • Special JVM / Closure compiler option to swap the default registry • Default to global mutable registry in Malli 1.0.0?
  • 14. (def Order [:schema {:registry {"Country" [:map [:name [:enum :FI :PO]] [:neighbors [:vector [:ref "Country"]]]] "Burger" [:map [:name string?] [:description {:optional true} string?] [:origin [:maybe "Country"]] [:price pos-int?]] "OrderLine" [:map [:burger "Burger"] [:amount int?]] "Order" [:map [:lines [:vector "OrderLine"]] [:delivery [:map [:delivered boolean?] [:address [:map [:street string?] [:zip int?] [:country "Country"]]]]]]}} "Order"])
  • 15.
  • 17. (s/def :address/id string?) (s/def :address/tags (s/coll-of keyword? :kind set?)) (s/def :address/street string?) (s/def :address/city string?) (s/def :address/zip int?) (s/def :address/latlon (s/tuple double? double?)) (s/def :address.address/address (s/keys :req [::street ::city ::zip ::latlon])) (s/def :address/address (s/keys :req [::id ::tags :address/address]))
  • 18. [:schema {:registry {::id string? ::tags [:set keyword?] ::street string? ::city string? ::zip int? ::latlon [:tuple double? double?] :address/address [:map ::street ::city ::zip ::latlon] ::address [:map ::id ::tags :address/address]}} ::address]
  • 19. [:map {:registry {::id string? ::tags [:set keyword?] ::address [:map {:registry {::street string? ::city string? ::zip int? ::latlon [:tuple double? double?]}} ::street ::city ::zip ::latlon]}} ::id ::tags ::address]
  • 21. Coercion • We are dealing with various data sources with different capabilities, e.g. JSON,YAML and XML data • We need to decode from X to EDN and encode from EDN to X’ • … or just apply default values. Or convert strings into keyword keys • Malli has fast two-way interceptor-based transformers • Transforming based on Schema type and properties
  • 22. (def Address [:map {:title “Address” :summary “An address"} [:id string?] [:tags {:optional true} [:set keyword?]] [:address [:map {:closed true} [:street string?] [:city string?] [:zip {:default "33800"} int?] [:latlon [:tuple double? double?]]]]])
  • 23. (require '[malli.transform :as mt]) (m/decode Address {:id "123" :tags [“garage” “chicken”] :address {:street "Jl. Pacar No.15" :city "Densapar" :zip 80236 :latlon [-8.652037 115.226808]}} (mt/json-transformer)) ;{:id "123" ; :tags #{:garage :chicken}, ; :address {:street "Jl. Pacar No.15, Sumerta Kauh, Kec." ; :city "Densapar" ; :zip 80236 ; :latlon [-8.652037 115.226808]}}
  • 24. (m/decode Address {:id "Lillan" :EVIL "LYN" :tags ["coffee" "artesan" "garden"] :address {:street "Ahlmanintie 29" :DARK "ORKO" :city "Tampere" :lonlat [61.4858322 23.7854658]}} (mt/transformer (mt/strip-extra-keys-transformer) (mt/default-value-transformer) (mt/json-transformer))) ;{:id "Lillan" ; :tags #{:coffee :artesan :garden} ; :address {:street "Ahlmanintie 29" ; :city "Tampere" ; :zip "33800"}}
  • 25. (def LegacyString [:string {:decode/string '(fn [x] (str/lower-case (subs x 4))) :encode/string '(fn [x] (str/upper-case (str "HAL_" x)))}]) (m/decode LegacyString "HAL_KIKKA" (mt/string-transformer)) ; => "kikka" (m/encode LegacyString "kikka" (mt/string-transformer)) ; => "HAL_KIKKA" (m/decode [:string {:decode/string {:enter '#(str "olipa_" %) :leave '#(str % "_avaruus")}}] "kerran" (mt/string-transformer)) ; => "olipa_kerran_avaruus"
  • 26.
  • 27. Inferring values • Opposite of GeneratingValues - return a Schema that validates against the sample values • Crawled legacy MongoDB collection (5+ years of accumulated stuff) • For each value, inferred a schema + accumulated schema union • All documents have timestamps —>Temporal Schema index!
  • 28. (require '[malli.provider :as mp]) (mp/provide [{:id "123" :tags #{:garage :chicken} :address {:street "Jl. Pacar No.15, Sumerta Kauh, Kec." :city "Densapar" :zip 80236 :latlon [-8.652037 115.226808]}} {:id "Lillan" :tags #{:coffee :artesan :garden} :address {:street "Ahlmanintie 29" :city "Tampere" :lonlat [61.4858322 23.7854658]}}]) ;[:map ; [:id string?] ; [:tags [:set keyword?]] ; [:address ; [:map ; [:street string?] ; [:city string?] ; [:zip {:optional true} int?] ; [:latlon {:optional true} [:vector double?]] ; [:lonlat {:optional true} [:vector double?]]]]]
  • 29. Serialising Schemas • Thanks to SCI (https://github.com/borkdude/sci) and Edamame (https://github.com/borkdude/edamame), mostly all schemas can be • Thanks to SCI (https://github.com/borkdude/sci) and Edamame (https://github.com/borkdude/edamame), mostly all schemas can be persisted (and read back) to EDN • Works with all of clj (JVM & GraalVM) and cljs, no eval needed • Big leverage in building truly dynamic systems • Playground at malli.io
  • 30. (def Adult [:map {:registry {::age [:and int? [:> 18]]}} [:age ::age]]) (-> Adult (malli.edn/write-string) (malli.edn/read-string) (m/validate {:age 46})) ; => true
  • 32. malli.util • Schemas can be transformed, just like data • Pre- & postwalk for generic walking over schemas • update-properties, get, assoc, update, get-in, assoc-in, update-in, dissoc, select-keys, … • subschemas for • Backed by the Schema & LensSchema protocols
  • 33.
  • 34.
  • 36. Function Schemas • (Higher order) functions can also be described with Malli • Any existing ClojureVar can be annotated with Malli Schemas • Support multi-rarities with custom return values for each • Does not support varargs (WIP, the sequence schemas) • Integrates to CLJ-kondo, plumatic schema style inline schemas WIP • Aave, Ghostwheel-port for Malli (https://github.com/teknql/aave)
  • 37. CLJS • Designed to be light, DCE can remove most of the unneeded core • Starts from few kilos zipped (validation with minimal registry)
  • 38. GraalVM • Works on GraalVM too, binaries starting from 14mb
  • 39.
  • 41. Malli 1.0.0 • Support for sequence schemas (WIP, Pauli) • Support for Schema parsing • Protocol-based Fast Schema Inferrer • Describe Malli Schemas with Malli (recall spec-of-specs) • Expound-grade pretty printer (WIP) • Proper documentation • Re-visit some design decision (including the global registry)
  • 43. Designing with Malli • Where was the designing part??? ;) • Malli in a clean slate fusion of the best parts of existing libraries (plumatic schema and clojure.spec) • In alpha, under active development • Lot’s of ideas, so little (extra) time, help welcome • Try reitit-malli to get started…