SlideShare a Scribd company logo
Malli: inside data-driven schemas
Inside
Data-driven
Schemas
Tommi Reiman
29.2.2019
ClojureD
malli
Malli: inside data-driven schemas
Malli: inside data-driven schemas
Chapter 1:
Expectations
• Data-oriented - represent entities and their relationships as data.
• Data-driven - create DSLs in data structures and write interpreters for
them
Clojure <3 Data
https:!"clojureverse.org/t/clojure-a-pragmatic-data-driven-language/4565/5Eric Normand
Malli: inside data-driven schemas
It’s just data!
;; restaurant
{:name "Lie Mi"
:tags #{:street :vietnamese}
:stars 4.3
:address {:street "Hämeenkatu 14"
:city “Tampere"}}
It’s just data!
{:type :restaurant
:name "Lie Mi"
:tags #{:street :vietnamese}
:stars 4.3
:address {:street "Hämeenkatu 14"
:city “Tampere"}}
It’s just data!
{:type :customers.1234/restaurant
:name "Lie Mi"
:tags #{:street :vietnamese}
:stars 4.3
:address {:street "Hämeenkatu 14"
:city “Tampere"}}
It’s just data!
{:mydomain/type :mydomain.types/restaurant
:mydomain.restaurant/name "Lie Mi"
:mydomain.restaurant/tags #$:street :vietnamese}
:mydomain.restaurant/stars 4.3
:mydomain.restaurant/address {:mydomain.address/street "Hämeenkatu 14"
:mydomain.address/city "Tampere"}}
It’s just data!
{:type :restaurant
:name "Lie Mi"
:tags #{:street :vietnamese}
:stars 4.3
:address {:street "Hämeenkatu 14”
:city "Tampere"}}
It’s just data!
(-> {:type :restaurant
:name "Lie Mi"
:tags #{:street :vietnamese}
:stars 4.3
:address {:street "Hämeenkatu 14"
:city "Tampere"}})
(select-keys [:name :tags :address]))
(assoc-in [:address :zip] 33100))
;{:name "Lie Mi"
; :tags #{:vietnamese :street}
; :address {:street "Hämeenkatu 14"
; :city "Tampere"
; :zip 33100}}
https:!"devrant.com/rants/2192467/on-category-theory
Types, Schemas and Specs
Malcolm 16:45
Awesome!
Awesome!
Awesome!
One tool for everything?
Expectations
We are building dynamic multi-tenant systems where data-
models should be data too: they should drive the runtime value
transformations, forms and processes.We should be able to edit
the models at runtime, persist them and load them back from
database and over the wire, for both Clojure and ClojureScript.
Think of JSON Schema, but for EDN and Clojure/Script.
If you have expectations (of others) that aren't
being met, those expectations are your own
responsibility.You are responsible for your own
needs. If you want things, make them.
- Rich Hickey
https:!"gist.github.com/richhickey/1563cddea1002958f96e7ba9519972d9
Chapter 2:
DIY
The Idea
• Schemas as data (hiccup, reagent, internal.*, reitit)
• Take the best parts of Plumatic Schema, clojure.spec & JSON Schema
• Programming with Schemas, first class meta-data
• Focus on Developer Experience
• Small core, extendable
• Create a Prototype, experiment, have fun
Malli
/ˈmɑlːi/, [ˈmɑlːi]
Syntax (Schema AST)
[:vector {:min 0, :max 10} int?]
type %& [type ?properties & children]
{:type :vector
:properties {:min 0, :max 10}
:children [int?]}
Schemas
int?
[:= 43]
[:tuple double? double?]
[:and int? [:> 18]]
[:map
[:x int?]
[:y int?]]
AST '( (resolve) '( IntoSchema opts '( Schema
Validation
(require '[malli.core :as m])
(m/validate int? 1)
; => true
(m/validate int? "kikka")
; => false
(m/validate [:maybe keyword?] nil)
; => true
(m/validate [:vector int?] [1 2 3])
; => true
Complex Schema
(def CompositeMap
[:and
[:map {:closed true}
[:x pos-int?]
[:y pos-int?]]
[:fn {:error/message "x )* y"}
(fn [{:keys [x y]}] (> x y))]])
(m/validate CompositeMap {:x 3, :y 2})
; '( true
(m/validate CompositeMap {:x 1, :y 2})
; '( false
Complex Schema
(def CompositeMap
[:and
[:map {:closed true}
[:x pos-int?]
[:y pos-int?]]
[:fn {:error/message "x )* y"}
'(fn [{:keys [x y]}] (> x y))]])
(m/validate CompositeMap {:x 3, :y 2})
; '( true
(m/validate CompositeMap {:x 1, :y 2})
; '( falseMichiel Borkent
Forms
(def CompositeMap
[:and
[:map {:closed true}
[:x pos-int?]
[:y pos-int?]]
[:fn {:error/message "x )* y"}
'(fn [{:keys [x y]}] (> x y))]])
(m/form CompositeMap)
;[:and
; [:map {:closed true}
; [:x pos-int?]
; [:y pos-int?]]
; [:fn {:error/message "x )* y"}
; (fn [{:keys [x y]}] (> x y))]]
• Works on all of JVM, ClojureScript & GraalVM
Durable Schemas
Michiel Borkent
(require '[malli.edn :as edn])
(+, CompositeMap
(edn/write-string)
(edn/read-string)
(m/validate {:x 3, :y 2}))
; '( true
• Inspired by clojure.spec
Explaining Data
(m/explain CompositeMap {:x -1, :y -2, :EXTRA true})
;{:schema …,
; :value {:x -1, :y -2, :EXTRA true},
; :errors [{:path [1 2 1], :in [:x], :schema pos-int?, :value -1}
; {:path [1 3 1], :in [:y], :schema pos-int?, :value -2}
; {:path [1], :in [:EXTRA], :schema …, :type :malli.core/extra-key}]}
AlexRich
Errors for Humans
(require '[malli.error :as me])
(+, CompositeMap
(m/explain {:x -3, :y -2, :EXTRA true})
(me/humanize))
;{:x ["should be positive int"]
; :y ["should be positive int"]
; :EXTRA ["disallowed key"]
; :malli/error ["x )* y"]}
Alexander Kiel
GeneratingValues
(require '[malli.generator :as mg])
(mg/generate keyword?)
; '( :?
(mg/generate [:enum "a" "b" "c"] {:seed 42})
; '( "a"
(mg/generate
[:re #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9-.]+.[a-zA-Z]{2,63}$"]
{:seed 42, :size 10})
; '( "CaR@MavCk70OHiX.yZ"
GeneratingValues
(mg/generate
[:and {:gen/elements ["kikka" "kukka" "kakka"]} string?])
; '( "kikka"
(mg/generate
[:and {:gen/fmap '(partial str "kikka_")} string?]
{:seed 10, :size 10})
/0 '( "kikka_WT3K0yax2"
(require '[clojure.test.check.generators :as gen])
(mg/generate
[:sequential {:gen/gen (gen/list gen/neg-int)} int?]
{:size 42, :seed 42})
; '( (-37 -13 -13 -24 -20 -11 -34 -40 -22 0 -10)
Gary Frederics
Inferring Schemas
(def lie-mi
{:type :restaurant
:name "Lie Mi"
:tags #$:street :vietnamese}
:stars 4.3
:address {:street "Hämeenkatu 14"
:city "Tampere"}})
(def wanha-tappi
{:type :restaurant
:name "Wanha Tappi"
:tags #$:burgers :beer}
:address {:street "Jokipohjantie 18"
:city "Tampere"}})
Stathis Sideris
(require '[malli.provider :as mp])
(def Restaurant
(mp/provide [lie-mi wanha-tappi]))
Restaurant
;[:map
; [:type keyword?]
; [:name string?]
; [:tags [:set keyword?]]
; [:stars {:optional true} double?]
; [:address
; [:map
; [:street string?]
; [:city string?]]]]
Programming with Schemas
(require '[malli.util :as mu])
(+, [:map
[:a int?]
[:b string?]
[:c [:map
[:d int?]
[:e keyword?]]]]
(mu/closed-schema)
(mu/select-keys [:a :c])
(mu/update-in [:c] mu/dissoc :e))
;[:map {:closed true}
; [:a int?]
; [:c [:map {:closed true}
; [:d int?]]]]
Metosin
Walking over Schemas
• Generic schema walking using theVisitor-pattern (CLJ-2251)
• To JSON Schema, Swagger2, Map-syntax etc.
(require '[malli.json-schema :as json-schema])
(json-schema/transform
[:map {:title "a map"}
[:x int?]
[:y {:optional true} inst?]])
;{:type "object"
; :title "a map"
; :properties {:x {:type "integer", :format "int64"}
; :y {:type "string", :format "date-time"}
; :required [:x]}
Walking over Schemas
(defn closed-schema
"Closes recursively all :map schemas by adding `{:closed true}`
property, unless schema explicitely open with `{:closed false}`"
([schema]
(closed-schema schema nil))
([schema options]
(m/accept
schema
(m/schema-visitor
(fn [schema]
(if (-open-map? schema options)
(update-properties schema c/assoc :closed true)
schema))))))
Malli: inside data-driven schemas
• Open Schemas to embrace growth (and typing errors)
• Closed Schemas and Spell Checking to the rescue?
Spell Checking
(def nante-eck
{:type :restaurant
:name "Nante-Eck"
:tags #$:traditional :vegan}
:starz 4.2
:address {:streez "Unter den Linden 35"
:city "Berlin"}})
Restaurant
;[:map
; [:type keyword?]
; [:name string?]
; [:tags [:set keyword?]]
; [:stars {:optional true} double?]
; [:address
; [:map
; [:street string?]
; [:city string?]]]]
Spell Checking
(+, Restaurant
(m/explain nante-eck)
(me/humanize))
; {:address {:street ["missing required key"]}}
(+, Restaurant
(mu/closed-schema)
(m/explain nante-eck)
(me/humanize))
;{:address {:street ["missing required key"]
; :streez ["disallowed key"]}
; :starz ["disallowed key"]}
(+, Restaurant
(mu/closed-schema)
(m/explain nante-eck)
(me/with-spell-checking)
(me/humanize))
;{:address {:streez ["should be spelled :street"]}
; :starz ["should be spelled :stars"]}
Bruce Hauman
• Fully re-written engine, built with interceptors
• Encode and decode chains with enter & leave phases
• Json, string, strip-extra-keys & default-value-transformer
• Schemas can define transformation via properties
• Fast
ValueTransformers
(m/decode int? "42" (mt/string-transformer))
; '( 42
(m/encode int? 42 (mt/string-transformer))
; '( ”42”
(require '[malli.transform :as mt])
(def json-transformer
(mt/transformer
(mt/strip-extra-keys-transformer)
(mt/json-transformer)
(mt/default-value-transformer)))
(def json+,Restaurant
(m/decoder Restaurant json-transformer))
(json+,Restaurant
{:type "restaurant"
:DARK "ORKO"
:name "Mustafas Gemüse Kebab"
:tags ["kebab" "yoghurt"]
:address {:street "Mehringdamm 32"
:EXTRA "KEY"
:city "Berlin"}})
;{:type :restaurant,
; :name "Mustafas Gemüse Kebab",
; :tags #$:kebab :yoghurt},
; :address {:street "Mehringdamm 32"
; :city "Berlin"}}
(require '[criterium.core :as cc])
/0 1.8µs
(cc/quick-bench
(+, json
(update :type keyword)
(update :tags (comp set (partial map keyword)))
(select-keys [:type :name :tags :address])
(update :address select-keys [:street :city])))
/0 1.9µs
(cc/quick-bench (json+,Restaurant json))
(def json+,Order
(m/decoder
[:map
[:id int?]
[:tags string?]
[:address
[:map
[:street string?]
[:zip string?]
[:country string?]]]]
(mt/json-transformer)))
json+,Order
; '( #object[clojure.core$identity]
(require '[criterium.core :as cc])
/0 1.8µs
(cc/quick-bench
(+, json
(update :type keyword)
(update :tags (comp set (partial map keyword)))
(select-keys [:type :name :tags :address])
(update :address select-keys [:street :city])))
/0 1.9µs
(cc/quick-bench (json+,Restaurant json))
(def json+,Order
(m/decoder
[:map
[:id int?]
[:tags [:vector string?]]
[:address
[:map
[:street string?]
[:zip string?]
[:country string?]]]]
(mt/json-transformer)))
json+,Order
; '( #object[clojure.core$identity]
(require '[criterium.core :as cc])
/0 1.8µs
(cc/quick-bench
(+, json
(update :type keyword)
(update :tags (comp set (partial map keyword)))
(select-keys [:type :name :tags :address])
(update :address select-keys [:street :city])))
/0 1.9µs
(cc/quick-bench (json+,Restaurant json))
(def json+,Order
(m/decoder
[:map
[:id int?]
[:tags [:vector string?]]
[:address
[:map
[:street string?]
[:zip string?]
[:country string?]]]]
(mt/json-transformer)))
json+,Order
; '( #object[clojure.core$identity]
Chapter 3:
The Future
• reitit-malli coercion module, since 0.4.0
• Orders of magnitude faster coercion than with reitit-spec
• Small example application: https://github.com/metosin/reitit/tree/
master/examples/ring-malli-swagger
• A new module & configuration system?
reitit + malli
• … and custom Schemas to inline external stuff, maybe like:
Schema providers (F#)
(m/validate
[:json-schema
{:type "object"
:properties {:x {:type "integer", :format "int64"}
:y {:type "integer", :format "int64"}}
:required [:x]}]
{:x 1, :y 2})
; => true
• Have generated forms in four decades, just one more time ;)
• Good companion for FSMs and rule engines, rapid prototyping
• https://www.youtube.com/watch?v=IekPZpfbdaI
• https://github.com/domino-clj + malli
Generating UIs
Dmitri Carmen Nikola
Schema '( UI %& Schema UI-Schema '( UI
• Inspired by expound, backed by metosin/virhe
Errors for Developers
Ben Brinkerhoff
• malli-powered code checking: https://github.com/teknql/aave
• Add support schematized defn and fn
• Emit clj-kondo type annotations
• Schemas for Schemas AST
• Test utilities
MoreTooling
Ryan Schukler
Michiel Borkent
Malli: inside data-driven schemas
• Pre-alpha, still experimenting, but core is 90% code complete
• Was public announcement by the community long time ago
• Many active contributors and some users too
• Big thanks to all people and libraries for source of innovation
• Goal to get official release out in a month or two
• Learned a lot, has been fun to develop
Current Status
• Understand and manage your expectations
• Clojure is awesome tool for building data-driven systems
• Malli is a fresh new schema library for Clojure/Script, try it out
• If you’re interested in type and schema systems, consider contributing
• https://github.com/metosin/malli
• #malli on slack
Takeaways
Questions?
Tommi Reiman
tommi@metosin.fi
@ikitommi
https://www.github.com/metosin/malli
malli.io
Multi-Schemas
(def MultiSchema
[:multi {:dispatch :type}
[:sized [:map
[:type [12 :sized]]
[:size int?]]]
[:human [:map
[:type [12 :human]]
[:name string?]]]])
(m/validate MultiSchema {:type :sized, :size 10})
; '( true
(m/validate MultiSchema {:type :human, :name “Tiina"})
; '( true
Multi-Schemas
(def MultiSchema
[:multi {:dispatch 'first}
[:sized [:tuple [12 :sized] [:map [:size int?]]]]
[:human [:tuple [12 :human] [:map [:name string?]]]]])
(m/validate MultiSchema [:sized {:size 10}])
; '( true
(m/validate MultiSchema [:human {:name "Tiina"}])
; '( true

More Related Content

What's hot

JSON-LD: JSON for the Social Web
JSON-LD: JSON for the Social WebJSON-LD: JSON for the Social Web
JSON-LD: JSON for the Social Web
Gregg Kellogg
 
How to Lock Down Apache Kafka and Keep Your Streams Safe
How to Lock Down Apache Kafka and Keep Your Streams SafeHow to Lock Down Apache Kafka and Keep Your Streams Safe
How to Lock Down Apache Kafka and Keep Your Streams Safe
confluent
 
JSON-LD and MongoDB
JSON-LD and MongoDBJSON-LD and MongoDB
JSON-LD and MongoDB
Gregg Kellogg
 
Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)
Niels de Bruijn
 
With events to a modern integration architecture
With events to a modern integration architectureWith events to a modern integration architecture
With events to a modern integration architecture
confluent
 
Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...
Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...
Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...
HostedbyConfluent
 
JSON-LD for RESTful services
JSON-LD for RESTful servicesJSON-LD for RESTful services
JSON-LD for RESTful services
Markus Lanthaler
 
Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...
Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...
Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...
AWSKRUG - AWS한국사용자모임
 
AWS Elastic Beanstalk - Running Microservices and Docker
AWS Elastic Beanstalk - Running Microservices and DockerAWS Elastic Beanstalk - Running Microservices and Docker
AWS Elastic Beanstalk - Running Microservices and Docker
Amazon Web Services
 
Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...
Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...
Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...
confluent
 
Elasticsearch
ElasticsearchElasticsearch
Elasticsearch
Hermeto Romano
 
Creating a Context-Aware solution, Complex Event Processing with FIWARE Perseo
Creating a Context-Aware solution, Complex Event Processing with FIWARE PerseoCreating a Context-Aware solution, Complex Event Processing with FIWARE Perseo
Creating a Context-Aware solution, Complex Event Processing with FIWARE Perseo
Fernando Lopez Aguilar
 
JSON-LD: JSON for Linked Data
JSON-LD: JSON for Linked DataJSON-LD: JSON for Linked Data
JSON-LD: JSON for Linked Data
Gregg Kellogg
 
AWS Black Belt Techシリーズ Amazon SNS / Amazon SQS
AWS Black Belt Techシリーズ Amazon SNS / Amazon SQSAWS Black Belt Techシリーズ Amazon SNS / Amazon SQS
AWS Black Belt Techシリーズ Amazon SNS / Amazon SQS
Amazon Web Services Japan
 
Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...
Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...
Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...
HostedbyConfluent
 
Building secure applications with keycloak
Building secure applications with keycloak Building secure applications with keycloak
Building secure applications with keycloak
Abhishek Koserwal
 
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon Web Services Korea
 
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in ProductionKong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
FIWARE
 
KSQL Intro
KSQL IntroKSQL Intro
KSQL Intro
confluent
 
Location Analytics - Real-Time Geofencing using Apache Kafka
Location Analytics - Real-Time Geofencing using Apache KafkaLocation Analytics - Real-Time Geofencing using Apache Kafka
Location Analytics - Real-Time Geofencing using Apache Kafka
Guido Schmutz
 

What's hot (20)

JSON-LD: JSON for the Social Web
JSON-LD: JSON for the Social WebJSON-LD: JSON for the Social Web
JSON-LD: JSON for the Social Web
 
How to Lock Down Apache Kafka and Keep Your Streams Safe
How to Lock Down Apache Kafka and Keep Your Streams SafeHow to Lock Down Apache Kafka and Keep Your Streams Safe
How to Lock Down Apache Kafka and Keep Your Streams Safe
 
JSON-LD and MongoDB
JSON-LD and MongoDBJSON-LD and MongoDB
JSON-LD and MongoDB
 
Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)
 
With events to a modern integration architecture
With events to a modern integration architectureWith events to a modern integration architecture
With events to a modern integration architecture
 
Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...
Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...
Highly Available Kafka Consumers and Kafka Streams on Kubernetes with Adrian ...
 
JSON-LD for RESTful services
JSON-LD for RESTful servicesJSON-LD for RESTful services
JSON-LD for RESTful services
 
Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...
Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...
Athena & Step Function 으로 통계 파이프라인 구축하기 - 변규현 (당근마켓) :: AWS Community Day Onl...
 
AWS Elastic Beanstalk - Running Microservices and Docker
AWS Elastic Beanstalk - Running Microservices and DockerAWS Elastic Beanstalk - Running Microservices and Docker
AWS Elastic Beanstalk - Running Microservices and Docker
 
Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...
Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...
Kafka Summit NYC 2017 - Singe Message Transforms are not the Transformations ...
 
Elasticsearch
ElasticsearchElasticsearch
Elasticsearch
 
Creating a Context-Aware solution, Complex Event Processing with FIWARE Perseo
Creating a Context-Aware solution, Complex Event Processing with FIWARE PerseoCreating a Context-Aware solution, Complex Event Processing with FIWARE Perseo
Creating a Context-Aware solution, Complex Event Processing with FIWARE Perseo
 
JSON-LD: JSON for Linked Data
JSON-LD: JSON for Linked DataJSON-LD: JSON for Linked Data
JSON-LD: JSON for Linked Data
 
AWS Black Belt Techシリーズ Amazon SNS / Amazon SQS
AWS Black Belt Techシリーズ Amazon SNS / Amazon SQSAWS Black Belt Techシリーズ Amazon SNS / Amazon SQS
AWS Black Belt Techシリーズ Amazon SNS / Amazon SQS
 
Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...
Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...
Reigning in Protobuf with David Navalho and Graham Stirling | Kafka Summit Lo...
 
Building secure applications with keycloak
Building secure applications with keycloak Building secure applications with keycloak
Building secure applications with keycloak
 
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
 
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in ProductionKong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
 
KSQL Intro
KSQL IntroKSQL Intro
KSQL Intro
 
Location Analytics - Real-Time Geofencing using Apache Kafka
Location Analytics - Real-Time Geofencing using Apache KafkaLocation Analytics - Real-Time Geofencing using Apache Kafka
Location Analytics - Real-Time Geofencing using Apache Kafka
 

Similar to Malli: inside data-driven schemas

Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?
osfameron
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in Ruby
Jason Yeo Jie Shun
 
R Language
R LanguageR Language
R Language
ShwetDadhaniya1
 
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
Georg Sorst
 
Let's build a parser!
Let's build a parser!Let's build a parser!
Let's build a parser!
Boy Baukema
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
Domenic Denicola
 
A Rusty introduction to Apache Arrow and how it applies to a time series dat...
A Rusty introduction to Apache Arrow and how it applies to a  time series dat...A Rusty introduction to Apache Arrow and how it applies to a  time series dat...
A Rusty introduction to Apache Arrow and how it applies to a time series dat...
Andrew Lamb
 
What you forgot from your Computer Science Degree
What you forgot from your Computer Science DegreeWhat you forgot from your Computer Science Degree
What you forgot from your Computer Science Degree
Stephen Darlington
 
A miało być tak... bez wycieków
A miało być tak... bez wyciekówA miało być tak... bez wycieków
A miało być tak... bez wycieków
Konrad Kokosa
 
R programming language
R programming languageR programming language
R programming language
Alberto Minetti
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applications
Skills Matter
 
MongoDB Analytics
MongoDB AnalyticsMongoDB Analytics
MongoDB Analytics
datablend
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick tour
aztack
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio Akita
iMasters
 
Complex Values
Complex ValuesComplex Values
Complex Values
ESUG
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
Movel
 
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
eddiebaggott
 
Elasticsearch intro output
Elasticsearch intro outputElasticsearch intro output
Elasticsearch intro output
Tom Chen
 
Scalding big ADta
Scalding big ADtaScalding big ADta
Scalding big ADta
b0ris_1
 
RDataMining slides-r-programming
RDataMining slides-r-programmingRDataMining slides-r-programming
RDataMining slides-r-programming
Yanchang Zhao
 

Similar to Malli: inside data-driven schemas (20)

Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in Ruby
 
R Language
R LanguageR Language
R Language
 
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
 
Let's build a parser!
Let's build a parser!Let's build a parser!
Let's build a parser!
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
A Rusty introduction to Apache Arrow and how it applies to a time series dat...
A Rusty introduction to Apache Arrow and how it applies to a  time series dat...A Rusty introduction to Apache Arrow and how it applies to a  time series dat...
A Rusty introduction to Apache Arrow and how it applies to a time series dat...
 
What you forgot from your Computer Science Degree
What you forgot from your Computer Science DegreeWhat you forgot from your Computer Science Degree
What you forgot from your Computer Science Degree
 
A miało być tak... bez wycieków
A miało być tak... bez wyciekówA miało być tak... bez wycieków
A miało być tak... bez wycieków
 
R programming language
R programming languageR programming language
R programming language
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applications
 
MongoDB Analytics
MongoDB AnalyticsMongoDB Analytics
MongoDB Analytics
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick tour
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio Akita
 
Complex Values
Complex ValuesComplex Values
Complex Values
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
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
 
Elasticsearch intro output
Elasticsearch intro outputElasticsearch intro output
Elasticsearch intro output
 
Scalding big ADta
Scalding big ADtaScalding big ADta
Scalding big ADta
 
RDataMining slides-r-programming
RDataMining slides-r-programmingRDataMining slides-r-programming
RDataMining slides-r-programming
 

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 Saari
Metosin 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 report
Metosin Oy
 
Naked Performance With Clojure
Naked Performance With ClojureNaked Performance With Clojure
Naked Performance With Clojure
Metosin Oy
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
Metosin 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 Tampere
Metosin 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 & Clojure
Metosin Oy
 
Performance and Abstractions
Performance and AbstractionsPerformance and Abstractions
Performance and Abstractions
Metosin Oy
 
ClojuTRE2016 Opening slides
ClojuTRE2016 Opening slidesClojuTRE2016 Opening slides
ClojuTRE2016 Opening slides
Metosin 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.2016
Metosin Oy
 
ClojuTRE - a (very) brief history
ClojuTRE - a (very) brief historyClojuTRE - a (very) brief history
ClojuTRE - a (very) brief history
Metosin 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 2016
Metosin 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 awesome
Metosin 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.2014
Metosin 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 awesome
Metosin Oy
 
Swaggered web apis in Clojure
Swaggered web apis in ClojureSwaggered web apis in Clojure
Swaggered web apis in Clojure
Metosin Oy
 

More from Metosin Oy (19)

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
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
 
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

Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
Tatiana Al-Chueyr
 
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
Priyanka Aash
 
How to build a generative AI solution A step-by-step guide (2).pdf
How to build a generative AI solution A step-by-step guide (2).pdfHow to build a generative AI solution A step-by-step guide (2).pdf
How to build a generative AI solution A step-by-step guide (2).pdf
ChristopherTHyatt
 
Data Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining DataData Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining Data
Safe Software
 
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly DetectionAdvanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
Bert Blevins
 
Salesforce AI & Einstein Copilot Workshop
Salesforce AI & Einstein Copilot WorkshopSalesforce AI & Einstein Copilot Workshop
Salesforce AI & Einstein Copilot Workshop
CEPTES Software Inc
 
WPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide DeckWPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide Deck
Lidia A.
 
Calgary MuleSoft Meetup APM and IDP .pptx
Calgary MuleSoft Meetup APM and IDP .pptxCalgary MuleSoft Meetup APM and IDP .pptx
Calgary MuleSoft Meetup APM and IDP .pptx
ishalveerrandhawa1
 
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
bhumivarma35300
 
Scaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - Mydbops
Scaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - MydbopsScaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - Mydbops
Scaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - Mydbops
Mydbops
 
Applying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAI
Applying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAIApplying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAI
Applying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAI
ssuserd4e0d2
 
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Bert Blevins
 
Acumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdf
Acumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdfAcumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdf
Acumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdf
BrainSell Technologies
 
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
Edge AI and Vision Alliance
 
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
aslasdfmkhan4750
 
The Evolution of Remote Server Management
The Evolution of Remote Server ManagementThe Evolution of Remote Server Management
The Evolution of Remote Server Management
Bert Blevins
 
How Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdfHow Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdf
HackersList
 
ARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdf
ARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdfARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdf
ARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdf
Inglês no Mundo Digital
 
Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...
chetankumar9855
 
How to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptxHow to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptx
Adam Dunkels
 

Recently uploaded (20)

Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
 
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
 
How to build a generative AI solution A step-by-step guide (2).pdf
How to build a generative AI solution A step-by-step guide (2).pdfHow to build a generative AI solution A step-by-step guide (2).pdf
How to build a generative AI solution A step-by-step guide (2).pdf
 
Data Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining DataData Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining Data
 
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly DetectionAdvanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
 
Salesforce AI & Einstein Copilot Workshop
Salesforce AI & Einstein Copilot WorkshopSalesforce AI & Einstein Copilot Workshop
Salesforce AI & Einstein Copilot Workshop
 
WPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide DeckWPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide Deck
 
Calgary MuleSoft Meetup APM and IDP .pptx
Calgary MuleSoft Meetup APM and IDP .pptxCalgary MuleSoft Meetup APM and IDP .pptx
Calgary MuleSoft Meetup APM and IDP .pptx
 
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
 
Scaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - Mydbops
Scaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - MydbopsScaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - Mydbops
Scaling Connections in PostgreSQL Postgres Bangalore(PGBLR) Meetup-2 - Mydbops
 
Applying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAI
Applying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAIApplying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAI
Applying Retrieval-Augmented Generation (RAG) to Combat Hallucinations in GenAI
 
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
 
Acumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdf
Acumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdfAcumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdf
Acumatica vs. Sage Intacct vs. NetSuite _ NOW CFO.pdf
 
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
 
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
 
The Evolution of Remote Server Management
The Evolution of Remote Server ManagementThe Evolution of Remote Server Management
The Evolution of Remote Server Management
 
How Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdfHow Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdf
 
ARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdf
ARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdfARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdf
ARTIFICIAL INTELLIGENCE (AI) IN MUSIC.pdf
 
Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...
 
How to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptxHow to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptx
 

Malli: inside data-driven schemas

  • 6. • Data-oriented - represent entities and their relationships as data. • Data-driven - create DSLs in data structures and write interpreters for them Clojure <3 Data https:!"clojureverse.org/t/clojure-a-pragmatic-data-driven-language/4565/5Eric Normand
  • 8. It’s just data! ;; restaurant {:name "Lie Mi" :tags #{:street :vietnamese} :stars 4.3 :address {:street "Hämeenkatu 14" :city “Tampere"}}
  • 9. It’s just data! {:type :restaurant :name "Lie Mi" :tags #{:street :vietnamese} :stars 4.3 :address {:street "Hämeenkatu 14" :city “Tampere"}}
  • 10. It’s just data! {:type :customers.1234/restaurant :name "Lie Mi" :tags #{:street :vietnamese} :stars 4.3 :address {:street "Hämeenkatu 14" :city “Tampere"}}
  • 11. It’s just data! {:mydomain/type :mydomain.types/restaurant :mydomain.restaurant/name "Lie Mi" :mydomain.restaurant/tags #$:street :vietnamese} :mydomain.restaurant/stars 4.3 :mydomain.restaurant/address {:mydomain.address/street "Hämeenkatu 14" :mydomain.address/city "Tampere"}}
  • 12. It’s just data! {:type :restaurant :name "Lie Mi" :tags #{:street :vietnamese} :stars 4.3 :address {:street "Hämeenkatu 14” :city "Tampere"}}
  • 13. It’s just data! (-> {:type :restaurant :name "Lie Mi" :tags #{:street :vietnamese} :stars 4.3 :address {:street "Hämeenkatu 14" :city "Tampere"}}) (select-keys [:name :tags :address])) (assoc-in [:address :zip] 33100)) ;{:name "Lie Mi" ; :tags #{:vietnamese :street} ; :address {:street "Hämeenkatu 14" ; :city "Tampere" ; :zip 33100}}
  • 15. Types, Schemas and Specs Malcolm 16:45 Awesome! Awesome! Awesome!
  • 16. One tool for everything?
  • 17. Expectations We are building dynamic multi-tenant systems where data- models should be data too: they should drive the runtime value transformations, forms and processes.We should be able to edit the models at runtime, persist them and load them back from database and over the wire, for both Clojure and ClojureScript. Think of JSON Schema, but for EDN and Clojure/Script.
  • 18. If you have expectations (of others) that aren't being met, those expectations are your own responsibility.You are responsible for your own needs. If you want things, make them. - Rich Hickey https:!"gist.github.com/richhickey/1563cddea1002958f96e7ba9519972d9
  • 20. The Idea • Schemas as data (hiccup, reagent, internal.*, reitit) • Take the best parts of Plumatic Schema, clojure.spec & JSON Schema • Programming with Schemas, first class meta-data • Focus on Developer Experience • Small core, extendable • Create a Prototype, experiment, have fun
  • 22. Syntax (Schema AST) [:vector {:min 0, :max 10} int?] type %& [type ?properties & children] {:type :vector :properties {:min 0, :max 10} :children [int?]}
  • 23. Schemas int? [:= 43] [:tuple double? double?] [:and int? [:> 18]] [:map [:x int?] [:y int?]] AST '( (resolve) '( IntoSchema opts '( Schema
  • 24. Validation (require '[malli.core :as m]) (m/validate int? 1) ; => true (m/validate int? "kikka") ; => false (m/validate [:maybe keyword?] nil) ; => true (m/validate [:vector int?] [1 2 3]) ; => true
  • 25. Complex Schema (def CompositeMap [:and [:map {:closed true} [:x pos-int?] [:y pos-int?]] [:fn {:error/message "x )* y"} (fn [{:keys [x y]}] (> x y))]]) (m/validate CompositeMap {:x 3, :y 2}) ; '( true (m/validate CompositeMap {:x 1, :y 2}) ; '( false
  • 26. Complex Schema (def CompositeMap [:and [:map {:closed true} [:x pos-int?] [:y pos-int?]] [:fn {:error/message "x )* y"} '(fn [{:keys [x y]}] (> x y))]]) (m/validate CompositeMap {:x 3, :y 2}) ; '( true (m/validate CompositeMap {:x 1, :y 2}) ; '( falseMichiel Borkent
  • 27. Forms (def CompositeMap [:and [:map {:closed true} [:x pos-int?] [:y pos-int?]] [:fn {:error/message "x )* y"} '(fn [{:keys [x y]}] (> x y))]]) (m/form CompositeMap) ;[:and ; [:map {:closed true} ; [:x pos-int?] ; [:y pos-int?]] ; [:fn {:error/message "x )* y"} ; (fn [{:keys [x y]}] (> x y))]]
  • 28. • Works on all of JVM, ClojureScript & GraalVM Durable Schemas Michiel Borkent (require '[malli.edn :as edn]) (+, CompositeMap (edn/write-string) (edn/read-string) (m/validate {:x 3, :y 2})) ; '( true
  • 29. • Inspired by clojure.spec Explaining Data (m/explain CompositeMap {:x -1, :y -2, :EXTRA true}) ;{:schema …, ; :value {:x -1, :y -2, :EXTRA true}, ; :errors [{:path [1 2 1], :in [:x], :schema pos-int?, :value -1} ; {:path [1 3 1], :in [:y], :schema pos-int?, :value -2} ; {:path [1], :in [:EXTRA], :schema …, :type :malli.core/extra-key}]} AlexRich
  • 30. Errors for Humans (require '[malli.error :as me]) (+, CompositeMap (m/explain {:x -3, :y -2, :EXTRA true}) (me/humanize)) ;{:x ["should be positive int"] ; :y ["should be positive int"] ; :EXTRA ["disallowed key"] ; :malli/error ["x )* y"]} Alexander Kiel
  • 31. GeneratingValues (require '[malli.generator :as mg]) (mg/generate keyword?) ; '( :? (mg/generate [:enum "a" "b" "c"] {:seed 42}) ; '( "a" (mg/generate [:re #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9-.]+.[a-zA-Z]{2,63}$"] {:seed 42, :size 10}) ; '( "CaR@MavCk70OHiX.yZ"
  • 32. GeneratingValues (mg/generate [:and {:gen/elements ["kikka" "kukka" "kakka"]} string?]) ; '( "kikka" (mg/generate [:and {:gen/fmap '(partial str "kikka_")} string?] {:seed 10, :size 10}) /0 '( "kikka_WT3K0yax2" (require '[clojure.test.check.generators :as gen]) (mg/generate [:sequential {:gen/gen (gen/list gen/neg-int)} int?] {:size 42, :seed 42}) ; '( (-37 -13 -13 -24 -20 -11 -34 -40 -22 0 -10) Gary Frederics
  • 33. Inferring Schemas (def lie-mi {:type :restaurant :name "Lie Mi" :tags #$:street :vietnamese} :stars 4.3 :address {:street "Hämeenkatu 14" :city "Tampere"}}) (def wanha-tappi {:type :restaurant :name "Wanha Tappi" :tags #$:burgers :beer} :address {:street "Jokipohjantie 18" :city "Tampere"}}) Stathis Sideris (require '[malli.provider :as mp]) (def Restaurant (mp/provide [lie-mi wanha-tappi])) Restaurant ;[:map ; [:type keyword?] ; [:name string?] ; [:tags [:set keyword?]] ; [:stars {:optional true} double?] ; [:address ; [:map ; [:street string?] ; [:city string?]]]]
  • 34. Programming with Schemas (require '[malli.util :as mu]) (+, [:map [:a int?] [:b string?] [:c [:map [:d int?] [:e keyword?]]]] (mu/closed-schema) (mu/select-keys [:a :c]) (mu/update-in [:c] mu/dissoc :e)) ;[:map {:closed true} ; [:a int?] ; [:c [:map {:closed true} ; [:d int?]]]] Metosin
  • 35. Walking over Schemas • Generic schema walking using theVisitor-pattern (CLJ-2251) • To JSON Schema, Swagger2, Map-syntax etc. (require '[malli.json-schema :as json-schema]) (json-schema/transform [:map {:title "a map"} [:x int?] [:y {:optional true} inst?]]) ;{:type "object" ; :title "a map" ; :properties {:x {:type "integer", :format "int64"} ; :y {:type "string", :format "date-time"} ; :required [:x]}
  • 36. Walking over Schemas (defn closed-schema "Closes recursively all :map schemas by adding `{:closed true}` property, unless schema explicitely open with `{:closed false}`" ([schema] (closed-schema schema nil)) ([schema options] (m/accept schema (m/schema-visitor (fn [schema] (if (-open-map? schema options) (update-properties schema c/assoc :closed true) schema))))))
  • 38. • Open Schemas to embrace growth (and typing errors) • Closed Schemas and Spell Checking to the rescue? Spell Checking (def nante-eck {:type :restaurant :name "Nante-Eck" :tags #$:traditional :vegan} :starz 4.2 :address {:streez "Unter den Linden 35" :city "Berlin"}}) Restaurant ;[:map ; [:type keyword?] ; [:name string?] ; [:tags [:set keyword?]] ; [:stars {:optional true} double?] ; [:address ; [:map ; [:street string?] ; [:city string?]]]]
  • 39. Spell Checking (+, Restaurant (m/explain nante-eck) (me/humanize)) ; {:address {:street ["missing required key"]}} (+, Restaurant (mu/closed-schema) (m/explain nante-eck) (me/humanize)) ;{:address {:street ["missing required key"] ; :streez ["disallowed key"]} ; :starz ["disallowed key"]} (+, Restaurant (mu/closed-schema) (m/explain nante-eck) (me/with-spell-checking) (me/humanize)) ;{:address {:streez ["should be spelled :street"]} ; :starz ["should be spelled :stars"]} Bruce Hauman
  • 40. • Fully re-written engine, built with interceptors • Encode and decode chains with enter & leave phases • Json, string, strip-extra-keys & default-value-transformer • Schemas can define transformation via properties • Fast ValueTransformers (m/decode int? "42" (mt/string-transformer)) ; '( 42 (m/encode int? 42 (mt/string-transformer)) ; '( ”42”
  • 41. (require '[malli.transform :as mt]) (def json-transformer (mt/transformer (mt/strip-extra-keys-transformer) (mt/json-transformer) (mt/default-value-transformer))) (def json+,Restaurant (m/decoder Restaurant json-transformer)) (json+,Restaurant {:type "restaurant" :DARK "ORKO" :name "Mustafas Gemüse Kebab" :tags ["kebab" "yoghurt"] :address {:street "Mehringdamm 32" :EXTRA "KEY" :city "Berlin"}}) ;{:type :restaurant, ; :name "Mustafas Gemüse Kebab", ; :tags #$:kebab :yoghurt}, ; :address {:street "Mehringdamm 32" ; :city "Berlin"}}
  • 42. (require '[criterium.core :as cc]) /0 1.8µs (cc/quick-bench (+, json (update :type keyword) (update :tags (comp set (partial map keyword))) (select-keys [:type :name :tags :address]) (update :address select-keys [:street :city]))) /0 1.9µs (cc/quick-bench (json+,Restaurant json)) (def json+,Order (m/decoder [:map [:id int?] [:tags string?] [:address [:map [:street string?] [:zip string?] [:country string?]]]] (mt/json-transformer))) json+,Order ; '( #object[clojure.core$identity]
  • 43. (require '[criterium.core :as cc]) /0 1.8µs (cc/quick-bench (+, json (update :type keyword) (update :tags (comp set (partial map keyword))) (select-keys [:type :name :tags :address]) (update :address select-keys [:street :city]))) /0 1.9µs (cc/quick-bench (json+,Restaurant json)) (def json+,Order (m/decoder [:map [:id int?] [:tags [:vector string?]] [:address [:map [:street string?] [:zip string?] [:country string?]]]] (mt/json-transformer))) json+,Order ; '( #object[clojure.core$identity]
  • 44. (require '[criterium.core :as cc]) /0 1.8µs (cc/quick-bench (+, json (update :type keyword) (update :tags (comp set (partial map keyword))) (select-keys [:type :name :tags :address]) (update :address select-keys [:street :city]))) /0 1.9µs (cc/quick-bench (json+,Restaurant json)) (def json+,Order (m/decoder [:map [:id int?] [:tags [:vector string?]] [:address [:map [:street string?] [:zip string?] [:country string?]]]] (mt/json-transformer))) json+,Order ; '( #object[clojure.core$identity]
  • 46. • reitit-malli coercion module, since 0.4.0 • Orders of magnitude faster coercion than with reitit-spec • Small example application: https://github.com/metosin/reitit/tree/ master/examples/ring-malli-swagger • A new module & configuration system? reitit + malli
  • 47. • … and custom Schemas to inline external stuff, maybe like: Schema providers (F#) (m/validate [:json-schema {:type "object" :properties {:x {:type "integer", :format "int64"} :y {:type "integer", :format "int64"}} :required [:x]}] {:x 1, :y 2}) ; => true
  • 48. • Have generated forms in four decades, just one more time ;) • Good companion for FSMs and rule engines, rapid prototyping • https://www.youtube.com/watch?v=IekPZpfbdaI • https://github.com/domino-clj + malli Generating UIs Dmitri Carmen Nikola Schema '( UI %& Schema UI-Schema '( UI
  • 49. • Inspired by expound, backed by metosin/virhe Errors for Developers Ben Brinkerhoff
  • 50. • malli-powered code checking: https://github.com/teknql/aave • Add support schematized defn and fn • Emit clj-kondo type annotations • Schemas for Schemas AST • Test utilities MoreTooling Ryan Schukler Michiel Borkent
  • 52. • Pre-alpha, still experimenting, but core is 90% code complete • Was public announcement by the community long time ago • Many active contributors and some users too • Big thanks to all people and libraries for source of innovation • Goal to get official release out in a month or two • Learned a lot, has been fun to develop Current Status
  • 53. • Understand and manage your expectations • Clojure is awesome tool for building data-driven systems • Malli is a fresh new schema library for Clojure/Script, try it out • If you’re interested in type and schema systems, consider contributing • https://github.com/metosin/malli • #malli on slack Takeaways
  • 55. Multi-Schemas (def MultiSchema [:multi {:dispatch :type} [:sized [:map [:type [12 :sized]] [:size int?]]] [:human [:map [:type [12 :human]] [:name string?]]]]) (m/validate MultiSchema {:type :sized, :size 10}) ; '( true (m/validate MultiSchema {:type :human, :name “Tiina"}) ; '( true
  • 56. Multi-Schemas (def MultiSchema [:multi {:dispatch 'first} [:sized [:tuple [12 :sized] [:map [:size int?]]]] [:human [:tuple [12 :human] [:map [:name string?]]]]]) (m/validate MultiSchema [:sized {:size 10}]) ; '( true (m/validate MultiSchema [:human {:name "Tiina"}]) ; '( true